diff --git a/.all-contributorsrc b/.all-contributorsrc deleted file mode 100644 index bfc0ca79..00000000 --- a/.all-contributorsrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "projectName": "xeofs", - "projectOwner": "nicrie" -} diff --git a/.github/workflows/black_formatting.yml b/.github/workflows/black_formatting.yml deleted file mode 100644 index 85a9ce92..00000000 --- a/.github/workflows/black_formatting.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Code Formatting Check - -on: - pull_request: - branches: [main, develop] - types: [opened, synchronize, reopened, edited] - workflow_dispatch: # Allows you to run this workflow manually from the Actions tab - - -jobs: - black_formatting: - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v3 - - name: Check Code Formatting with Black - uses: psf/black@stable - with: - src: "./xeofs" - version: "~= 23.7.0" \ No newline at end of file diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 2f4b18fb..15dc6e16 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -13,7 +13,7 @@ jobs: fetch-depth: 0 - uses: BobAnkh/auto-generate-changelog@v1.2.5 with: - REPO_NAME: 'nicrie/xeofs' + REPO_NAME: 'xarray-contrib/xeofs' ACCESS_TOKEN: ${{ secrets.CHANGELOG_TOKEN }} PATH: 'CHANGELOG.md' COMMIT_MESSAGE: 'docs(CHANGELOG): update release notes' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7bd81ca5..1d2f743b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,51 +8,40 @@ on: types: [opened, synchronize, reopened, edited] workflow_dispatch: # Allows you to run this workflow manually from the Actions tab -jobs: - - Code_Quality_Check: +jobs: + test: + name: py${{ matrix.versions.python-version }} ${{ matrix.versions.resolution }} runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10', 3.11] + versions: + - python-version: '3.10' + resolution: lowest-direct + - python-version: '3.11' + resolution: highest + - python-version: '3.12' + resolution: highest steps: - - name: Checkout Repository - uses: actions/checkout@v3 - - - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} + - uses: actions/checkout@v4 - - name: Setup Poetry - uses: abatilo/actions-poetry@v2.1.0 + - name: Setup Python ${{ matrix.versions.python-version }} + uses: actions/setup-python@v5 with: - poetry-version: 1.5.1 + python-version: ${{ matrix.versions.python-version }} - - name: Configure Poetry Settings - shell: bash - run: python -m poetry config virtualenvs.in-project true - - - name: Verify Poetry Version - run: poetry --version - - - name: Install Project Dependencies - run: python -m poetry install --with dev - - - name: Lint Codebase with flake8 + - name: Install dependencies run: | - python -m poetry run flake8 . --exclude .venv --count --select=E9,F63,F7,F82 --show-source --statistics - python -m poetry run flake8 . --exclude .venv --count --exit-zero --max-complexity=10 --max-line-length=79 --statistics + pip install uv + uv pip install . -r pyproject.toml --system --extra dev --resolution ${{ matrix.versions.resolution }} - - name: Execute Tests with pytest and Coverage + - name: Execute Tests run: | - python -m poetry run coverage run -m pytest - python -m poetry run coverage report -m - python -m poetry run coverage xml + coverage run -m pytest -n auto --doctest-glob="README.md" + coverage report -m + coverage xml - name: Upload Coverage Report to Codecov uses: codecov/codecov-action@v3 with: files: ./coverage.xml - diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml new file mode 100644 index 00000000..54149bdc --- /dev/null +++ b/.github/workflows/formatting.yml @@ -0,0 +1,27 @@ +name: Formatting + +on: + pull_request: + branches: [main, develop] + types: [opened, synchronize, reopened, edited] + workflow_dispatch: # Allows you to run this workflow manually from the Actions tab + + +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ruff + # Update output format to enable automatic inline annotations. + - name: Run Ruff + run: | + ruff check + ruff format --check diff --git a/.github/workflows/pull-request-linting.yml b/.github/workflows/pull-request-linting.yml index 9616f09b..c71bee4a 100644 --- a/.github/workflows/pull-request-linting.yml +++ b/.github/workflows/pull-request-linting.yml @@ -5,15 +5,15 @@ # Aim: ensure that PR title matches the concentional commits spec # More info: https://github.com/marketplace/actions/semantic-pull-request -name: "Pull Request Linting" +name: "PR Linting" on: pull_request_target: types: [opened, edited, synchronize] jobs: - PR_Validation: - name: Validate Pull Request Title + validate: + name: validate conventional commit in title runs-on: ubuntu-latest steps: - name: Run Semantic Pull Request Linting diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6a92770f..fd0494ab 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,19 +1,21 @@ repos: -# - repo: ... - + # Conventional Commits - repo: https://github.com/compilerla/conventional-pre-commit rev: v1.2.0 hooks: - id: conventional-pre-commit stages: [commit-msg] args: [] # optional: list of Conventional Commits types to allow - - repo: https://github.com/psf/black - rev: 23.7.0 + # Lint and format with ruff + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.4 + hooks: + - id: ruff + args: [ --fix ] + - id: ruff-format + # Strip output from Jupyter Notebooks + - repo: https://github.com/kynan/nbstripout + rev: 0.6.1 hooks: - - id: black - # It is recommended to specify the latest version of Python - # supported by your project here, or alternatively use - # pre-commit's default_language_version, see - # https://pre-commit.com/#top_level-default_language_version - language_version: python3.11 \ No newline at end of file + - id: nbstripout \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1459388a..7b39d95a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,198 +2,323 @@ +## v2.3.2 (2024-03-30) + +### Fix + +* fix: handle indexing changes in new xarray versions (#159) ([`7d07d30`](https://github.com/xarray-contrib/xeofs/commit/7d07d30690523b3ba844a5e0b388cdeb9eb1ce02)) + + +## v2.3.1 (2024-02-28) + +### Build + +* build: constrain xarray version (#155) ([`8158657`](https://github.com/xarray-contrib/xeofs/commit/8158657fd837407c64e01969317aea39d1f192d7)) + +### Chore + +* chore(release): v2.3.1 ([`a3cb204`](https://github.com/xarray-contrib/xeofs/commit/a3cb204171dbbd1f09f2c083099cf3b67f625495)) + +### Fix + +* fix: correct inverse transform of unseen scores (#154) ([`5f0f7a5`](https://github.com/xarray-contrib/xeofs/commit/5f0f7a5593da5ce266b1e951f0d632cfe51b311c)) + + +## v2.3.0 (2024-02-04) + +### Chore + +* chore(release): v2.3.0 ([`1f54401`](https://github.com/xarray-contrib/xeofs/commit/1f54401f01ca7ad6760422eb300e696f12976d4c)) + +### Feature + +* feat: support complex input data (#152) ([`c6ce4e1`](https://github.com/xarray-contrib/xeofs/commit/c6ce4e171399f774f7d49dd40b59fa5477b38e8d)) + + +## v2.2.6 (2024-02-04) + +### Chore + +* chore(release): v2.2.6 ([`66b31fb`](https://github.com/xarray-contrib/xeofs/commit/66b31fbeb111dd8b41b9a0cdcc7ca26b498dcf24)) + +### Fix + +* fix: inverse_transform fails with single mode and normalized pcs (#151) ([`9ea7547`](https://github.com/xarray-contrib/xeofs/commit/9ea7547c5f5b60722f675b1dab776a507da9b9e1)) + + +## v2.2.5 (2024-01-28) + +### Chore + +* chore(release): v2.2.5 ([`b5d04cc`](https://github.com/xarray-contrib/xeofs/commit/b5d04ccb0279ed9b0661ccaa6dc0183ecacc9eef)) + +### Documentation + +* docs: update xeofs citation (#145) ([`4cf84cf`](https://github.com/xarray-contrib/xeofs/commit/4cf84cfc0c99e790e53b183370ca9edfdbdd01c5)) + +* docs: add CITATION.cff (#144) ([`787c598`](https://github.com/xarray-contrib/xeofs/commit/787c5982111eaa046e697a63aaa7b71180452314)) + +### Fix + +* fix: incorrect explained variance in CCA (#147) ([`f825c68`](https://github.com/xarray-contrib/xeofs/commit/f825c68c885a14d546165f95ea2ca5ff7f5c6f4b)) + + +## v2.2.4 (2023-12-23) + +### Build + +* build: loose version constraints of dependencies (#137) ([`1a0efe1`](https://github.com/xarray-contrib/xeofs/commit/1a0efe1cbd18d5ce444a6e42eb2f290c9619dcb0)) + +### Chore + +* chore(release): v2.2.4 ([`bde4456`](https://github.com/xarray-contrib/xeofs/commit/bde445690ae0c853f5fce1c8757f0d3ea42dcc5d)) + +### Documentation + +* docs: automatically sync quickstart tutorial with codebase (#136) ([`48e63a0`](https://github.com/xarray-contrib/xeofs/commit/48e63a09579ff559908183ea2f13032886d64290)) + +* docs: use doctest to test README examples (#135) ([`382f6c7`](https://github.com/xarray-contrib/xeofs/commit/382f6c7db5496d6a8921e3044add4acc8acb75d5)) + +### Fix + +* fix: bump new release for JOSS (#143) + +Co-authored-by: Sam Levang <slevang@salientpredictions.com> ([`c3e4780`](https://github.com/xarray-contrib/xeofs/commit/c3e4780e915c2c72ecdf21739742b5b8a5ad07bd)) + + +## v2.2.3 (2023-12-18) + +### Chore + +* chore(release): v2.2.3 ([`b149477`](https://github.com/xarray-contrib/xeofs/commit/b1494771cddab30812fcdb3633f42c871034ac89)) + +### Documentation + +* docs: show contributors in readme (#140) ([`0c12fa5`](https://github.com/xarray-contrib/xeofs/commit/0c12fa5385e807e2cd45599e6fc0f10b3a520119)) + +* docs: remove all-contributor config file ([`f5234fc`](https://github.com/xarray-contrib/xeofs/commit/f5234fc3895f3bcd8893ae684ea23a0ebe001db4)) + +* docs: add required dependencies (#138) ([`7ec694f`](https://github.com/xarray-contrib/xeofs/commit/7ec694f41d6aca0509782096cbabbcd19264180a)) + +* docs: add required dependencies ([`ce6b93a`](https://github.com/xarray-contrib/xeofs/commit/ce6b93ab31da6ab10ebc70e9444f1b9956ec02b2)) + +* docs: fix link to perf scripts (#131) ([`e2b3276`](https://github.com/xarray-contrib/xeofs/commit/e2b32762bd6bb3111c973bbd571b56367a496eba)) + +* docs: Update link to contributing guide (#129) ([`21b8d3d`](https://github.com/xarray-contrib/xeofs/commit/21b8d3dd3cf46fb631f7c2fe28fdf95246cd4153)) + +* docs: show contributors in README ([`049e654`](https://github.com/xarray-contrib/xeofs/commit/049e6544637d4c396d40ffcb1b29b7a710c584de)) + +### Fix + +* fix: serialization for dataset (#139) ([`93fce38`](https://github.com/xarray-contrib/xeofs/commit/93fce38ca170b1c6c9adb32b345a4531f2db6fdf)) + +* fix: test serialization roundtrip with dataset ([`ff9a1be`](https://github.com/xarray-contrib/xeofs/commit/ff9a1bea1441e0c742ca049750352b110b6376b1)) + +* fix: handle preprocessor serialization for dataset ([`5bcdf5c`](https://github.com/xarray-contrib/xeofs/commit/5bcdf5c95cdf2d0cf4206c386268b4ffd0fed053)) + +### Unknown + +* Merge branch 'main' into contrib-rocks ([`e8ba057`](https://github.com/xarray-contrib/xeofs/commit/e8ba0571c1a2c023d9cacc07d0bc5188e6ead70a)) + +* Fix link to perf scripts ([`38ba677`](https://github.com/xarray-contrib/xeofs/commit/38ba6770a5c502708c59f4ae3000fc46fb302f4b)) + +* Update link to contributing guide ([`11c1208`](https://github.com/xarray-contrib/xeofs/commit/11c120881c9dbe93a47043be1ec87365279cd6ec)) + + ## v2.2.2 (2023-11-20) ### Chore -* chore(release): update PSR version ([`0f5524f`](https://github.com/nicrie/xeofs/commit/0f5524fddafbd5aa71df5de40006f5ace75561bf)) +* chore(release): v2.2.2 ([`a58d0ad`](https://github.com/xarray-contrib/xeofs/commit/a58d0adb8fbb27c8008189beec51161300f97277)) + +* chore(release): update PSR version ([`0f5524f`](https://github.com/xarray-contrib/xeofs/commit/0f5524fddafbd5aa71df5de40006f5ace75561bf)) * chore(release): Updated semantic-release -configuration ([`320dbcb`](https://github.com/nicrie/xeofs/commit/320dbcbb252340343fa6eaef794a8941c2fe03de)) +configuration ([`320dbcb`](https://github.com/xarray-contrib/xeofs/commit/320dbcbb252340343fa6eaef794a8941c2fe03de)) ### Fix -* fix: trigger new release ([`c79a116`](https://github.com/nicrie/xeofs/commit/c79a1160d5b27e44f82b9c8fe9a9ac808ffca895)) +* fix: trigger new release ([`c79a116`](https://github.com/xarray-contrib/xeofs/commit/c79a1160d5b27e44f82b9c8fe9a9ac808ffca895)) ## v2.2.1 (2023-11-20) ### Ci -* ci: add password input for PyPI token ([`600b43e`](https://github.com/nicrie/xeofs/commit/600b43ec432ff58ab0c0eb27799a0726801fcd1b)) +* ci: add password input for PyPI token ([`600b43e`](https://github.com/xarray-contrib/xeofs/commit/600b43ec432ff58ab0c0eb27799a0726801fcd1b)) ### Fix -* fix: trigger new release ([`58250b9`](https://github.com/nicrie/xeofs/commit/58250b948bf1d2316a589b3872a44d3d7ecb7ec9)) +* fix: trigger new release ([`58250b9`](https://github.com/xarray-contrib/xeofs/commit/58250b948bf1d2316a589b3872a44d3d7ecb7ec9)) ### Unknown * 2.2.1 -Automatically generated by python-semantic-release ([`aba57e0`](https://github.com/nicrie/xeofs/commit/aba57e0d97c792ffd5449486bb6cd10b6e534a86)) +Automatically generated by python-semantic-release ([`aba57e0`](https://github.com/xarray-contrib/xeofs/commit/aba57e0d97c792ffd5449486bb6cd10b6e534a86)) ## v2.2.0 (2023-11-20) ### Chore -* chore: release v2.2.0 (#128) ([`ef40a8a`](https://github.com/nicrie/xeofs/commit/ef40a8afa32ca5896aee75ad0cabcb943c66dfbc)) +* chore: release v2.2.0 (#128) ([`ef40a8a`](https://github.com/xarray-contrib/xeofs/commit/ef40a8afa32ca5896aee75ad0cabcb943c66dfbc)) ### Ci -* ci: specify Python Semantic Release version v8.0.0 ([`c7c79e4`](https://github.com/nicrie/xeofs/commit/c7c79e448462d96d49cec2ab903363085e5ed9d4)) +* ci: specify Python Semantic Release version v8.0.0 ([`c7c79e4`](https://github.com/xarray-contrib/xeofs/commit/c7c79e448462d96d49cec2ab903363085e5ed9d4)) -* ci: add workflow dispatch to Github Action ([`26f8345`](https://github.com/nicrie/xeofs/commit/26f834516d1aacecdffc91e425a801c2086bdcd8)) +* ci: add workflow dispatch to Github Action ([`26f8345`](https://github.com/xarray-contrib/xeofs/commit/26f834516d1aacecdffc91e425a801c2086bdcd8)) ### Documentation -* docs(CHANGELOG): update release notes ([`42b5c5e`](https://github.com/nicrie/xeofs/commit/42b5c5ebb1e98c20a98c3ab770eb94000243b6d2)) +* docs(CHANGELOG): update release notes ([`42b5c5e`](https://github.com/xarray-contrib/xeofs/commit/42b5c5ebb1e98c20a98c3ab770eb94000243b6d2)) -* docs(changelog): use PAT instead of GITHUB_TOKEN ([`fa58532`](https://github.com/nicrie/xeofs/commit/fa5853203b514146b295d9185e436295fed18c81)) +* docs(changelog): use PAT instead of GITHUB_TOKEN ([`fa58532`](https://github.com/xarray-contrib/xeofs/commit/fa5853203b514146b295d9185e436295fed18c81)) ### Feature -* feat: normalized option in inverse_transform (#124) ([`4ad2791`](https://github.com/nicrie/xeofs/commit/4ad2791d4db672c7c722ee2e5d12cf3b3a88028c)) +* feat: normalized option in inverse_transform (#124) ([`4ad2791`](https://github.com/xarray-contrib/xeofs/commit/4ad2791d4db672c7c722ee2e5d12cf3b3a88028c)) -* feat: support saving to netcdf (#123) ([`8d06153`](https://github.com/nicrie/xeofs/commit/8d06153b5de31aad3f0817979c1122250f444c57)) +* feat: support saving to netcdf (#123) ([`8d06153`](https://github.com/xarray-contrib/xeofs/commit/8d06153b5de31aad3f0817979c1122250f444c57)) -* feat: normalized option in inverse_transform ([`e7d6d90`](https://github.com/nicrie/xeofs/commit/e7d6d90d6fdcbd4575cddf3b12ebf1852dc329ef)) +* feat: normalized option in inverse_transform ([`e7d6d90`](https://github.com/xarray-contrib/xeofs/commit/e7d6d90d6fdcbd4575cddf3b12ebf1852dc329ef)) ### Fix -* fix: update to handle v8 semantic release GH action (#127) ([`5b8c6d8`](https://github.com/nicrie/xeofs/commit/5b8c6d83f10d9439b0ced8d72c06c1fb36804fe4)) +* fix: update to handle v8 semantic release GH action (#127) ([`5b8c6d8`](https://github.com/xarray-contrib/xeofs/commit/5b8c6d83f10d9439b0ced8d72c06c1fb36804fe4)) -* fix: test loaded model vs transform not scores ([`a9d6bdf`](https://github.com/nicrie/xeofs/commit/a9d6bdf21278477bb42d7a406aed6053dee9c223)) +* fix: test loaded model vs transform not scores ([`a9d6bdf`](https://github.com/xarray-contrib/xeofs/commit/a9d6bdf21278477bb42d7a406aed6053dee9c223)) ### Unknown * 2.2.0 -Automatically generated by python-semantic-release ([`901982d`](https://github.com/nicrie/xeofs/commit/901982d6df1c73b21bd222cc54f7a6e50a683d56)) +Automatically generated by python-semantic-release ([`901982d`](https://github.com/xarray-contrib/xeofs/commit/901982d6df1c73b21bd222cc54f7a6e50a683d56)) -* Merge branch 'main' into develop ([`af25e8c`](https://github.com/nicrie/xeofs/commit/af25e8cf989d5a68fa362a72062f211b9a392798)) +* Merge branch 'main' into develop ([`af25e8c`](https://github.com/xarray-contrib/xeofs/commit/af25e8cf989d5a68fa362a72062f211b9a392798)) ## v2.1.2 (2023-11-18) ### Chore -* chore: Merge branch 'main' into develop ([`607d25b`](https://github.com/nicrie/xeofs/commit/607d25bd827f849dbd40c5fb0b68ca93a95e45a5)) +* chore: Merge branch 'main' into develop ([`607d25b`](https://github.com/xarray-contrib/xeofs/commit/607d25bd827f849dbd40c5fb0b68ca93a95e45a5)) ### Documentation -* docs: reactivate CHANGELOG (#121) ([`6a4370b`](https://github.com/nicrie/xeofs/commit/6a4370b0bdfa31a679ce97b1aa7f1ab56041dbe4)) +* docs: reactivate CHANGELOG (#121) ([`6a4370b`](https://github.com/xarray-contrib/xeofs/commit/6a4370b0bdfa31a679ce97b1aa7f1ab56041dbe4)) -* docs: reactivate CHANGELOG ([`06a2014`](https://github.com/nicrie/xeofs/commit/06a201463a0cbce258cc6bde27e7fcab316980b7)) +* docs: reactivate CHANGELOG ([`06a2014`](https://github.com/xarray-contrib/xeofs/commit/06a201463a0cbce258cc6bde27e7fcab316980b7)) ### Fix -* fix: update default power iterations for improved accuracy (#122) ([`9045bc6`](https://github.com/nicrie/xeofs/commit/9045bc68f18b34df2ff88c64de9131d8d26e3e38)) +* fix: update default power iterations for improved accuracy (#122) ([`9045bc6`](https://github.com/xarray-contrib/xeofs/commit/9045bc68f18b34df2ff88c64de9131d8d26e3e38)) ### Unknown * 2.1.2 -Automatically generated by python-semantic-release ([`d80a839`](https://github.com/nicrie/xeofs/commit/d80a839dc0c301557e7ec58559197a5f40c7353d)) +Automatically generated by python-semantic-release ([`d80a839`](https://github.com/xarray-contrib/xeofs/commit/d80a839dc0c301557e7ec58559197a5f40c7353d)) ## v2.1.1 (2023-11-17) ### Chore -* chore: merge branch 'main' into develop ([`f9ef729`](https://github.com/nicrie/xeofs/commit/f9ef72920becf750f63bc8ed4f8b80f6c25593e4)) +* chore: merge branch 'main' into develop ([`f9ef729`](https://github.com/xarray-contrib/xeofs/commit/f9ef72920becf750f63bc8ed4f8b80f6c25593e4)) -* chore: fix config of all-contributor bot ([`1eedf4f`](https://github.com/nicrie/xeofs/commit/1eedf4f5c2b69f30ee45be0c110d9cca7e25ce9d)) +* chore: fix config of all-contributor bot ([`1eedf4f`](https://github.com/xarray-contrib/xeofs/commit/1eedf4f5c2b69f30ee45be0c110d9cca7e25ce9d)) * chore: bring all-contributors bot back to life -Implement solution suggested in all-contributors/app#485 ([`8929ed5`](https://github.com/nicrie/xeofs/commit/8929ed5a1f6757eb9f55e191eb4d7d417ad37b1b)) +Implement solution suggested in all-contributors/app#485 ([`8929ed5`](https://github.com/xarray-contrib/xeofs/commit/8929ed5a1f6757eb9f55e191eb4d7d417ad37b1b)) -* chore: merge branches ([`4447b07`](https://github.com/nicrie/xeofs/commit/4447b07a948bc4cdd083ef781c605a630e29c6dc)) +* chore: merge branches ([`4447b07`](https://github.com/xarray-contrib/xeofs/commit/4447b07a948bc4cdd083ef781c605a630e29c6dc)) ### Documentation -* docs: fix broken link ([`de49038`](https://github.com/nicrie/xeofs/commit/de4903863b7c9fd53f8bae39ff6505bcdfadeb6e)) +* docs: fix broken link ([`de49038`](https://github.com/xarray-contrib/xeofs/commit/de4903863b7c9fd53f8bae39ff6505bcdfadeb6e)) -* docs: acknowledge contributors in README (#116) ([`1a88379`](https://github.com/nicrie/xeofs/commit/1a8837915bf89b83c58de1cdff4fe826b0f6d43d)) +* docs: acknowledge contributors in README (#116) ([`1a88379`](https://github.com/xarray-contrib/xeofs/commit/1a8837915bf89b83c58de1cdff4fe826b0f6d43d)) -* docs: acknowledge contributors in README (#115) ([`f2781d8`](https://github.com/nicrie/xeofs/commit/f2781d88371f9a772b67b3458dd098d2281920a5)) +* docs: acknowledge contributors in README (#115) ([`f2781d8`](https://github.com/xarray-contrib/xeofs/commit/f2781d88371f9a772b67b3458dd098d2281920a5)) ### Fix -* fix: only sort transform if model is already sorted (#118) ([`dfe0001`](https://github.com/nicrie/xeofs/commit/dfe0001a18a2ebd2073831e2b6484ace86ea0088)) +* fix: only sort transform if model is already sorted (#118) ([`dfe0001`](https://github.com/xarray-contrib/xeofs/commit/dfe0001a18a2ebd2073831e2b6484ace86ea0088)) ### Refactor -* refactor: set computed attrs via deserialize (#117) ([`1878406`](https://github.com/nicrie/xeofs/commit/1878406702963f099c8a0b3ba2db494d4ef0bab4)) +* refactor: set computed attrs via deserialize (#117) ([`1878406`](https://github.com/xarray-contrib/xeofs/commit/1878406702963f099c8a0b3ba2db494d4ef0bab4)) ### Unknown * 2.1.1 -Automatically generated by python-semantic-release ([`65e9f79`](https://github.com/nicrie/xeofs/commit/65e9f79a880fc2ca24b60961e5271ccbad1a2084)) +Automatically generated by python-semantic-release ([`65e9f79`](https://github.com/xarray-contrib/xeofs/commit/65e9f79a880fc2ca24b60961e5271ccbad1a2084)) ## v2.1.0 (2023-11-14) ### Chore -* chore: release 2.1.0 (#114) ([`acc62ff`](https://github.com/nicrie/xeofs/commit/acc62ff7ce45790880792b6d162f0ac3b2bef6d6)) +* chore: release 2.1.0 (#114) ([`acc62ff`](https://github.com/xarray-contrib/xeofs/commit/acc62ff7ce45790880792b6d162f0ac3b2bef6d6)) -* chore: merge branches ([`c36eca5`](https://github.com/nicrie/xeofs/commit/c36eca57505df28b18f7853e8a880199025fef37)) +* chore: merge branches ([`c36eca5`](https://github.com/xarray-contrib/xeofs/commit/c36eca57505df28b18f7853e8a880199025fef37)) ### Documentation -* docs: remove dead files ([`6c4842e`](https://github.com/nicrie/xeofs/commit/6c4842e34d83aaa9dce06e41c32665a21611a928)) +* docs: remove dead files ([`6c4842e`](https://github.com/xarray-contrib/xeofs/commit/6c4842e34d83aaa9dce06e41c32665a21611a928)) ### Feature -* feat: lazy execution mode (#110) ([`314901e`](https://github.com/nicrie/xeofs/commit/314901ebd978290d56214219d7a87f5111f07775)) +* feat: lazy execution mode (#110) ([`314901e`](https://github.com/xarray-contrib/xeofs/commit/314901ebd978290d56214219d7a87f5111f07775)) ### Unknown * 2.1.0 -Automatically generated by python-semantic-release ([`a3505c9`](https://github.com/nicrie/xeofs/commit/a3505c99abcc8329033d221016b2d2b85e2528bf)) +Automatically generated by python-semantic-release ([`a3505c9`](https://github.com/xarray-contrib/xeofs/commit/a3505c99abcc8329033d221016b2d2b85e2528bf)) ## v2.0.3 (2023-11-12) ### Feature -* feat: add EEOF inverse_transform() (#111) ([`ab6e3cc`](https://github.com/nicrie/xeofs/commit/ab6e3cced44f288c48905bda34e2e4e6d1b60dee)) +* feat: add EEOF inverse_transform() (#111) ([`ab6e3cc`](https://github.com/xarray-contrib/xeofs/commit/ab6e3cced44f288c48905bda34e2e4e6d1b60dee)) ### Fix -* fix: remove poetry io group (#113) ([`23cca05`](https://github.com/nicrie/xeofs/commit/23cca0582748ecaa8df34adfdc7be26ed5a513e1)) +* fix: remove poetry io group (#113) ([`23cca05`](https://github.com/xarray-contrib/xeofs/commit/23cca0582748ecaa8df34adfdc7be26ed5a513e1)) ### Unknown * 2.0.3 -Automatically generated by python-semantic-release ([`e48b3fd`](https://github.com/nicrie/xeofs/commit/e48b3fda148d6be0b6b0b74cebcd033e37935d8a)) +Automatically generated by python-semantic-release ([`e48b3fd`](https://github.com/xarray-contrib/xeofs/commit/e48b3fda148d6be0b6b0b74cebcd033e37935d8a)) ## v2.0.2 (2023-11-08) ### Fix -* fix: safe default zarr write mode (#107) ([`3003f5a`](https://github.com/nicrie/xeofs/commit/3003f5a104db3c954e7e9ad48f88e7056e8fa5bb)) +* fix: safe default zarr write mode (#107) ([`3003f5a`](https://github.com/xarray-contrib/xeofs/commit/3003f5a104db3c954e7e9ad48f88e7056e8fa5bb)) -* fix: safe default zarr write mode ([`0f95d04`](https://github.com/nicrie/xeofs/commit/0f95d0444a6e9d93dba30bd0c4211fe9000ea6bd)) +* fix: safe default zarr write mode ([`0f95d04`](https://github.com/xarray-contrib/xeofs/commit/0f95d0444a6e9d93dba30bd0c4211fe9000ea6bd)) ### Unknown * 2.0.2 -Automatically generated by python-semantic-release ([`1f38a5b`](https://github.com/nicrie/xeofs/commit/1f38a5b818a5d5fc55720e1119e6f686aef89168)) +Automatically generated by python-semantic-release ([`1f38a5b`](https://github.com/xarray-contrib/xeofs/commit/1f38a5b818a5d5fc55720e1119e6f686aef89168)) ## v2.0.1 (2023-11-07) ### Fix -* fix: circumvent pypi block with v2.0.1 release (#105) ([`dbad76a`](https://github.com/nicrie/xeofs/commit/dbad76a3f17967b18b30acb53a2e56e488606f0f)) +* fix: circumvent pypi block with v2.0.1 release (#105) ([`dbad76a`](https://github.com/xarray-contrib/xeofs/commit/dbad76a3f17967b18b30acb53a2e56e488606f0f)) * fix: circumvent pypi block with v2.0.1 release @@ -201,61 +326,61 @@ Previously, an accidental release marked v2.0.0 was published to pypi. Though it was stashed, the tag persisted, obstructing our official v2.0.0. We're addressing this by incrementing to v2.0.1, enabling the correct -release to be published on both pypi and conda without conflict. ([`d014c87`](https://github.com/nicrie/xeofs/commit/d014c87b6f604f9a5d014ee93c09e2b7f9f31f92)) +release to be published on both pypi and conda without conflict. ([`d014c87`](https://github.com/xarray-contrib/xeofs/commit/d014c87b6f604f9a5d014ee93c09e2b7f9f31f92)) ### Unknown * 2.0.1 -Automatically generated by python-semantic-release ([`8cf91ea`](https://github.com/nicrie/xeofs/commit/8cf91eae89e03489241201b9a48bf5d2090054e5)) +Automatically generated by python-semantic-release ([`8cf91ea`](https://github.com/xarray-contrib/xeofs/commit/8cf91eae89e03489241201b9a48bf5d2090054e5)) ## v2.0.0 (2023-11-07) ### Breaking -* feat!: inverse transform for unseen data (#102) ([`4974844`](https://github.com/nicrie/xeofs/commit/4974844bbd5fcfb16806f0d393505d4b93805140)) +* feat!: inverse transform for unseen data (#102) ([`4974844`](https://github.com/xarray-contrib/xeofs/commit/4974844bbd5fcfb16806f0d393505d4b93805140)) -* feat!: inverse_transform scores arg ([`7c1dc16`](https://github.com/nicrie/xeofs/commit/7c1dc16515f3c7588324eba53be9327ca8b4e8c2)) +* feat!: inverse_transform scores arg ([`7c1dc16`](https://github.com/xarray-contrib/xeofs/commit/7c1dc16515f3c7588324eba53be9327ca8b4e8c2)) ### Chore -* chore: release v2.0.0 (#104) ([`226efc7`](https://github.com/nicrie/xeofs/commit/226efc7cf07932f9d17b387a12117fb9f6790575)) +* chore: release v2.0.0 (#104) ([`226efc7`](https://github.com/xarray-contrib/xeofs/commit/226efc7cf07932f9d17b387a12117fb9f6790575)) -* chore: Merge branch 'main' into develop ([`0edb852`](https://github.com/nicrie/xeofs/commit/0edb852259a171397541cb518c25ad6ca9d20fc2)) +* chore: Merge branch 'main' into develop ([`0edb852`](https://github.com/xarray-contrib/xeofs/commit/0edb852259a171397541cb518c25ad6ca9d20fc2)) ### Documentation -* docs: update authors and description (#100) ([`49c4367`](https://github.com/nicrie/xeofs/commit/49c4367b145a84ef4cdbd71f51ef34a63accc654)) +* docs: update authors and description (#100) ([`49c4367`](https://github.com/xarray-contrib/xeofs/commit/49c4367b145a84ef4cdbd71f51ef34a63accc654)) -* docs: update authors and description ([`3e39eda`](https://github.com/nicrie/xeofs/commit/3e39edaa22e9e28ff2140a414af9d1fb82194d67)) +* docs: update authors and description ([`3e39eda`](https://github.com/xarray-contrib/xeofs/commit/3e39edaa22e9e28ff2140a414af9d1fb82194d67)) ### Feature * feat: serialization methods (#103) -Co-authored-by: Niclas Rieger <niclasrieger@gmail.com> ([`69df4d9`](https://github.com/nicrie/xeofs/commit/69df4d9378197935793fc2863f3ffa6a716af49b)) +Co-authored-by: Niclas Rieger <niclasrieger@gmail.com> ([`69df4d9`](https://github.com/xarray-contrib/xeofs/commit/69df4d9378197935793fc2863f3ffa6a716af49b)) ### Test -* test: set random_seed for deterministic output ([`9f0058a`](https://github.com/nicrie/xeofs/commit/9f0058a63f4294f549476b93c33ee35dcf004ab8)) +* test: set random_seed for deterministic output ([`9f0058a`](https://github.com/xarray-contrib/xeofs/commit/9f0058a63f4294f549476b93c33ee35dcf004ab8)) ### Unknown * 2.0.0 -Automatically generated by python-semantic-release ([`ecb92b1`](https://github.com/nicrie/xeofs/commit/ecb92b1e7e64a46461c42b472c475bd2378db055)) +Automatically generated by python-semantic-release ([`ecb92b1`](https://github.com/xarray-contrib/xeofs/commit/ecb92b1e7e64a46461c42b472c475bd2378db055)) ## v1.2.2 (2023-10-31) ### Chore -* chore: release 1.2.2 (#99) ([`17cb471`](https://github.com/nicrie/xeofs/commit/17cb471f8e7a76d77d260a747cca1411b9c67bdd)) +* chore: release 1.2.2 (#99) ([`17cb471`](https://github.com/xarray-contrib/xeofs/commit/17cb471f8e7a76d77d260a747cca1411b9c67bdd)) ### Documentation -* docs: add performance tests ([`42d8e75`](https://github.com/nicrie/xeofs/commit/42d8e752de7d052a4f7e2b83eb17a534f1d3789c)) +* docs: add performance tests ([`42d8e75`](https://github.com/xarray-contrib/xeofs/commit/42d8e752de7d052a4f7e2b83eb17a534f1d3789c)) ### Fix @@ -265,107 +390,107 @@ Resolved an issue where the coordinates of transformed scores were incorrectly reindexed using the fitted data's reference frame. The indexing now correctly utilizes the coordinates from the tansformed data itself, ensuring accurate -alignment with the original dataset (closes #98). ([`a8e458e`](https://github.com/nicrie/xeofs/commit/a8e458e21a5b30c323b93263ff6e7dd687cb391c)) +alignment with the original dataset (closes #98). ([`a8e458e`](https://github.com/xarray-contrib/xeofs/commit/a8e458e21a5b30c323b93263ff6e7dd687cb391c)) ### Performance * perf(Decomposer): compute by default For Dask setting compute=True in svd_compressed avoids that we run out of -memory + increases speed. ([`1f3b214`](https://github.com/nicrie/xeofs/commit/1f3b2146574d56c0724fd194433037ee08428264)) +memory + increases speed. ([`1f3b214`](https://github.com/xarray-contrib/xeofs/commit/1f3b2146574d56c0724fd194433037ee08428264)) -* perf(Dask): avoid double computation ([`f24cb09`](https://github.com/nicrie/xeofs/commit/f24cb09c30d91bd1c2b7405cfdbbfd74a3ead5eb)) +* perf(Dask): avoid double computation ([`f24cb09`](https://github.com/xarray-contrib/xeofs/commit/f24cb09c30d91bd1c2b7405cfdbbfd74a3ead5eb)) ### Unknown * 1.2.2 -Automatically generated by python-semantic-release ([`5aaf7be`](https://github.com/nicrie/xeofs/commit/5aaf7bee35f066a3a193f5a51497a8da1135f248)) +Automatically generated by python-semantic-release ([`5aaf7be`](https://github.com/xarray-contrib/xeofs/commit/5aaf7bee35f066a3a193f5a51497a8da1135f248)) ## v1.2.1 (2023-10-29) ### Build -* build: declare dev docs as optional groups ([`52070d3`](https://github.com/nicrie/xeofs/commit/52070d34d9fe67e71a8efed28058823d3de80b43)) +* build: declare dev docs as optional groups ([`52070d3`](https://github.com/xarray-contrib/xeofs/commit/52070d34d9fe67e71a8efed28058823d3de80b43)) -* build: no support for 3.12 ([`a0ca2ac`](https://github.com/nicrie/xeofs/commit/a0ca2ac706cea2a6453b6a1fb17d054d9d10c5dc)) +* build: no support for 3.12 ([`a0ca2ac`](https://github.com/xarray-contrib/xeofs/commit/a0ca2ac706cea2a6453b6a1fb17d054d9d10c5dc)) -* build: add pre-commit as dev dependency ([`3219562`](https://github.com/nicrie/xeofs/commit/3219562d225f5c5cf6bb1719bbd2c15689c4ea11)) +* build: add pre-commit as dev dependency ([`3219562`](https://github.com/xarray-contrib/xeofs/commit/3219562d225f5c5cf6bb1719bbd2c15689c4ea11)) -* build: update env ([`572cead`](https://github.com/nicrie/xeofs/commit/572cead3c0e4e121de014cfa2115e829457d62c8)) +* build: update env ([`572cead`](https://github.com/xarray-contrib/xeofs/commit/572cead3c0e4e121de014cfa2115e829457d62c8)) -* build: docs require rpy2 package ([`edd69e2`](https://github.com/nicrie/xeofs/commit/edd69e2fb5dd15cb83eadb2d15fd9e576962382b)) +* build: docs require rpy2 package ([`edd69e2`](https://github.com/xarray-contrib/xeofs/commit/edd69e2fb5dd15cb83eadb2d15fd9e576962382b)) -* build: add ipykernel as dependency (#92) ([`7fb4b62`](https://github.com/nicrie/xeofs/commit/7fb4b629caf10185372201aae8a954dd3dedbb05)) +* build: add ipykernel as dependency (#92) ([`7fb4b62`](https://github.com/xarray-contrib/xeofs/commit/7fb4b629caf10185372201aae8a954dd3dedbb05)) * build: add ipykernel as dependency Include ipykernel in the doc environment which is required -to build documentation on readthedocs ([`066dc2a`](https://github.com/nicrie/xeofs/commit/066dc2ac526fc2cd8663507c31c90bd3c692169b)) +to build documentation on readthedocs ([`066dc2a`](https://github.com/xarray-contrib/xeofs/commit/066dc2ac526fc2cd8663507c31c90bd3c692169b)) ### Chore -* chore: release 1.2.1 (#96) ([`2c9b9a3`](https://github.com/nicrie/xeofs/commit/2c9b9a32d9a901a1c1c480392e20df1c18536f73)) +* chore: release 1.2.1 (#96) ([`2c9b9a3`](https://github.com/xarray-contrib/xeofs/commit/2c9b9a32d9a901a1c1c480392e20df1c18536f73)) -* chore: Merge branch 'main' into develop ([`b08e2c3`](https://github.com/nicrie/xeofs/commit/b08e2c355ce39c4c28f0e59d0e3a8753a567c82d)) +* chore: Merge branch 'main' into develop ([`b08e2c3`](https://github.com/xarray-contrib/xeofs/commit/b08e2c355ce39c4c28f0e59d0e3a8753a567c82d)) ### Ci -* ci: install dev dependencies ([`be8bffd`](https://github.com/nicrie/xeofs/commit/be8bffdd746a3a8683a42cfebccac107ff16db60)) +* ci: install dev dependencies ([`be8bffd`](https://github.com/xarray-contrib/xeofs/commit/be8bffdd746a3a8683a42cfebccac107ff16db60)) ### Documentation -* docs: fix link ([`c6a595b`](https://github.com/nicrie/xeofs/commit/c6a595b2d03855b8267992b7f2b345fb1578fe15)) +* docs: fix link ([`c6a595b`](https://github.com/xarray-contrib/xeofs/commit/c6a595b2d03855b8267992b7f2b345fb1578fe15)) -* docs: minor tweaks in documentation ([`977a89e`](https://github.com/nicrie/xeofs/commit/977a89e99b74d7629a6478356ffc458ea1c0359f)) +* docs: minor tweaks in documentation ([`977a89e`](https://github.com/xarray-contrib/xeofs/commit/977a89e99b74d7629a6478356ffc458ea1c0359f)) -* docs: build with Python 3.11 ([`c181972`](https://github.com/nicrie/xeofs/commit/c181972253d9e6bc3ddcfd945f14bc1f06d7ef5f)) +* docs: build with Python 3.11 ([`c181972`](https://github.com/xarray-contrib/xeofs/commit/c181972253d9e6bc3ddcfd945f14bc1f06d7ef5f)) -* docs: complete overhaul ([`47e13ea`](https://github.com/nicrie/xeofs/commit/47e13ea6d0972f67b3e362473380ec802598e409)) +* docs: complete overhaul ([`47e13ea`](https://github.com/xarray-contrib/xeofs/commit/47e13ea6d0972f67b3e362473380ec802598e409)) -* docs: add CoC ([`70f10b2`](https://github.com/nicrie/xeofs/commit/70f10b29e3ac22b49bb3de0f00992761c1e6a059)) +* docs: add CoC ([`70f10b2`](https://github.com/xarray-contrib/xeofs/commit/70f10b29e3ac22b49bb3de0f00992761c1e6a059)) -* docs: update doc environment (#94) ([`9592dbc`](https://github.com/nicrie/xeofs/commit/9592dbcab5b59236b60ce5c82fa2f374e4dc5bec)) +* docs: update doc environment (#94) ([`9592dbc`](https://github.com/xarray-contrib/xeofs/commit/9592dbcab5b59236b60ce5c82fa2f374e4dc5bec)) -* docs: update env ([`e8f72d5`](https://github.com/nicrie/xeofs/commit/e8f72d5cc97393a806a276ff8932103392435b33)) +* docs: update env ([`e8f72d5`](https://github.com/xarray-contrib/xeofs/commit/e8f72d5cc97393a806a276ff8932103392435b33)) -* docs: repair gallery ([`fa647d8`](https://github.com/nicrie/xeofs/commit/fa647d8a0420e2938cea885956bb26a5376cfdaf)) +* docs: repair gallery ([`fa647d8`](https://github.com/xarray-contrib/xeofs/commit/fa647d8a0420e2938cea885956bb26a5376cfdaf)) -* docs: update examples (#93) ([`9f3c0c1`](https://github.com/nicrie/xeofs/commit/9f3c0c15a3e6df57adeabdbc213928a524795fe9)) +* docs: update examples (#93) ([`9f3c0c1`](https://github.com/xarray-contrib/xeofs/commit/9f3c0c15a3e6df57adeabdbc213928a524795fe9)) -* docs: update some docstrings ([`2795c54`](https://github.com/nicrie/xeofs/commit/2795c54951b47ff0e124566338d5dfa0f8a15b91)) +* docs: update some docstrings ([`2795c54`](https://github.com/xarray-contrib/xeofs/commit/2795c54951b47ff0e124566338d5dfa0f8a15b91)) -* docs: fix reference hyperlinks ([`38cadb9`](https://github.com/nicrie/xeofs/commit/38cadb9aa970640f02734457fb07e5e43212facf)) +* docs: fix reference hyperlinks ([`38cadb9`](https://github.com/xarray-contrib/xeofs/commit/38cadb9aa970640f02734457fb07e5e43212facf)) -* docs: fix up minor errors ([`ef3fe8a`](https://github.com/nicrie/xeofs/commit/ef3fe8aa2f707377efdd444b136c29acc592a418)) +* docs: fix up minor errors ([`ef3fe8a`](https://github.com/xarray-contrib/xeofs/commit/ef3fe8aa2f707377efdd444b136c29acc592a418)) -* docs: fix broken example ([`ecc114e`](https://github.com/nicrie/xeofs/commit/ecc114e789ec3711cab6c53d42cf9b67035d3c06)) +* docs: fix broken example ([`ecc114e`](https://github.com/xarray-contrib/xeofs/commit/ecc114e789ec3711cab6c53d42cf9b67035d3c06)) * docs: fix broken example EOF class now computes 2 modes by default, not 10 as before. Specify the number of modes to be -computed in the example to avoid issues ([`b58d985`](https://github.com/nicrie/xeofs/commit/b58d9857b15a599063f99578e8f8d481b77fce9b)) +computed in the example to avoid issues ([`b58d985`](https://github.com/xarray-contrib/xeofs/commit/b58d9857b15a599063f99578e8f8d481b77fce9b)) ### Fix * fix: parameter to show dask progress bar By default, dask progress bar is turned of but can be activated by setting verbose=True -in EOF and Complex EOF models ([`3482fa4`](https://github.com/nicrie/xeofs/commit/3482fa465da66a8e540d10e3a13ef3b8c1461e70)) +in EOF and Complex EOF models ([`3482fa4`](https://github.com/xarray-contrib/xeofs/commit/3482fa465da66a8e540d10e3a13ef3b8c1461e70)) -* fix(Bootstrapper): correct scaling of PCs ([`ed59dd9`](https://github.com/nicrie/xeofs/commit/ed59dd9a6b66ae878c1eb596a2fa9fb9b0e137ca)) +* fix(Bootstrapper): correct scaling of PCs ([`ed59dd9`](https://github.com/xarray-contrib/xeofs/commit/ed59dd9a6b66ae878c1eb596a2fa9fb9b0e137ca)) ### Unknown * 1.2.1 -Automatically generated by python-semantic-release ([`893f2ea`](https://github.com/nicrie/xeofs/commit/893f2ea4e1dddb3522aa6bdc80b5f6912fb0498a)) +Automatically generated by python-semantic-release ([`893f2ea`](https://github.com/xarray-contrib/xeofs/commit/893f2ea4e1dddb3522aa6bdc80b5f6912fb0498a)) -* Update issue templates ([`0f46dd6`](https://github.com/nicrie/xeofs/commit/0f46dd628fc4a9deec2d5211ba0952ed1fca3fc0)) +* Update issue templates ([`0f46dd6`](https://github.com/xarray-contrib/xeofs/commit/0f46dd628fc4a9deec2d5211ba0952ed1fca3fc0)) -* Update issue templates ([`79b1629`](https://github.com/nicrie/xeofs/commit/79b1629d095d2a01b391dd1511c6e84519ab278a)) +* Update issue templates ([`79b1629`](https://github.com/xarray-contrib/xeofs/commit/79b1629d095d2a01b391dd1511c6e84519ab278a)) ## v1.2.0 (2023-10-24) @@ -374,64 +499,64 @@ Automatically generated by python-semantic-release ([`893f2ea`](https://github.c * build: add typing-extensions -Adds Self in python3.10 ([`fb85abe`](https://github.com/nicrie/xeofs/commit/fb85abea09d98975d1784fd206a00bdfcd5c5e6f)) +Adds Self in python3.10 ([`fb85abe`](https://github.com/xarray-contrib/xeofs/commit/fb85abea09d98975d1784fd206a00bdfcd5c5e6f)) -* build: add cca-zoo as dev dependency ([`47e6909`](https://github.com/nicrie/xeofs/commit/47e6909f88fc15ae1891ac5b15d76020c179299b)) +* build: add cca-zoo as dev dependency ([`47e6909`](https://github.com/xarray-contrib/xeofs/commit/47e6909f88fc15ae1891ac5b15d76020c179299b)) -* build: py3.10 requires typing_extension for Self ([`10faa03`](https://github.com/nicrie/xeofs/commit/10faa036da1555b5fadbd714ccd529f4849bb2b9)) +* build: py3.10 requires typing_extension for Self ([`10faa03`](https://github.com/xarray-contrib/xeofs/commit/10faa036da1555b5fadbd714ccd529f4849bb2b9)) -* build: Merge branch 'main' into cca ([`a7df1b8`](https://github.com/nicrie/xeofs/commit/a7df1b8fec3f13c66befad0a4610705e1aba2bf0)) +* build: Merge branch 'main' into cca ([`a7df1b8`](https://github.com/xarray-contrib/xeofs/commit/a7df1b8fec3f13c66befad0a4610705e1aba2bf0)) ### Chore -* chore: Release v1.2.0 (#91) ([`d8fc3f3`](https://github.com/nicrie/xeofs/commit/d8fc3f3c3de595141f2f4df9258ea70f48351408)) +* chore: Release v1.2.0 (#91) ([`d8fc3f3`](https://github.com/xarray-contrib/xeofs/commit/d8fc3f3c3de595141f2f4df9258ea70f48351408)) ### Documentation -* docs: provide top-level type hints ([`6be8923`](https://github.com/nicrie/xeofs/commit/6be892354a208a95d7fe56ebbd3ca90ec86dc31b)) +* docs: provide top-level type hints ([`6be8923`](https://github.com/xarray-contrib/xeofs/commit/6be892354a208a95d7fe56ebbd3ca90ec86dc31b)) ### Feature * feat: provide standard kwarg for random_state -resolves #90 ([`cf8b641`](https://github.com/nicrie/xeofs/commit/cf8b641fffa92892fb7168b0e20dcdd7275cc736)) +resolves #90 ([`cf8b641`](https://github.com/xarray-contrib/xeofs/commit/cf8b641fffa92892fb7168b0e20dcdd7275cc736)) -* feat: add Extended EOF Analysis ([`2db736c`](https://github.com/nicrie/xeofs/commit/2db736cdc5b860c36dbc23c43ffa04251e813533)) +* feat: add Extended EOF Analysis ([`2db736c`](https://github.com/xarray-contrib/xeofs/commit/2db736cdc5b860c36dbc23c43ffa04251e813533)) * feat: parameter normalized scores Returned scores were always (L2) normalized which can lead to confusion when compared to the scores of other packages like sklearn or eofs. -Now users can decide whether to return normalized or "raw" scores. ([`f0dcb34`](https://github.com/nicrie/xeofs/commit/f0dcb3411f36d8aac29a7b781556afd31a36a6b6)) +Now users can decide whether to return normalized or "raw" scores. ([`f0dcb34`](https://github.com/xarray-contrib/xeofs/commit/f0dcb3411f36d8aac29a7b781556afd31a36a6b6)) -* feat: add GWPCA support ([`58c2dbe`](https://github.com/nicrie/xeofs/commit/58c2dbedea9e72f62a80e11415338aa2862e778b)) +* feat: add GWPCA support ([`58c2dbe`](https://github.com/xarray-contrib/xeofs/commit/58c2dbedea9e72f62a80e11415338aa2862e778b)) -* feat: add CCA support ([`79e82cc`](https://github.com/nicrie/xeofs/commit/79e82ccb0802079123d3254c0ef9a617a962fb90)) +* feat: add CCA support ([`79e82cc`](https://github.com/xarray-contrib/xeofs/commit/79e82ccb0802079123d3254c0ef9a617a962fb90)) ### Fix -* fix(CCA): add checks for edge cases ([`76c0b1b`](https://github.com/nicrie/xeofs/commit/76c0b1bbe7f64d16b340ae10789f3df3234321b0)) +* fix(CCA): add checks for edge cases ([`76c0b1b`](https://github.com/xarray-contrib/xeofs/commit/76c0b1bbe7f64d16b340ae10789f3df3234321b0)) * fix: streamline model attribute types Boolean or None values cannot be serialized by xarray which required manual conversion of attributes before to_netcdf can be used. Now model attributes are streamlined internally by converting any boolean or None -values to strings (resolves #89 ) ([`98c5cef`](https://github.com/nicrie/xeofs/commit/98c5cef82e542daa7cf7f003c52666bbedba994b)) +values to strings (resolves #89 ) ([`98c5cef`](https://github.com/xarray-contrib/xeofs/commit/98c5cef82e542daa7cf7f003c52666bbedba994b)) * fix(GWPCA): raise error in scores -scores aren't (yet) supported by GWPCA ([`43e9274`](https://github.com/nicrie/xeofs/commit/43e9274a3eb270a6e331e2f73f77a785e3eb6654)) +scores aren't (yet) supported by GWPCA ([`43e9274`](https://github.com/xarray-contrib/xeofs/commit/43e9274a3eb270a6e331e2f73f77a785e3eb6654)) -* fix(Bootstrapper): avoid pertubating sample coords ([`ffd11fc`](https://github.com/nicrie/xeofs/commit/ffd11fcf21041b7defba6adb9973807d39678678)) +* fix(Bootstrapper): avoid pertubating sample coords ([`ffd11fc`](https://github.com/xarray-contrib/xeofs/commit/ffd11fcf21041b7defba6adb9973807d39678678)) -* fix: score coordinates in T-mode EOF analysis ([`731eec2`](https://github.com/nicrie/xeofs/commit/731eec2825dbe091634cf41a52f38187cce3109c)) +* fix: score coordinates in T-mode EOF analysis ([`731eec2`](https://github.com/xarray-contrib/xeofs/commit/731eec2825dbe091634cf41a52f38187cce3109c)) * fix: PCA preprocessing before Hilbert transform In Complex MCA, PCA preprocessing must happen before Hilbert transform -(fix #85) ([`2bbcb69`](https://github.com/nicrie/xeofs/commit/2bbcb6929ab92d051623c1b15f7ae0eb2f5eebac)) +(fix #85) ([`2bbcb69`](https://github.com/xarray-contrib/xeofs/commit/2bbcb6929ab92d051623c1b15f7ae0eb2f5eebac)) ### Performance @@ -440,86 +565,86 @@ In Complex MCA, PCA preprocessing must happen before Hilbert transform New parameter allows to choose whether dask models will be computed immediately after decomposition or not. Before, all dask objects were delayed until the end -resulting in redundant dask computations. ([`807b7e8`](https://github.com/nicrie/xeofs/commit/807b7e896990c4cfb788478644e7647ab3a9ffa1)) +resulting in redundant dask computations. ([`807b7e8`](https://github.com/xarray-contrib/xeofs/commit/807b7e896990c4cfb788478644e7647ab3a9ffa1)) ### Refactor -* refactor(GenericListTransformer): remove inherit ([`2307169`](https://github.com/nicrie/xeofs/commit/2307169a58d42357cca9edb2a60de82a17c95718)) +* refactor(GenericListTransformer): remove inherit ([`2307169`](https://github.com/xarray-contrib/xeofs/commit/2307169a58d42357cca9edb2a60de82a17c95718)) -* refactor(BaseModel): move input check to utils ([`183779a`](https://github.com/nicrie/xeofs/commit/183779a188e68550f886d08648075bc9d9ba106b)) +* refactor(BaseModel): move input check to utils ([`183779a`](https://github.com/xarray-contrib/xeofs/commit/183779a188e68550f886d08648075bc9d9ba106b)) -* refactor(Preprocessor): enforce input as list ([`ebadaa2`](https://github.com/nicrie/xeofs/commit/ebadaa21fc0d212034ac617f42ccd3b5e579c54b)) +* refactor(Preprocessor): enforce input as list ([`ebadaa2`](https://github.com/xarray-contrib/xeofs/commit/ebadaa21fc0d212034ac617f42ccd3b5e579c54b)) * refactor: simplify model data structure Instead of individual classes that store different model results use a single DataContainer class that structures results -in a dictionary (resolve #88). ([`09415a3`](https://github.com/nicrie/xeofs/commit/09415a3591dc926838c2436c2a94a94adaa37e22)) +in a dictionary (resolve #88). ([`09415a3`](https://github.com/xarray-contrib/xeofs/commit/09415a3591dc926838c2436c2a94a94adaa37e22)) * refactor: create hilbert_transform.py Move Hilbert transform related methods into own file -(resolve refactor: complex utilties #54) ([`166e957`](https://github.com/nicrie/xeofs/commit/166e9578e5f08dc383de7a64688d73833f1ccaaa)) +(resolve refactor: complex utilties #54) ([`166e957`](https://github.com/xarray-contrib/xeofs/commit/166e9578e5f08dc383de7a64688d73833f1ccaaa)) * refactor(BaseModel): create algorithm methods Move actual implementation of method into algorithm methods, while fit, transform, inverse_transform take care of -pre and post-processing ([`12cfc97`](https://github.com/nicrie/xeofs/commit/12cfc975c6203942670f3d8f3bb38f796d02701a)) +pre and post-processing ([`12cfc97`](https://github.com/xarray-contrib/xeofs/commit/12cfc975c6203942670f3d8f3bb38f796d02701a)) -* refactor: generalize preprocessing in MCA ([`fe9bd46`](https://github.com/nicrie/xeofs/commit/fe9bd46cd0e288fbf8bd217acd675bb3d952f0cb)) +* refactor: generalize preprocessing in MCA ([`fe9bd46`](https://github.com/xarray-contrib/xeofs/commit/fe9bd46cd0e288fbf8bd217acd675bb3d952f0cb)) -* refactor: reflect refactoring in Factory ([`0ce02f0`](https://github.com/nicrie/xeofs/commit/0ce02f015c0981811fa5ce1aee02ad4affb97e86)) +* refactor: reflect refactoring in Factory ([`0ce02f0`](https://github.com/xarray-contrib/xeofs/commit/0ce02f015c0981811fa5ce1aee02ad4affb97e86)) -* refactor: adapt Preprocessor to refactoring ([`4a43ce9`](https://github.com/nicrie/xeofs/commit/4a43ce98ba37eaf2330ee1956686d3d73a8f2d1b)) +* refactor: adapt Preprocessor to refactoring ([`4a43ce9`](https://github.com/xarray-contrib/xeofs/commit/4a43ce98ba37eaf2330ee1956686d3d73a8f2d1b)) -* refactor: streamline Scaler ([`a62fc5a`](https://github.com/nicrie/xeofs/commit/a62fc5a2a617c4c5b7915c182944df6583e6b3ac)) +* refactor: streamline Scaler ([`a62fc5a`](https://github.com/xarray-contrib/xeofs/commit/a62fc5a2a617c4c5b7915c182944df6583e6b3ac)) -* refactor: Sanitizer removes NaNs ([`7b5068b`](https://github.com/nicrie/xeofs/commit/7b5068b9215351aaca855d716cc1b7b60069251c)) +* refactor: Sanitizer removes NaNs ([`7b5068b`](https://github.com/xarray-contrib/xeofs/commit/7b5068b9215351aaca855d716cc1b7b60069251c)) * refactor: Stacker focuses on stacking Other actions like converting multiindices or removing NaNs -is present in separate classes ([`9f39f8f`](https://github.com/nicrie/xeofs/commit/9f39f8fccacb03ea4e1f1f32f2082a0a525d7589)) +is present in separate classes ([`9f39f8f`](https://github.com/xarray-contrib/xeofs/commit/9f39f8fccacb03ea4e1f1f32f2082a0a525d7589)) -* refactor: add Sanitizer & tests ([`508d742`](https://github.com/nicrie/xeofs/commit/508d742dc026b97f28be7af20ac41b12357a4f08)) +* refactor: add Sanitizer & tests ([`508d742`](https://github.com/xarray-contrib/xeofs/commit/508d742dc026b97f28be7af20ac41b12357a4f08)) -* refactor: add MultiIndexConvert & tests ([`52935a0`](https://github.com/nicrie/xeofs/commit/52935a0c1e09484046276bedd102ea92d65690d8)) +* refactor: add MultiIndexConvert & tests ([`52935a0`](https://github.com/xarray-contrib/xeofs/commit/52935a0c1e09484046276bedd102ea92d65690d8)) ### Style -* style(decomposer): use structural pattern matching ([`6f8a9cf`](https://github.com/nicrie/xeofs/commit/6f8a9cf192e7e660aa4bec112b624ceccea8df93)) +* style(decomposer): use structural pattern matching ([`6f8a9cf`](https://github.com/xarray-contrib/xeofs/commit/6f8a9cf192e7e660aa4bec112b624ceccea8df93)) -* style: update typings ([`324c06b`](https://github.com/nicrie/xeofs/commit/324c06bba0fdc8afdecc4898c2a40173b01ac9e5)) +* style: update typings ([`324c06b`](https://github.com/xarray-contrib/xeofs/commit/324c06bba0fdc8afdecc4898c2a40173b01ac9e5)) -* style: add and streamline type hints ([`b51f36a`](https://github.com/nicrie/xeofs/commit/b51f36ac2a4235aebafac972547bf14c02f39c7a)) +* style: add and streamline type hints ([`b51f36a`](https://github.com/xarray-contrib/xeofs/commit/b51f36ac2a4235aebafac972547bf14c02f39c7a)) ### Test * test: remove cca-zoo test Conflict between poetry and torch version that cannot be resolved. -Therefore remove cca-zoo dependency and associated tests. ([`6ed06f0`](https://github.com/nicrie/xeofs/commit/6ed06f0654a2a8b1f44f57ea54159f6b142a04ae)) +Therefore remove cca-zoo dependency and associated tests. ([`6ed06f0`](https://github.com/xarray-contrib/xeofs/commit/6ed06f0654a2a8b1f44f57ea54159f6b142a04ae)) -* test: isolated NaNs are invalid test cases ([`d4b5a77`](https://github.com/nicrie/xeofs/commit/d4b5a77bc91b7c13426d424dad72eb94a4f1c30f)) +* test: isolated NaNs are invalid test cases ([`d4b5a77`](https://github.com/xarray-contrib/xeofs/commit/d4b5a77bc91b7c13426d424dad72eb94a4f1c30f)) -* test(EOF): fix random seed ([`4080143`](https://github.com/nicrie/xeofs/commit/40801431873acc87f851e88090dc0d919884bfc1)) +* test(EOF): fix random seed ([`4080143`](https://github.com/xarray-contrib/xeofs/commit/40801431873acc87f851e88090dc0d919884bfc1)) * test: add more flexible data generation classes -Support generation of test cases (resolve #55) ([`15f0194`](https://github.com/nicrie/xeofs/commit/15f01947ee430138dad6a301dd04ab84c2e534c4)) +Support generation of test cases (resolve #55) ([`15f0194`](https://github.com/xarray-contrib/xeofs/commit/15f01947ee430138dad6a301dd04ab84c2e534c4)) * test: provide method to create synthetic data Added three methods for creating synthetic DataArray, Dataset and list of DataArrays. These methods will slowly replace -mock data currently used. ([`a737127`](https://github.com/nicrie/xeofs/commit/a737127c75531b52e37634d90efb7635d21c42b4)) +mock data currently used. ([`a737127`](https://github.com/xarray-contrib/xeofs/commit/a737127c75531b52e37634d90efb7635d21c42b4)) ### Unknown * 1.2.0 -Automatically generated by python-semantic-release ([`0f31950`](https://github.com/nicrie/xeofs/commit/0f319502128014bfc2a6b6a5a553262e1ef4a100)) +Automatically generated by python-semantic-release ([`0f31950`](https://github.com/xarray-contrib/xeofs/commit/0f319502128014bfc2a6b6a5a553262e1ef4a100)) ## v1.1.0 (2023-08-31) @@ -528,20 +653,20 @@ Automatically generated by python-semantic-release ([`0f31950`](https://github.c * build: add black as dev dependency -needed for the Github Action to run black successfully ([`81ccaa8`](https://github.com/nicrie/xeofs/commit/81ccaa8c0410a5c2961e88206b69e88ac80211ee)) +needed for the Github Action to run black successfully ([`81ccaa8`](https://github.com/xarray-contrib/xeofs/commit/81ccaa8c0410a5c2961e88206b69e88ac80211ee)) ### Chore -* chore(release): v1.1.0 (#80) ([`f576cb1`](https://github.com/nicrie/xeofs/commit/f576cb1dea5a8c13ce060ddad418f45ffb76ec9e)) +* chore(release): v1.1.0 (#80) ([`f576cb1`](https://github.com/xarray-contrib/xeofs/commit/f576cb1dea5a8c13ce060ddad418f45ffb76ec9e)) -* chore: cosmetic changes (#72) ([`9f44357`](https://github.com/nicrie/xeofs/commit/9f44357c1223b513bdbdfc7f40be68dd0b687938)) +* chore: cosmetic changes (#72) ([`9f44357`](https://github.com/xarray-contrib/xeofs/commit/9f44357c1223b513bdbdfc7f40be68dd0b687938)) ### Ci * ci(black): specify version and target directory Black linted all files in repo including examples. Main folder xeofs -is sufficient though. ([`7919090`](https://github.com/nicrie/xeofs/commit/7919090682f3bf1ba2c689e86cc802529e390cf7)) +is sufficient though. ([`7919090`](https://github.com/xarray-contrib/xeofs/commit/7919090682f3bf1ba2c689e86cc802529e390cf7)) * ci: update Github Action workflows @@ -549,73 +674,73 @@ New structure separates workflows into separate workflows: ci, PR linting, black formatting and creating release. The latter is only triggered after a PR has been merged. All others are triggered when -a PR on main/develop is opened, edited or synchronized. ([`25211eb`](https://github.com/nicrie/xeofs/commit/25211ebcd0e0a0ec23ce823303107febd9f1079f)) +a PR on main/develop is opened, edited or synchronized. ([`25211eb`](https://github.com/xarray-contrib/xeofs/commit/25211ebcd0e0a0ec23ce823303107febd9f1079f)) ### Documentation -* docs: more instructive quickstart (#75) ([`58c2f09`](https://github.com/nicrie/xeofs/commit/58c2f09e3e7e57c4d2457445634d125b13c6fda8)) +* docs: more instructive quickstart (#75) ([`58c2f09`](https://github.com/xarray-contrib/xeofs/commit/58c2f09e3e7e57c4d2457445634d125b13c6fda8)) -* docs: correct typo in README ([`3b88d5e`](https://github.com/nicrie/xeofs/commit/3b88d5e1b28249efc0cbe5f9c86586eedb6273fb)) +* docs: correct typo in README ([`3b88d5e`](https://github.com/xarray-contrib/xeofs/commit/3b88d5e1b28249efc0cbe5f9c86586eedb6273fb)) -* docs: add quickstart example and point to methods ([`f741199`](https://github.com/nicrie/xeofs/commit/f7411991f29370703560e605578db76b850a2ebc)) +* docs: add quickstart example and point to methods ([`f741199`](https://github.com/xarray-contrib/xeofs/commit/f7411991f29370703560e605578db76b850a2ebc)) -* docs: update location of Action workflow for badge ([`650a8c8`](https://github.com/nicrie/xeofs/commit/650a8c8e2ae1738a89e308bf79d3a2c5dd4b7250)) +* docs: update location of Action workflow for badge ([`650a8c8`](https://github.com/xarray-contrib/xeofs/commit/650a8c8e2ae1738a89e308bf79d3a2c5dd4b7250)) -* docs: update location of Action workflow for badge ([`878c5f5`](https://github.com/nicrie/xeofs/commit/878c5f58e36e7a87b88800fbcd7229bdec7c0b5a)) +* docs: update location of Action workflow for badge ([`878c5f5`](https://github.com/xarray-contrib/xeofs/commit/878c5f58e36e7a87b88800fbcd7229bdec7c0b5a)) -* docs: update badges ([`51113e4`](https://github.com/nicrie/xeofs/commit/51113e4acebfe954b93b8bd79a07c9f2f7a1284a)) +* docs: update badges ([`51113e4`](https://github.com/xarray-contrib/xeofs/commit/51113e4acebfe954b93b8bd79a07c9f2f7a1284a)) -* docs: add Black badge to README ([`759b011`](https://github.com/nicrie/xeofs/commit/759b01101da8bbd8e39327d49d24574137fc6bed)) +* docs: add Black badge to README ([`759b011`](https://github.com/xarray-contrib/xeofs/commit/759b01101da8bbd8e39327d49d24574137fc6bed)) ### Feature -* feat: choose name of sample and feature dim ([`4d521f8`](https://github.com/nicrie/xeofs/commit/4d521f83dea46c558202fc9ce9cfe35c5126453c)) +* feat: choose name of sample and feature dim ([`4d521f8`](https://github.com/xarray-contrib/xeofs/commit/4d521f83dea46c558202fc9ce9cfe35c5126453c)) -* feat: add Optimal Persistence Analysis (OPA) ([`2482110`](https://github.com/nicrie/xeofs/commit/248211086e140b5f0d8ec40a40962ed4b56a7b94)) +* feat: add Optimal Persistence Analysis (OPA) ([`2482110`](https://github.com/xarray-contrib/xeofs/commit/248211086e140b5f0d8ec40a40962ed4b56a7b94)) -* feat: add Canonical Correlation Analysis ([`782e624`](https://github.com/nicrie/xeofs/commit/782e6242ac1f0dd34ed12ee3d0e8154c66551d83)) +* feat: add Canonical Correlation Analysis ([`782e624`](https://github.com/xarray-contrib/xeofs/commit/782e6242ac1f0dd34ed12ee3d0e8154c66551d83)) * feat(MCA): provide optional PCA preprocessing -This can greatly increase computation speed ([`100f40d`](https://github.com/nicrie/xeofs/commit/100f40d7d2f5d9c59725948f4a642a511c4b347f)) +This can greatly increase computation speed ([`100f40d`](https://github.com/xarray-contrib/xeofs/commit/100f40d7d2f5d9c59725948f4a642a511c4b347f)) * feat: choose the SVD solver Following the PCA implementation of scikit-learn, the use can now choose whether full SVD decomposition or randomzied SVD is to be used. Defaults to 'auto' which uses full SVD for small datasets -and randomized SVD for large datasets. ([`50c2386`](https://github.com/nicrie/xeofs/commit/50c23864dd0eb3cd18a4113edd87980622f31da9)) +and randomized SVD for large datasets. ([`50c2386`](https://github.com/xarray-contrib/xeofs/commit/50c23864dd0eb3cd18a4113edd87980622f31da9)) ### Refactor -* refactor: add MultIndexConverter to preprocessor ([`39ee3fb`](https://github.com/nicrie/xeofs/commit/39ee3fbc77b1386f92586e699cffe3aa54ad17cd)) +* refactor: add MultIndexConverter to preprocessor ([`39ee3fb`](https://github.com/xarray-contrib/xeofs/commit/39ee3fbc77b1386f92586e699cffe3aa54ad17cd)) * refactor: generalize hilbert transform over dims Dimensions were hard coded but we want Hilbert transform to -be performed over any general 2D Arrays ([`983e0ad`](https://github.com/nicrie/xeofs/commit/983e0adf7cf46dcea148d2f24a31b650054f4570)) +be performed over any general 2D Arrays ([`983e0ad`](https://github.com/xarray-contrib/xeofs/commit/983e0adf7cf46dcea148d2f24a31b650054f4570)) * refactor: remove dim checks Checks were hard coded to ensure dimensions of e.g. sample-feature. However, we want to allow more general data, with sample and feature -names provided by the user. ([`79b43cf`](https://github.com/nicrie/xeofs/commit/79b43cf874905c531fe0974a0255d95905101eda)) +names provided by the user. ([`79b43cf`](https://github.com/xarray-contrib/xeofs/commit/79b43cf874905c531fe0974a0255d95905101eda)) -* refactor: add class for MultiIndex convertion ([`0033359`](https://github.com/nicrie/xeofs/commit/0033359697c9955a33276af599794aab0b85482d)) +* refactor: add class for MultiIndex convertion ([`0033359`](https://github.com/xarray-contrib/xeofs/commit/0033359697c9955a33276af599794aab0b85482d)) -* refactor(decomposer): coercing signs is optional ([`bb8a0da`](https://github.com/nicrie/xeofs/commit/bb8a0dad086bea00ba77c981eee64aa06a18f95e)) +* refactor(decomposer): coercing signs is optional ([`bb8a0da`](https://github.com/xarray-contrib/xeofs/commit/bb8a0dad086bea00ba77c981eee64aa06a18f95e)) * refactor: extra class for renaming (multi)indeces Helper class to keep track of dimension names. When dimension names of MultiIndex needs to be changes to avoid name conflicts, the class provides easy forth-and-back transformations -between new and old dimension names. ([`80a4c95`](https://github.com/nicrie/xeofs/commit/80a4c95851a9c7d56a3f3fed0073d0c3d5e23578)) +between new and old dimension names. ([`80a4c95`](https://github.com/xarray-contrib/xeofs/commit/80a4c95851a9c7d56a3f3fed0073d0c3d5e23578)) * refactor(decomposer): remove CrossDecomposer The core functionality is now provided by Decomposer. -Any further computations have to be done in the method class ([`52ac245`](https://github.com/nicrie/xeofs/commit/52ac2455a1daee40812db38fef4a90906a8626c2)) +Any further computations have to be done in the method class ([`52ac245`](https://github.com/xarray-contrib/xeofs/commit/52ac2455a1daee40812db38fef4a90906a8626c2)) * refactor(decomposer): generalize SVD decomposer @@ -625,32 +750,32 @@ Now, decomposition of any 2D DataArray is possible if dimensions are given. Decomposer also provides now an argument to specify the solver following the PCA implementation of scikit-learn. For small data sets, full SVD decomposition is performed -instead of randomized SVD. ([`8161e6f`](https://github.com/nicrie/xeofs/commit/8161e6f0983ecabfc7a65588b672718a81df0a77)) +instead of randomized SVD. ([`8161e6f`](https://github.com/xarray-contrib/xeofs/commit/8161e6f0983ecabfc7a65588b672718a81df0a77)) * refactor(stacker): allow sample feature DataArray Specifically, test cases for sample-feature DataArray, that test edge cases when trying to stack/unstack a DataArray -consisting only of sample-feature dimensions ([`25c2bed`](https://github.com/nicrie/xeofs/commit/25c2bedf694307d773f39f8cd2cd27eb311fe105)) +consisting only of sample-feature dimensions ([`25c2bed`](https://github.com/xarray-contrib/xeofs/commit/25c2bedf694307d773f39f8cd2cd27eb311fe105)) * refactor(decomposer): provide kwargs before only specific parameter were allowed. -Now one can set any parameter available in the given solver. ([`a75c805`](https://github.com/nicrie/xeofs/commit/a75c805d9bf606c8f80d0ce2a7f3112f83287444)) +Now one can set any parameter available in the given solver. ([`a75c805`](https://github.com/xarray-contrib/xeofs/commit/a75c805d9bf606c8f80d0ce2a7f3112f83287444)) ### Style -* style(tests): streamline test names ([`3a1fb91`](https://github.com/nicrie/xeofs/commit/3a1fb918244fda8896949fc4bbf38efa459296a5)) +* style(tests): streamline test names ([`3a1fb91`](https://github.com/xarray-contrib/xeofs/commit/3a1fb918244fda8896949fc4bbf38efa459296a5)) * style(tests): apply Black coding format -use Black default settings ([`717f5fe`](https://github.com/nicrie/xeofs/commit/717f5fe4fbaeb14595bf853721128e6143870127)) +use Black default settings ([`717f5fe`](https://github.com/xarray-contrib/xeofs/commit/717f5fe4fbaeb14595bf853721128e6143870127)) * style: integrate Black into repo -pre-hooks and GitHub Actions will use Black. ([`dd4cd7f`](https://github.com/nicrie/xeofs/commit/dd4cd7f44ca84e8b52ae9fd2006954ee2a708c5f)) +pre-hooks and GitHub Actions will use Black. ([`dd4cd7f`](https://github.com/xarray-contrib/xeofs/commit/dd4cd7f44ca84e8b52ae9fd2006954ee2a708c5f)) -* style: apply Black formatting to repo ([`029f6e9`](https://github.com/nicrie/xeofs/commit/029f6e9192b5c386c4dfe913a664bc6709197402)) +* style: apply Black formatting to repo ([`029f6e9`](https://github.com/xarray-contrib/xeofs/commit/029f6e9192b5c386c4dfe913a664bc6709197402)) ### Test @@ -661,17 +786,17 @@ Not sure why this happens but reported this unexpected behaviour at xarray (https://github.com/pydata/xarray/discussions/8063). No regression, since this issue already exists in current xeofs version, but the additional test brought this behavour to light. -To be tackled in the future. ([`3a2411e`](https://github.com/nicrie/xeofs/commit/3a2411e6310ae4f021e3fbd2f317861d9d7282b6)) +To be tackled in the future. ([`3a2411e`](https://github.com/xarray-contrib/xeofs/commit/3a2411e6310ae4f021e3fbd2f317861d9d7282b6)) ### Unknown * 1.1.0 -Automatically generated by python-semantic-release ([`7a09efe`](https://github.com/nicrie/xeofs/commit/7a09efeaf835f43a9072fa2d9220d9fc3b1d379e)) +Automatically generated by python-semantic-release ([`7a09efe`](https://github.com/xarray-contrib/xeofs/commit/7a09efeaf835f43a9072fa2d9220d9fc3b1d379e)) * Merge pull request #73 from nicrie:update-workflows -ci: update Github Action workflows ([`7e679bc`](https://github.com/nicrie/xeofs/commit/7e679bc3d604126431ac53f82eaeea58b3e72bc6)) +ci: update Github Action workflows ([`7e679bc`](https://github.com/xarray-contrib/xeofs/commit/7e679bc3d604126431ac53f82eaeea58b3e72bc6)) ## v1.0.5 (2023-07-31) @@ -682,68 +807,68 @@ ci: update Github Action workflows ([`7e679bc`](https://github.com/nicrie/xeofs/ cartopy crashes during build with poetry. Don't know how to force conda for installation so I'll -go without cartopy for now. ([`c95f658`](https://github.com/nicrie/xeofs/commit/c95f658c52262bccae16061bd9f256c837031823)) +go without cartopy for now. ([`c95f658`](https://github.com/xarray-contrib/xeofs/commit/c95f658c52262bccae16061bd9f256c837031823)) -* build: specify cartopy version ([`ec15384`](https://github.com/nicrie/xeofs/commit/ec1538477188e2e1f2e9d2a7a1fb0a9d432c7dac)) +* build: specify cartopy version ([`ec15384`](https://github.com/xarray-contrib/xeofs/commit/ec1538477188e2e1f2e9d2a7a1fb0a9d432c7dac)) -* build: update poetry lock ([`7edfdc9`](https://github.com/nicrie/xeofs/commit/7edfdc92b25b1f0e1f898247827cec3d5c4a5bf5)) +* build: update poetry lock ([`7edfdc9`](https://github.com/xarray-contrib/xeofs/commit/7edfdc92b25b1f0e1f898247827cec3d5c4a5bf5)) * build: add cartopy and ipywidgets as dev depends Additional examples in online documentation require -advanced plotting and interactivity ([`4d4dcd4`](https://github.com/nicrie/xeofs/commit/4d4dcd4b2899ddc7af70107b08b9840186368c9f)) +advanced plotting and interactivity ([`4d4dcd4`](https://github.com/xarray-contrib/xeofs/commit/4d4dcd4b2899ddc7af70107b08b9840186368c9f)) ### Chore -* chore(release): bump version (#71) ([`58ae844`](https://github.com/nicrie/xeofs/commit/58ae844884483c4c20b463519e8fbcd7ec6679da)) +* chore(release): bump version (#71) ([`58ae844`](https://github.com/xarray-contrib/xeofs/commit/58ae844884483c4c20b463519e8fbcd7ec6679da)) * chore(release): bump version last release did not trigger PSR action to publish to PyPI. Therefore version number lags behid the release number. -To resolve PSR error bump version by hand. ([`8ba42d3`](https://github.com/nicrie/xeofs/commit/8ba42d3dfc77020903efcd84472aba027ed4c0b8)) +To resolve PSR error bump version by hand. ([`8ba42d3`](https://github.com/xarray-contrib/xeofs/commit/8ba42d3dfc77020903efcd84472aba027ed4c0b8)) -* chore(release): 1.0.5 (#70) ([`1dc9ce6`](https://github.com/nicrie/xeofs/commit/1dc9ce614932cf62a97c8c6137d025b01e5ad31d)) +* chore(release): 1.0.5 (#70) ([`1dc9ce6`](https://github.com/xarray-contrib/xeofs/commit/1dc9ce614932cf62a97c8c6137d025b01e5ad31d)) -* chore: internal design (#69) ([`b39bdaf`](https://github.com/nicrie/xeofs/commit/b39bdaf89c71bac831bb8683831e773e57d353bc)) +* chore: internal design (#69) ([`b39bdaf`](https://github.com/xarray-contrib/xeofs/commit/b39bdaf89c71bac831bb8683831e773e57d353bc)) -* chore: Merge branch 'hotfix-mca-scores' into develop ([`f380aed`](https://github.com/nicrie/xeofs/commit/f380aed55b8a530565203b8eb524f9df36ce0dff)) +* chore: Merge branch 'hotfix-mca-scores' into develop ([`f380aed`](https://github.com/xarray-contrib/xeofs/commit/f380aed55b8a530565203b8eb524f9df36ce0dff)) ### Ci -* ci: lock PSR to 7.x ([`b5b94e3`](https://github.com/nicrie/xeofs/commit/b5b94e3d33ee376addc395d612d6e21c7b13d613)) +* ci: lock PSR to 7.x ([`b5b94e3`](https://github.com/xarray-contrib/xeofs/commit/b5b94e3d33ee376addc395d612d6e21c7b13d613)) -* ci: update python-semantic-release to v8 ([`0887579`](https://github.com/nicrie/xeofs/commit/08875797ba42448f0242fd559608b54407e771cd)) +* ci: update python-semantic-release to v8 ([`0887579`](https://github.com/xarray-contrib/xeofs/commit/08875797ba42448f0242fd559608b54407e771cd)) ### Documentation * docs: remove interactivity In html, interactivity is not straightforward. -For simplicity remove all interactive features in the documentation. ([`6e99b8e`](https://github.com/nicrie/xeofs/commit/6e99b8e62831da4eee752e0d2ee0ee48c429f3c3)) +For simplicity remove all interactive features in the documentation. ([`6e99b8e`](https://github.com/xarray-contrib/xeofs/commit/6e99b8e62831da4eee752e0d2ee0ee48c429f3c3)) -* docs: add mamba to RTD config ([`33d040b`](https://github.com/nicrie/xeofs/commit/33d040b4a01ee2f55b510e4f0fc02eafa3c48019)) +* docs: add mamba to RTD config ([`33d040b`](https://github.com/xarray-contrib/xeofs/commit/33d040b4a01ee2f55b510e4f0fc02eafa3c48019)) * docs: use mamba to create doc env Documentation build fails due to excessive memory usage. Potential solution could be using mamba -instead of conda, the former is less memory intensive. ([`610facf`](https://github.com/nicrie/xeofs/commit/610facfd01b7d7ca277a38119fb60b91a43c8439)) +instead of conda, the former is less memory intensive. ([`610facf`](https://github.com/xarray-contrib/xeofs/commit/610facfd01b7d7ca277a38119fb60b91a43c8439)) -* docs: add a Project description to conf.py ([`0a5cfe3`](https://github.com/nicrie/xeofs/commit/0a5cfe3c40bf02ae86de8fcef71de553a5ed1406)) +* docs: add a Project description to conf.py ([`0a5cfe3`](https://github.com/xarray-contrib/xeofs/commit/0a5cfe3c40bf02ae86de8fcef71de553a5ed1406)) * docs: improve documentation -Restructure documentation, add model section and some more background ([`ea32e7e`](https://github.com/nicrie/xeofs/commit/ea32e7ed5dcff5531c6bdaac18a47b6725e7f105)) +Restructure documentation, add model section and some more background ([`ea32e7e`](https://github.com/xarray-contrib/xeofs/commit/ea32e7ed5dcff5531c6bdaac18a47b6725e7f105)) * docs: extend and streamline doc strings of methods More information added to classes and methods, -including references, notes and examples. ([`a70b9d0`](https://github.com/nicrie/xeofs/commit/a70b9d04e9ce58fd0bdc7ef74540134c383fea7f)) +including references, notes and examples. ([`a70b9d0`](https://github.com/xarray-contrib/xeofs/commit/a70b9d04e9ce58fd0bdc7ef74540134c383fea7f)) -* docs(bootstrapper): update to new design pattern ([`d61525b`](https://github.com/nicrie/xeofs/commit/d61525bff6681c30236111b443af4c39bbbc8a98)) +* docs(bootstrapper): update to new design pattern ([`d61525b`](https://github.com/xarray-contrib/xeofs/commit/d61525bff6681c30236111b443af4c39bbbc8a98)) -* docs: update changelog ([`ace7ac9`](https://github.com/nicrie/xeofs/commit/ace7ac9ad101c64c7b041f48d4b3629b4bd747f7)) +* docs: update changelog ([`ace7ac9`](https://github.com/xarray-contrib/xeofs/commit/ace7ac9ad101c64c7b041f48d4b3629b4bd747f7)) ### Fix @@ -753,217 +878,217 @@ Use the inverse_transform_scores of the individual DataArrayStacker to unstack the scores within the ListDataArrayStacker. This will help catching special cases where the -sample dimension is of length one. ([`c6479cf`](https://github.com/nicrie/xeofs/commit/c6479cfb2601d966f58348149667775c5d467063)) +sample dimension is of length one. ([`c6479cf`](https://github.com/xarray-contrib/xeofs/commit/c6479cfb2601d966f58348149667775c5d467063)) -* fix: MCA covariance (fraction) ([`3e4558d`](https://github.com/nicrie/xeofs/commit/3e4558d361fa115aea81a20cf17c4e2b62f03389)) +* fix: MCA covariance (fraction) ([`3e4558d`](https://github.com/xarray-contrib/xeofs/commit/3e4558d361fa115aea81a20cf17c4e2b62f03389)) -* fix: remove **kwargs from BaseModel classes ([`555d0db`](https://github.com/nicrie/xeofs/commit/555d0db92ebf0e855e27364a8494168fc8bab622)) +* fix: remove **kwargs from BaseModel classes ([`555d0db`](https://github.com/xarray-contrib/xeofs/commit/555d0db92ebf0e855e27364a8494168fc8bab622)) -* fix: inverse_transform enforces real output ([`5e97160`](https://github.com/nicrie/xeofs/commit/5e971606781e71e81ee7e90af26a994e73d33781)) +* fix: inverse_transform enforces real output ([`5e97160`](https://github.com/xarray-contrib/xeofs/commit/5e971606781e71e81ee7e90af26a994e73d33781)) -* fix: add missing conj for PCA inverse transform ([`e9d6fe1`](https://github.com/nicrie/xeofs/commit/e9d6fe10795317f719062c2dacb21c2d2e9d3af5)) +* fix: add missing conj for PCA inverse transform ([`e9d6fe1`](https://github.com/xarray-contrib/xeofs/commit/e9d6fe10795317f719062c2dacb21c2d2e9d3af5)) -* fix: transform of rotator classes ([`3368ed0`](https://github.com/nicrie/xeofs/commit/3368ed067d6b87ac8ccfb555c2e1f8da41d77fb0)) +* fix: transform of rotator classes ([`3368ed0`](https://github.com/xarray-contrib/xeofs/commit/3368ed067d6b87ac8ccfb555c2e1f8da41d77fb0)) -* fix: weigh modes with norm before reconstructing ([`13f42e0`](https://github.com/nicrie/xeofs/commit/13f42e07d4e2765bc1a88421258a1ea1872c6434)) +* fix: weigh modes with norm before reconstructing ([`13f42e0`](https://github.com/xarray-contrib/xeofs/commit/13f42e07d4e2765bc1a88421258a1ea1872c6434)) ### Performance -* perf: use xarray built-in method for variance ([`23af4d8`](https://github.com/nicrie/xeofs/commit/23af4d8384d01cfd4ef7098b3ccd22ad8d89612b)) +* perf: use xarray built-in method for variance ([`23af4d8`](https://github.com/xarray-contrib/xeofs/commit/23af4d8384d01cfd4ef7098b3ccd22ad8d89612b)) ### Refactor -* refactor: init DataContainer in models ([`fdd0e78`](https://github.com/nicrie/xeofs/commit/fdd0e786e7697b6068a5fea182531cffed910b41)) +* refactor: init DataContainer in models ([`fdd0e78`](https://github.com/xarray-contrib/xeofs/commit/fdd0e786e7697b6068a5fea182531cffed910b41)) -* refactor: use values of modes sorting index ([`3925ed6`](https://github.com/nicrie/xeofs/commit/3925ed658e3ffd2c02a9fe8acb4bfa270f598bc8)) +* refactor: use values of modes sorting index ([`3925ed6`](https://github.com/xarray-contrib/xeofs/commit/3925ed658e3ffd2c02a9fe8acb4bfa270f598bc8)) -* refactor: align Bootstrapper with design pattern ([`f3e2a10`](https://github.com/nicrie/xeofs/commit/f3e2a101bc84f42a87d5fb31bb38680cb6ae402a)) +* refactor: align Bootstrapper with design pattern ([`f3e2a10`](https://github.com/xarray-contrib/xeofs/commit/f3e2a101bc84f42a87d5fb31bb38680cb6ae402a)) -* refactor: add DataContainer to model structure ([`fc73ccf`](https://github.com/nicrie/xeofs/commit/fc73ccff233957b0a9300e2830d0244658e583ef)) +* refactor: add DataContainer to model structure ([`fc73ccf`](https://github.com/xarray-contrib/xeofs/commit/fc73ccff233957b0a9300e2830d0244658e583ef)) ### Style -* style: apply rotation matrix in a consistent way ([`2f5286d`](https://github.com/nicrie/xeofs/commit/2f5286d956e2b54dfb4ec8b6c7f2fc0a6038d944)) +* style: apply rotation matrix in a consistent way ([`2f5286d`](https://github.com/xarray-contrib/xeofs/commit/2f5286d956e2b54dfb4ec8b6c7f2fc0a6038d944)) -* style: remove unnecessary imports ([`29954c0`](https://github.com/nicrie/xeofs/commit/29954c015bc386952b4e1ac7a07059826b280146)) +* style: remove unnecessary imports ([`29954c0`](https://github.com/xarray-contrib/xeofs/commit/29954c015bc386952b4e1ac7a07059826b280146)) ### Test -* test(MCA): check dimensions of components/scores ([`a214801`](https://github.com/nicrie/xeofs/commit/a214801894cb7fabef59072675d2d1678b733615)) +* test(MCA): check dimensions of components/scores ([`a214801`](https://github.com/xarray-contrib/xeofs/commit/a214801894cb7fabef59072675d2d1678b733615)) -* test(EOF): check dimensions of components/scores ([`093cee8`](https://github.com/nicrie/xeofs/commit/093cee82d8aacafdec8bd8bb7800979c80fee821)) +* test(EOF): check dimensions of components/scores ([`093cee8`](https://github.com/xarray-contrib/xeofs/commit/093cee82d8aacafdec8bd8bb7800979c80fee821)) -* test: test cases for transform, inverse_transform ([`bee9b1f`](https://github.com/nicrie/xeofs/commit/bee9b1f1727ff2a2400334491e0236a11a699100)) +* test: test cases for transform, inverse_transform ([`bee9b1f`](https://github.com/xarray-contrib/xeofs/commit/bee9b1f1727ff2a2400334491e0236a11a699100)) -* test: add basic test for preprocessor ([`aa840b0`](https://github.com/nicrie/xeofs/commit/aa840b076437ec3b8c96a0179d04671ea82f1ca9)) +* test: add basic test for preprocessor ([`aa840b0`](https://github.com/xarray-contrib/xeofs/commit/aa840b076437ec3b8c96a0179d04671ea82f1ca9)) ### Unknown * 1.0.5 -Automatically generated by python-semantic-release ([`6d26bb3`](https://github.com/nicrie/xeofs/commit/6d26bb34496a41007e6c2665903a0423e9ed9f4e)) +Automatically generated by python-semantic-release ([`6d26bb3`](https://github.com/xarray-contrib/xeofs/commit/6d26bb34496a41007e6c2665903a0423e9ed9f4e)) ## v1.0.4 (2023-07-22) ### Documentation -* docs: add ipython to env to use syntax highlight ([`6b2d16b`](https://github.com/nicrie/xeofs/commit/6b2d16b496abfdca4c69e6af556fdeca78227d63)) +* docs: add ipython to env to use syntax highlight ([`6b2d16b`](https://github.com/xarray-contrib/xeofs/commit/6b2d16b496abfdca4c69e6af556fdeca78227d63)) ### Fix -* fix: correct MCA scores and SCF (#66) ([`f6ecc49`](https://github.com/nicrie/xeofs/commit/f6ecc49480807b364780c5b61e1c24f7b1c5b9a5)) +* fix: correct MCA scores and SCF (#66) ([`f6ecc49`](https://github.com/xarray-contrib/xeofs/commit/f6ecc49480807b364780c5b61e1c24f7b1c5b9a5)) -* fix: consistent (squared) covariance for MCA ([`8e43d15`](https://github.com/nicrie/xeofs/commit/8e43d155c32ff210ff5e059b99aa5022c3718496)) +* fix: consistent (squared) covariance for MCA ([`8e43d15`](https://github.com/xarray-contrib/xeofs/commit/8e43d155c32ff210ff5e059b99aa5022c3718496)) -* fix: use conjugate for squared total variance ([`597ba77`](https://github.com/nicrie/xeofs/commit/597ba77ffe4e364946225679a11c7d4a4e059935)) +* fix: use conjugate for squared total variance ([`597ba77`](https://github.com/xarray-contrib/xeofs/commit/597ba77ffe4e364946225679a11c7d4a4e059935)) -* fix: issue with dot product in rotation ([`ab28cca`](https://github.com/nicrie/xeofs/commit/ab28ccad1e1b9dd777e5fef7a2dbbe4c77ab3bb4)) +* fix: issue with dot product in rotation ([`ab28cca`](https://github.com/xarray-contrib/xeofs/commit/ab28ccad1e1b9dd777e5fef7a2dbbe4c77ab3bb4)) ### Refactor -* refactor: merge Stacker & Scaler into Preprocessor ([`8c27b84`](https://github.com/nicrie/xeofs/commit/8c27b8402f3ded1c4eb072e12227b4a53bd68ca6)) +* refactor: merge Stacker & Scaler into Preprocessor ([`8c27b84`](https://github.com/xarray-contrib/xeofs/commit/8c27b8402f3ded1c4eb072e12227b4a53bd68ca6)) -* refactor: add Scaler and Stacker factories ([`5cf719f`](https://github.com/nicrie/xeofs/commit/5cf719ff21ea4dc3a2d66dad0fcb680cfc500b1b)) +* refactor: add Scaler and Stacker factories ([`5cf719f`](https://github.com/xarray-contrib/xeofs/commit/5cf719ff21ea4dc3a2d66dad0fcb680cfc500b1b)) ### Unknown * 1.0.4 -Automatically generated by python-semantic-release ([`118ad68`](https://github.com/nicrie/xeofs/commit/118ad68533fee3db00493b86ae3ea21ce4210524)) +Automatically generated by python-semantic-release ([`118ad68`](https://github.com/xarray-contrib/xeofs/commit/118ad68533fee3db00493b86ae3ea21ce4210524)) ## v1.0.3 (2023-07-10) ### Chore -* chore: correct package version ([`9070851`](https://github.com/nicrie/xeofs/commit/907085143bdd813668d76b4d765a756a0e7a7262)) +* chore: correct package version ([`9070851`](https://github.com/xarray-contrib/xeofs/commit/907085143bdd813668d76b4d765a756a0e7a7262)) ### Fix -* fix: dummy patch to fix package versioning (#53) ([`89d128d`](https://github.com/nicrie/xeofs/commit/89d128d9f3e1bea43242c8521e7f3d43716160cd)) +* fix: dummy patch to fix package versioning (#53) ([`89d128d`](https://github.com/xarray-contrib/xeofs/commit/89d128d9f3e1bea43242c8521e7f3d43716160cd)) ### Unknown * 1.0.3 -Automatically generated by python-semantic-release ([`75158c6`](https://github.com/nicrie/xeofs/commit/75158c638f7809982820acbda60d495b173aef03)) +Automatically generated by python-semantic-release ([`75158c6`](https://github.com/xarray-contrib/xeofs/commit/75158c638f7809982820acbda60d495b173aef03)) -* 1.0.2 | dummy commit to correct package version ([`e3457c0`](https://github.com/nicrie/xeofs/commit/e3457c0f195a81974399209a9c49c37209867b57)) +* 1.0.2 | dummy commit to correct package version ([`e3457c0`](https://github.com/xarray-contrib/xeofs/commit/e3457c0f195a81974399209a9c49c37209867b57)) ## v1.0.2 (2023-07-10) ### Build -* build: revert errorenous upgrade to v2 ([`ca22aa4`](https://github.com/nicrie/xeofs/commit/ca22aa420c4809deaa114de18164ce8d0f5fb02b)) +* build: revert errorenous upgrade to v2 ([`ca22aa4`](https://github.com/xarray-contrib/xeofs/commit/ca22aa420c4809deaa114de18164ce8d0f5fb02b)) ### Chore -* chore: merge branch 'main' into develop ([`e0e8d93`](https://github.com/nicrie/xeofs/commit/e0e8d93f2ca33ebb091f76a3e04ba5c18b5276ed)) +* chore: merge branch 'main' into develop ([`e0e8d93`](https://github.com/xarray-contrib/xeofs/commit/e0e8d93f2ca33ebb091f76a3e04ba5c18b5276ed)) -* chore: merge main into develop ([`9f50392`](https://github.com/nicrie/xeofs/commit/9f50392d7f99ca6bb7cd13608b630094e0845cb3)) +* chore: merge main into develop ([`9f50392`](https://github.com/xarray-contrib/xeofs/commit/9f50392d7f99ca6bb7cd13608b630094e0845cb3)) -* chore: merge branch 'main' of nicrie/xeofs ([`efb5ab9`](https://github.com/nicrie/xeofs/commit/efb5ab9c306e9d71a4aab20b6f16ccbfa6a65c56)) +* chore: merge branch 'main' of nicrie/xeofs ([`efb5ab9`](https://github.com/xarray-contrib/xeofs/commit/efb5ab9c306e9d71a4aab20b6f16ccbfa6a65c56)) -* chore: Merge branch 'main' into develop ([`bc4e87d`](https://github.com/nicrie/xeofs/commit/bc4e87d469807c4b2bb4679556813e2693affe5f)) +* chore: Merge branch 'main' into develop ([`bc4e87d`](https://github.com/xarray-contrib/xeofs/commit/bc4e87d469807c4b2bb4679556813e2693affe5f)) -* chore: Merge develop of nicrie/xeofs into develop ([`f31e56e`](https://github.com/nicrie/xeofs/commit/f31e56e49c550f87c6b132951f97ebd561ec5db5)) +* chore: Merge develop of nicrie/xeofs into develop ([`f31e56e`](https://github.com/xarray-contrib/xeofs/commit/f31e56e49c550f87c6b132951f97ebd561ec5db5)) ### Documentation -* docs: minor improvements (#50) ([`00ac5b3`](https://github.com/nicrie/xeofs/commit/00ac5b3e3776fe0dd63a8104d2768029459a61b4)) +* docs: minor improvements (#50) ([`00ac5b3`](https://github.com/xarray-contrib/xeofs/commit/00ac5b3e3776fe0dd63a8104d2768029459a61b4)) -* docs: citation in bibtex format ([`f33f2d5`](https://github.com/nicrie/xeofs/commit/f33f2d5a0add42decd41a1187ec6a071721845f5)) +* docs: citation in bibtex format ([`f33f2d5`](https://github.com/xarray-contrib/xeofs/commit/f33f2d5a0add42decd41a1187ec6a071721845f5)) -* docs: updates examples ([`f31024b`](https://github.com/nicrie/xeofs/commit/f31024bbc531c84a3dd963d5319e3e636dc82c74)) +* docs: updates examples ([`f31024b`](https://github.com/xarray-contrib/xeofs/commit/f31024bbc531c84a3dd963d5319e3e636dc82c74)) -* docs: citation ([`4054e15`](https://github.com/nicrie/xeofs/commit/4054e156247519281d8d9a810a5753f2b45542d5)) +* docs: citation ([`4054e15`](https://github.com/xarray-contrib/xeofs/commit/4054e156247519281d8d9a810a5753f2b45542d5)) -* docs: set color styling ([`59213dc`](https://github.com/nicrie/xeofs/commit/59213dc1818aadd2f1b0f5bab2d1a4071a55ec8a)) +* docs: set color styling ([`59213dc`](https://github.com/xarray-contrib/xeofs/commit/59213dc1818aadd2f1b0f5bab2d1a4071a55ec8a)) -* docs: add pydata-sphinx-theme as doc dependency (#49) ([`976d390`](https://github.com/nicrie/xeofs/commit/976d39008c9cb30f1c9870505d66d73c3ab6f01c)) +* docs: add pydata-sphinx-theme as doc dependency (#49) ([`976d390`](https://github.com/xarray-contrib/xeofs/commit/976d39008c9cb30f1c9870505d66d73c3ab6f01c)) -* docs: add pydata-sphinx-theme as doc dependency ([`15c5a3e`](https://github.com/nicrie/xeofs/commit/15c5a3e98ebdadbbabf014f5034edacc7f01a6da)) +* docs: add pydata-sphinx-theme as doc dependency ([`15c5a3e`](https://github.com/xarray-contrib/xeofs/commit/15c5a3e98ebdadbbabf014f5034edacc7f01a6da)) -* docs: improve documentation (#48) ([`378aae8`](https://github.com/nicrie/xeofs/commit/378aae871c15ad19b1e63631d58d8b00bafd65a2)) +* docs: improve documentation (#48) ([`378aae8`](https://github.com/xarray-contrib/xeofs/commit/378aae871c15ad19b1e63631d58d8b00bafd65a2)) -* docs: move to pydata sphinx theme ([`9e92920`](https://github.com/nicrie/xeofs/commit/9e92920d75114f1525ab59f01e81daf044f3f975)) +* docs: move to pydata sphinx theme ([`9e92920`](https://github.com/xarray-contrib/xeofs/commit/9e92920d75114f1525ab59f01e81daf044f3f975)) -* docs: add comparison to other packages ([`7985585`](https://github.com/nicrie/xeofs/commit/7985585b34fd27fd391f8a0d388723e2f639df30)) +* docs: add comparison to other packages ([`7985585`](https://github.com/xarray-contrib/xeofs/commit/7985585b34fd27fd391f8a0d388723e2f639df30)) -* docs: fix broken badge ([`9d9b5d8`](https://github.com/nicrie/xeofs/commit/9d9b5d889bbef74f67c3a2b9d946c2373e51d725)) +* docs: fix broken badge ([`9d9b5d8`](https://github.com/xarray-contrib/xeofs/commit/9d9b5d889bbef74f67c3a2b9d946c2373e51d725)) -* docs: add dev-dependeny for readthedocs (#46) ([`e1e6379`](https://github.com/nicrie/xeofs/commit/e1e6379e2da146e7d8422da45e68bf678561d600)) +* docs: add dev-dependeny for readthedocs (#46) ([`e1e6379`](https://github.com/xarray-contrib/xeofs/commit/e1e6379e2da146e7d8422da45e68bf678561d600)) -* docs: add sphinx related packages to env ([`6e07d3b`](https://github.com/nicrie/xeofs/commit/6e07d3b3c6797a787a5b10885c2f73ef5c14cdf8)) +* docs: add sphinx related packages to env ([`6e07d3b`](https://github.com/xarray-contrib/xeofs/commit/6e07d3b3c6797a787a5b10885c2f73ef5c14cdf8)) ### Fix -* fix(method): remove bias in Hilbert transform after padding (#52) ([`f65f54b`](https://github.com/nicrie/xeofs/commit/f65f54bf4ebc2dda2f787cc7cc5c6ce5bba73eb5)) +* fix(method): remove bias in Hilbert transform after padding (#52) ([`f65f54b`](https://github.com/xarray-contrib/xeofs/commit/f65f54bf4ebc2dda2f787cc7cc5c6ce5bba73eb5)) -* fix(method): remove bias in Hilbert transform after padding ([`8e199ef`](https://github.com/nicrie/xeofs/commit/8e199ef290018ff3649532f17cbd43d7c37b3681)) +* fix(method): remove bias in Hilbert transform after padding ([`8e199ef`](https://github.com/xarray-contrib/xeofs/commit/8e199ef290018ff3649532f17cbd43d7c37b3681)) -* fix: correct bias in Hilbert trans when padding (#51) ([`ef37dd3`](https://github.com/nicrie/xeofs/commit/ef37dd3b4443605e1106e59a5693d2ec7b9a4fe9)) +* fix: correct bias in Hilbert trans when padding (#51) ([`ef37dd3`](https://github.com/xarray-contrib/xeofs/commit/ef37dd3b4443605e1106e59a5693d2ec7b9a4fe9)) -* fix: correct bias in Hilbert trans when padding ([`c0183df`](https://github.com/nicrie/xeofs/commit/c0183df0a238db16fef8affde66b7c86a8a6382d)) +* fix: correct bias in Hilbert trans when padding ([`c0183df`](https://github.com/xarray-contrib/xeofs/commit/c0183df0a238db16fef8affde66b7c86a8a6382d)) ### Refactor -* refactor: Merge 'main' of github.com:nicrie/xeofs ([`93fb010`](https://github.com/nicrie/xeofs/commit/93fb010103923d839295fce67cb012e0b70d157f)) +* refactor: Merge 'main' of github.com:nicrie/xeofs ([`93fb010`](https://github.com/xarray-contrib/xeofs/commit/93fb010103923d839295fce67cb012e0b70d157f)) ### Unknown * 2.0.0 -Automatically generated by python-semantic-release ([`e33f1c9`](https://github.com/nicrie/xeofs/commit/e33f1c91e47af6b3f0275e8fe3282bf9b56cffeb)) +Automatically generated by python-semantic-release ([`e33f1c9`](https://github.com/xarray-contrib/xeofs/commit/e33f1c91e47af6b3f0275e8fe3282bf9b56cffeb)) -* 1.0.1 | dummy commit to force semantic release ([`08133ef`](https://github.com/nicrie/xeofs/commit/08133ef3fce95b1e5d646e0ad23d99a6947ef18b)) +* 1.0.1 | dummy commit to force semantic release ([`08133ef`](https://github.com/xarray-contrib/xeofs/commit/08133ef3fce95b1e5d646e0ad23d99a6947ef18b)) * 2.0.0 -Automatically generated by python-semantic-release ([`464d71e`](https://github.com/nicrie/xeofs/commit/464d71ea93f344a50e6729a78a039d0ae53f86e5)) +Automatically generated by python-semantic-release ([`464d71e`](https://github.com/xarray-contrib/xeofs/commit/464d71ea93f344a50e6729a78a039d0ae53f86e5)) ## v1.0.1 (2023-07-07) ### Build -* build: drop 3.9 support ([`4552fa9`](https://github.com/nicrie/xeofs/commit/4552fa95827d1944fbea0ca8ce9b8a9c4b9e866e)) +* build: drop 3.9 support ([`4552fa9`](https://github.com/xarray-contrib/xeofs/commit/4552fa95827d1944fbea0ca8ce9b8a9c4b9e866e)) -* build: remove python 3.8 support ([`2b408e7`](https://github.com/nicrie/xeofs/commit/2b408e71ccc5cacc8011c0ac41a5a357d8d2fd09)) +* build: remove python 3.8 support ([`2b408e7`](https://github.com/xarray-contrib/xeofs/commit/2b408e71ccc5cacc8011c0ac41a5a357d8d2fd09)) -* build: add dask ([`fef6509`](https://github.com/nicrie/xeofs/commit/fef6509bb5fce40b4d03aaca9ed2ef6d7566e5d1)) +* build: add dask ([`fef6509`](https://github.com/xarray-contrib/xeofs/commit/fef6509bb5fce40b4d03aaca9ed2ef6d7566e5d1)) ### Chore -* chore: Merge branch 'main' into develop ([`d1896d6`](https://github.com/nicrie/xeofs/commit/d1896d64a100809ae84140cc67172fa3e0da2f27)) +* chore: Merge branch 'main' into develop ([`d1896d6`](https://github.com/xarray-contrib/xeofs/commit/d1896d64a100809ae84140cc67172fa3e0da2f27)) -* chore: merge 'main' of github.com:nicrie/xeofs ([`cfc164b`](https://github.com/nicrie/xeofs/commit/cfc164b9182e771ddc785b6ec81de7ec8f8772bd)) +* chore: merge 'main' of github.com:nicrie/xeofs ([`cfc164b`](https://github.com/xarray-contrib/xeofs/commit/cfc164b9182e771ddc785b6ec81de7ec8f8772bd)) ### Ci -* ci: remove redundant file ([`4699a56`](https://github.com/nicrie/xeofs/commit/4699a566d6f44041c2401516db9ba5a38ff1e140)) +* ci: remove redundant file ([`4699a56`](https://github.com/xarray-contrib/xeofs/commit/4699a566d6f44041c2401516db9ba5a38ff1e140)) ### Fix -* fix: build and ci (#45) ([`7d1a88b`](https://github.com/nicrie/xeofs/commit/7d1a88b1cda8a66d04f3ffa96e1aa5cfe899029b)) +* fix: build and ci (#45) ([`7d1a88b`](https://github.com/xarray-contrib/xeofs/commit/7d1a88b1cda8a66d04f3ffa96e1aa5cfe899029b)) -* fix: add dependency statsmodels ([`87e7e1d`](https://github.com/nicrie/xeofs/commit/87e7e1d89f5d8dd3f7954bb4ebc79d2d41738404)) +* fix: add dependency statsmodels ([`87e7e1d`](https://github.com/xarray-contrib/xeofs/commit/87e7e1d89f5d8dd3f7954bb4ebc79d2d41738404)) -* fix: add dask as dependency (#42) ([`2bb2b6b`](https://github.com/nicrie/xeofs/commit/2bb2b6b817a457a7a24918914e88675f08e298d6)) +* fix: add dask as dependency (#42) ([`2bb2b6b`](https://github.com/xarray-contrib/xeofs/commit/2bb2b6b817a457a7a24918914e88675f08e298d6)) ### Test -* test: fix incorrect MCA output ([`9a22140`](https://github.com/nicrie/xeofs/commit/9a221405ba793122c765eada98a14c8828d4e54c)) +* test: fix incorrect MCA output ([`9a22140`](https://github.com/xarray-contrib/xeofs/commit/9a221405ba793122c765eada98a14c8828d4e54c)) ### Unknown * 1.0.1 -Automatically generated by python-semantic-release ([`99f2d28`](https://github.com/nicrie/xeofs/commit/99f2d28e328d2a44fdd9eb1c8eae44cdbaa46789)) +Automatically generated by python-semantic-release ([`99f2d28`](https://github.com/xarray-contrib/xeofs/commit/99f2d28e328d2a44fdd9eb1c8eae44cdbaa46789)) -* Merge branch 'main' into develop ([`4e33e86`](https://github.com/nicrie/xeofs/commit/4e33e86c5d340b5a4c2b58e9b29bec505db73101)) +* Merge branch 'main' into develop ([`4e33e86`](https://github.com/xarray-contrib/xeofs/commit/4e33e86c5d340b5a4c2b58e9b29bec505db73101)) ## v1.0.0 (2023-07-07) @@ -972,822 +1097,822 @@ Automatically generated by python-semantic-release ([`99f2d28`](https://github.c * feat!: v1.0.0 -BREAKING CHANGE: drop pandas support; add support for dask, complex EOF and flexible inputs ([`ec70e8a`](https://github.com/nicrie/xeofs/commit/ec70e8a9321d0aa1dc0b44ca83be14f441afef18)) +BREAKING CHANGE: drop pandas support; add support for dask, complex EOF and flexible inputs ([`ec70e8a`](https://github.com/xarray-contrib/xeofs/commit/ec70e8a9321d0aa1dc0b44ca83be14f441afef18)) -* fix!: rename n_rot to n_modes ([`5b39cd4`](https://github.com/nicrie/xeofs/commit/5b39cd4d565a82185c76f16b248e6aeae78577cc)) +* fix!: rename n_rot to n_modes ([`5b39cd4`](https://github.com/xarray-contrib/xeofs/commit/5b39cd4d565a82185c76f16b248e6aeae78577cc)) -* fix!: n_components instead of n_modes ([`5d282b1`](https://github.com/nicrie/xeofs/commit/5d282b1fc83f150113b13d4f736838676e5d9fff)) +* fix!: n_components instead of n_modes ([`5d282b1`](https://github.com/xarray-contrib/xeofs/commit/5d282b1fc83f150113b13d4f736838676e5d9fff)) -* fix!: change parameter dims to dim ([`70fe651`](https://github.com/nicrie/xeofs/commit/70fe65147f2dab8be7d9bdf08a81fbd36cc45897)) +* fix!: change parameter dims to dim ([`70fe651`](https://github.com/xarray-contrib/xeofs/commit/70fe65147f2dab8be7d9bdf08a81fbd36cc45897)) -* refactor(pandas)!: drop support for pandas ([`96196e5`](https://github.com/nicrie/xeofs/commit/96196e55a3094ae63266b534aa36e4cedf56d03a)) +* refactor(pandas)!: drop support for pandas ([`96196e5`](https://github.com/xarray-contrib/xeofs/commit/96196e55a3094ae63266b534aa36e4cedf56d03a)) ### Build -* build: adapt dev versions ([`9dba9c4`](https://github.com/nicrie/xeofs/commit/9dba9c48b058bee4669b13cb321d8f057c64d4e4)) +* build: adapt dev versions ([`9dba9c4`](https://github.com/xarray-contrib/xeofs/commit/9dba9c48b058bee4669b13cb321d8f057c64d4e4)) -* build: add sphinx theme ([`5b61bcd`](https://github.com/nicrie/xeofs/commit/5b61bcd870bcdd69f5344ae23c4586c68dbfd71c)) +* build: add sphinx theme ([`5b61bcd`](https://github.com/xarray-contrib/xeofs/commit/5b61bcd870bcdd69f5344ae23c4586c68dbfd71c)) -* build: update to most recent versions ([`3a06022`](https://github.com/nicrie/xeofs/commit/3a060228456f21dc847c19234bc793b43d76ae99)) +* build: update to most recent versions ([`3a06022`](https://github.com/xarray-contrib/xeofs/commit/3a060228456f21dc847c19234bc793b43d76ae99)) -* build: update environment to Python 3.11 ([`5947194`](https://github.com/nicrie/xeofs/commit/5947194733243b3fb84d7abdfb83df1c4fa3dd77)) +* build: update environment to Python 3.11 ([`5947194`](https://github.com/xarray-contrib/xeofs/commit/5947194733243b3fb84d7abdfb83df1c4fa3dd77)) -* build: update poetry.lock to newer versions ([`1215e57`](https://github.com/nicrie/xeofs/commit/1215e574ee7a41dcffd3add13f57b923f60baf68)) +* build: update poetry.lock to newer versions ([`1215e57`](https://github.com/xarray-contrib/xeofs/commit/1215e574ee7a41dcffd3add13f57b923f60baf68)) ### Ci -* ci: do not run on PR ([`9829517`](https://github.com/nicrie/xeofs/commit/9829517d2277c0d186552e014777726fdbd03b55)) +* ci: do not run on PR ([`9829517`](https://github.com/xarray-contrib/xeofs/commit/9829517d2277c0d186552e014777726fdbd03b55)) -* ci: Update semantic_release.yml ([`7f1b2b4`](https://github.com/nicrie/xeofs/commit/7f1b2b40f9918742ef30e48eab9713518f068b1f)) +* ci: Update semantic_release.yml ([`7f1b2b4`](https://github.com/xarray-contrib/xeofs/commit/7f1b2b40f9918742ef30e48eab9713518f068b1f)) -* ci: python 3.10 bug ([`0dd2a18`](https://github.com/nicrie/xeofs/commit/0dd2a185e7f51f6d9f70afcb863c392c37fde965)) +* ci: python 3.10 bug ([`0dd2a18`](https://github.com/xarray-contrib/xeofs/commit/0dd2a185e7f51f6d9f70afcb863c392c37fde965)) -* ci: test also against python 3.9, 3.10 and 3.11 ([`29d0ae0`](https://github.com/nicrie/xeofs/commit/29d0ae08a21203df04696cf7ac438fbee9daf691)) +* ci: test also against python 3.9, 3.10 and 3.11 ([`29d0ae0`](https://github.com/xarray-contrib/xeofs/commit/29d0ae08a21203df04696cf7ac438fbee9daf691)) -* ci: add action for semantic pull request ([`2af2456`](https://github.com/nicrie/xeofs/commit/2af2456d25318d028845d2e51534e2282c020e84)) +* ci: add action for semantic pull request ([`2af2456`](https://github.com/xarray-contrib/xeofs/commit/2af2456d25318d028845d2e51534e2282c020e84)) -* ci: update to Node 16 ([`7373b8a`](https://github.com/nicrie/xeofs/commit/7373b8a40725f0e53c28c4736c6f01e2611fca4c)) +* ci: update to Node 16 ([`7373b8a`](https://github.com/xarray-contrib/xeofs/commit/7373b8a40725f0e53c28c4736c6f01e2611fca4c)) ### Documentation -* docs: improve documentation ([`b7c6680`](https://github.com/nicrie/xeofs/commit/b7c6680d196b269301b16143626fc0fea15cd038)) +* docs: improve documentation ([`b7c6680`](https://github.com/xarray-contrib/xeofs/commit/b7c6680d196b269301b16143626fc0fea15cd038)) -* docs: add more docstrings ([`84ebb5a`](https://github.com/nicrie/xeofs/commit/84ebb5ac9a4abca9b30c04b9e9089d3c73ce15a7)) +* docs: add more docstrings ([`84ebb5a`](https://github.com/xarray-contrib/xeofs/commit/84ebb5ac9a4abca9b30c04b9e9089d3c73ce15a7)) -* docs: add docstrings ([`0fe6e24`](https://github.com/nicrie/xeofs/commit/0fe6e242f9f4bc1067e8b2fb8e2c0eafaaebf2b2)) +* docs: add docstrings ([`0fe6e24`](https://github.com/xarray-contrib/xeofs/commit/0fe6e242f9f4bc1067e8b2fb8e2c0eafaaebf2b2)) ### Feature -* feat: complex MCA amplitude and phase ([`55ce3b1`](https://github.com/nicrie/xeofs/commit/55ce3b17f2cb77ea2f11e4fe6444f9860ca5920d)) +* feat: complex MCA amplitude and phase ([`55ce3b1`](https://github.com/xarray-contrib/xeofs/commit/55ce3b17f2cb77ea2f11e4fe6444f9860ca5920d)) -* feat: add meta data to model output ([`083a8e0`](https://github.com/nicrie/xeofs/commit/083a8e049140bfbec87f354ed7f0504bbb208fd8)) +* feat: add meta data to model output ([`083a8e0`](https://github.com/xarray-contrib/xeofs/commit/083a8e049140bfbec87f354ed7f0504bbb208fd8)) -* feat: skeleton of Bootstrapper class ([`4934b31`](https://github.com/nicrie/xeofs/commit/4934b31f8ab3d2d35f371f13abedfd5c178775a1)) +* feat: skeleton of Bootstrapper class ([`4934b31`](https://github.com/xarray-contrib/xeofs/commit/4934b31f8ab3d2d35f371f13abedfd5c178775a1)) -* feat: Rotation supports dask input ([`78360cf`](https://github.com/nicrie/xeofs/commit/78360cfbc3b237e8791a32b65aca3f0e7b5d7ec7)) +* feat: Rotation supports dask input ([`78360cf`](https://github.com/xarray-contrib/xeofs/commit/78360cfbc3b237e8791a32b65aca3f0e7b5d7ec7)) -* feat: add complex MCA ([`13f8bbc`](https://github.com/nicrie/xeofs/commit/13f8bbc8b29e82af37ec6793b416a0ca1e2d1aa5)) +* feat: add complex MCA ([`13f8bbc`](https://github.com/xarray-contrib/xeofs/commit/13f8bbc8b29e82af37ec6793b416a0ca1e2d1aa5)) -* feat: RotatorFactory to access rotator classes ([`90b2db6`](https://github.com/nicrie/xeofs/commit/90b2db687314bc1b62aae5c74c0817eeb806203e)) +* feat: RotatorFactory to access rotator classes ([`90b2db6`](https://github.com/xarray-contrib/xeofs/commit/90b2db687314bc1b62aae5c74c0817eeb806203e)) -* feat: EOF class transform, inverse_trans and corr ([`fb71ffe`](https://github.com/nicrie/xeofs/commit/fb71ffede30fdfd65b4b812a62340e9f292fbea6)) +* feat: EOF class transform, inverse_trans and corr ([`fb71ffe`](https://github.com/xarray-contrib/xeofs/commit/fb71ffede30fdfd65b4b812a62340e9f292fbea6)) -* feat: add support for complex EOF ([`6bff6af`](https://github.com/nicrie/xeofs/commit/6bff6af12f0202fbce9cf06453ac66e8921d1d5c)) +* feat: add support for complex EOF ([`6bff6af`](https://github.com/xarray-contrib/xeofs/commit/6bff6af12f0202fbce9cf06453ac66e8921d1d5c)) ### Fix -* fix: add components and pattern method to MCA ([`849059b`](https://github.com/nicrie/xeofs/commit/849059b65d9218753ef886f5790742ea832a504d)) +* fix: add components and pattern method to MCA ([`849059b`](https://github.com/xarray-contrib/xeofs/commit/849059b65d9218753ef886f5790742ea832a504d)) -* fix: Merge 'release-v1.0.0' into bootstrapper ([`e6ea275`](https://github.com/nicrie/xeofs/commit/e6ea27536a43ff086c615ed720a03166d20718de)) +* fix: Merge 'release-v1.0.0' into bootstrapper ([`e6ea275`](https://github.com/xarray-contrib/xeofs/commit/e6ea27536a43ff086c615ed720a03166d20718de)) -* fix: stacker in T-mode ([`2f9be99`](https://github.com/nicrie/xeofs/commit/2f9be995f2a73e75c0bf88b86290246effc5989c)) +* fix: stacker in T-mode ([`2f9be99`](https://github.com/xarray-contrib/xeofs/commit/2f9be995f2a73e75c0bf88b86290246effc5989c)) -* fix: supress warning when unstacking coords ([`2f01695`](https://github.com/nicrie/xeofs/commit/2f01695eac40bae2519f7dfd7b4d936b4c6647c5)) +* fix: supress warning when unstacking coords ([`2f01695`](https://github.com/xarray-contrib/xeofs/commit/2f01695eac40bae2519f7dfd7b4d936b4c6647c5)) -* fix: number of modes to be rotated defaults 10 ([`b13c833`](https://github.com/nicrie/xeofs/commit/b13c833bd12241878b218cf62bbdc3121a8034de)) +* fix: number of modes to be rotated defaults 10 ([`b13c833`](https://github.com/xarray-contrib/xeofs/commit/b13c833bd12241878b218cf62bbdc3121a8034de)) -* fix: phase of complex methods returns np.ndarray ([`dfb050d`](https://github.com/nicrie/xeofs/commit/dfb050d82b8d12cc137bd51316b220dd1deb93c3)) +* fix: phase of complex methods returns np.ndarray ([`dfb050d`](https://github.com/xarray-contrib/xeofs/commit/dfb050d82b8d12cc137bd51316b220dd1deb93c3)) -* fix: complex decomposition not used ([`2086546`](https://github.com/nicrie/xeofs/commit/208654683c9071bc3927e8c7dd549a01e409dea3)) +* fix: complex decomposition not used ([`2086546`](https://github.com/xarray-contrib/xeofs/commit/208654683c9071bc3927e8c7dd549a01e409dea3)) -* fix: added missing import ([`207af0a`](https://github.com/nicrie/xeofs/commit/207af0ab15267eca5fccbbfb5a464ceb4004d56e)) +* fix: added missing import ([`207af0a`](https://github.com/xarray-contrib/xeofs/commit/207af0ab15267eca5fccbbfb5a464ceb4004d56e)) -* fix: remove unecessary dimensions in scores ([`63e2204`](https://github.com/nicrie/xeofs/commit/63e2204ab3cce1fdf4ae6a1a153a987fde69e5c0)) +* fix: remove unecessary dimensions in scores ([`63e2204`](https://github.com/xarray-contrib/xeofs/commit/63e2204ab3cce1fdf4ae6a1a153a987fde69e5c0)) -* fix: reindex data to ensure deterministic output ([`60c382b`](https://github.com/nicrie/xeofs/commit/60c382bc181aacb8997d955c225df96a7b3bed11)) +* fix: reindex data to ensure deterministic output ([`60c382b`](https://github.com/xarray-contrib/xeofs/commit/60c382bc181aacb8997d955c225df96a7b3bed11)) -* fix: ListStacker correctly unstacks ([`e363357`](https://github.com/nicrie/xeofs/commit/e363357851199b08d916b8efae4bac6a56f5c806)) +* fix: ListStacker correctly unstacks ([`e363357`](https://github.com/xarray-contrib/xeofs/commit/e363357851199b08d916b8efae4bac6a56f5c806)) -* fix: define names of output arrays ([`c826aa8`](https://github.com/nicrie/xeofs/commit/c826aa81dbd1bc9c6441982847bff08c4e9cd333)) +* fix: define names of output arrays ([`c826aa8`](https://github.com/xarray-contrib/xeofs/commit/c826aa81dbd1bc9c6441982847bff08c4e9cd333)) ### Performance -* perf: always compute scaling arrays prior to analy ([`5b810ce`](https://github.com/nicrie/xeofs/commit/5b810ce3f7ecddd9fb44d307e600cd472e07d599)) +* perf: always compute scaling arrays prior to analy ([`5b810ce`](https://github.com/xarray-contrib/xeofs/commit/5b810ce3f7ecddd9fb44d307e600cd472e07d599)) ### Refactor -* refactor: bootstrapper ([`5525ed1`](https://github.com/nicrie/xeofs/commit/5525ed1eddb05c2e8ab043e9fe9b22d4aa6103de)) +* refactor: bootstrapper ([`5525ed1`](https://github.com/xarray-contrib/xeofs/commit/5525ed1eddb05c2e8ab043e9fe9b22d4aa6103de)) -* refactor: version into separate file ([`d51d167`](https://github.com/nicrie/xeofs/commit/d51d1672e6b1dcb8706b4f2222d9c69359e9d978)) +* refactor: version into separate file ([`d51d167`](https://github.com/xarray-contrib/xeofs/commit/d51d1672e6b1dcb8706b4f2222d9c69359e9d978)) -* refactor: bootstrapper ([`7074942`](https://github.com/nicrie/xeofs/commit/707494211b10da188b64c59684d969fead8d3517)) +* refactor: bootstrapper ([`7074942`](https://github.com/xarray-contrib/xeofs/commit/707494211b10da188b64c59684d969fead8d3517)) -* refactor: Merg 'release-v1.0.0' into bootstrapper ([`97f57ff`](https://github.com/nicrie/xeofs/commit/97f57ff32416e188cfbaead67a753d6749c7822e)) +* refactor: Merg 'release-v1.0.0' into bootstrapper ([`97f57ff`](https://github.com/xarray-contrib/xeofs/commit/97f57ff32416e188cfbaead67a753d6749c7822e)) -* refactor: Stacker.fit to fit_transform ([`e949c57`](https://github.com/nicrie/xeofs/commit/e949c575578e3d585ad6c672f4e83819a52d8e25)) +* refactor: Stacker.fit to fit_transform ([`e949c57`](https://github.com/xarray-contrib/xeofs/commit/e949c575578e3d585ad6c672f4e83819a52d8e25)) -* refactor: move standard, complex model in one file ([`83f0aad`](https://github.com/nicrie/xeofs/commit/83f0aadb14f0d09d2ca484aa83cc10e6bb16dac2)) +* refactor: move standard, complex model in one file ([`83f0aad`](https://github.com/xarray-contrib/xeofs/commit/83f0aadb14f0d09d2ca484aa83cc10e6bb16dac2)) -* refactor: reorganize repo ([`d109a2c`](https://github.com/nicrie/xeofs/commit/d109a2cc49ffa5a3dfe512ee0bfec925afdbe65f)) +* refactor: reorganize repo ([`d109a2c`](https://github.com/xarray-contrib/xeofs/commit/d109a2cc49ffa5a3dfe512ee0bfec925afdbe65f)) -* refactor: clean up ([`0d868c6`](https://github.com/nicrie/xeofs/commit/0d868c6c7229a229502b32bdcea0ff54deb54159)) +* refactor: clean up ([`0d868c6`](https://github.com/xarray-contrib/xeofs/commit/0d868c6c7229a229502b32bdcea0ff54deb54159)) -* refactor: clean and move tests ([`68392e3`](https://github.com/nicrie/xeofs/commit/68392e3b70e0fe9fb513bd9b64532484f3f8f8e2)) +* refactor: clean and move tests ([`68392e3`](https://github.com/xarray-contrib/xeofs/commit/68392e3b70e0fe9fb513bd9b64532484f3f8f8e2)) -* refactor: add CrossDecomposer ([`43c9ca4`](https://github.com/nicrie/xeofs/commit/43c9ca4a02ed0278a8b30278627c856ae9b6d89d)) +* refactor: add CrossDecomposer ([`43c9ca4`](https://github.com/xarray-contrib/xeofs/commit/43c9ca4a02ed0278a8b30278627c856ae9b6d89d)) -* refactor: add method in tools for computing corr ([`4866357`](https://github.com/nicrie/xeofs/commit/48663574b97a4f8b2f451f7a56b2d1fd00b034b1)) +* refactor: add method in tools for computing corr ([`4866357`](https://github.com/xarray-contrib/xeofs/commit/48663574b97a4f8b2f451f7a56b2d1fd00b034b1)) -* refactor: components as correlations to testing ([`be1aed6`](https://github.com/nicrie/xeofs/commit/be1aed69a60b20ce494d2ec4441617a42656f697)) +* refactor: components as correlations to testing ([`be1aed6`](https://github.com/xarray-contrib/xeofs/commit/be1aed69a60b20ce494d2ec4441617a42656f697)) -* refactor: add Rotator class ([`58e66d2`](https://github.com/nicrie/xeofs/commit/58e66d2c134fb6b2c6742259c25a44c6a9e18058)) +* refactor: add Rotator class ([`58e66d2`](https://github.com/xarray-contrib/xeofs/commit/58e66d2c134fb6b2c6742259c25a44c6a9e18058)) -* refactor: Merge branch 'stacker' into release-v ([`aea74c7`](https://github.com/nicrie/xeofs/commit/aea74c7fbc7f93d9dd22a464085cd984d88bb505)) +* refactor: Merge branch 'stacker' into release-v ([`aea74c7`](https://github.com/xarray-contrib/xeofs/commit/aea74c7fbc7f93d9dd22a464085cd984d88bb505)) -* refactor: EOF model uses xarray only ([`369f40b`](https://github.com/nicrie/xeofs/commit/369f40bd66f6ac1edf4966a798cb76dda577481f)) +* refactor: EOF model uses xarray only ([`369f40b`](https://github.com/xarray-contrib/xeofs/commit/369f40bd66f6ac1edf4966a798cb76dda577481f)) -* refactor: add Decomposer class ([`cb76350`](https://github.com/nicrie/xeofs/commit/cb76350998d84fb8c28ec47be6266a98cd3951bc)) +* refactor: add Decomposer class ([`cb76350`](https://github.com/xarray-contrib/xeofs/commit/cb76350998d84fb8c28ec47be6266a98cd3951bc)) -* refactor: add basic Stacker class ([`8d170be`](https://github.com/nicrie/xeofs/commit/8d170bea9097e829520092660f1df34269383ea5)) +* refactor: add basic Stacker class ([`8d170be`](https://github.com/xarray-contrib/xeofs/commit/8d170bea9097e829520092660f1df34269383ea5)) -* refactor: add Scaler class ([`8428471`](https://github.com/nicrie/xeofs/commit/8428471714a74829b9fc601310a6b38f5fb00060)) +* refactor: add Scaler class ([`8428471`](https://github.com/xarray-contrib/xeofs/commit/8428471714a74829b9fc601310a6b38f5fb00060)) -* refactor: add Scaler class ([`a202fa5`](https://github.com/nicrie/xeofs/commit/a202fa54098383d40310b294b7a973a49112a411)) +* refactor: add Scaler class ([`a202fa5`](https://github.com/xarray-contrib/xeofs/commit/a202fa54098383d40310b294b7a973a49112a411)) ### Style -* style: streamline arguments ([`4af426c`](https://github.com/nicrie/xeofs/commit/4af426cb99d1736645142a4ac4f0325b4add9165)) +* style: streamline arguments ([`4af426c`](https://github.com/xarray-contrib/xeofs/commit/4af426cb99d1736645142a4ac4f0325b4add9165)) -* style: ignore some type hints ([`0e3cff2`](https://github.com/nicrie/xeofs/commit/0e3cff22b04e11439a9bae7f028fc2aa03c50f1c)) +* style: ignore some type hints ([`0e3cff2`](https://github.com/xarray-contrib/xeofs/commit/0e3cff22b04e11439a9bae7f028fc2aa03c50f1c)) -* style: ignore some type hints ([`dfeb5a0`](https://github.com/nicrie/xeofs/commit/dfeb5a0d38e9366753983cfded65470ffea45199)) +* style: ignore some type hints ([`dfeb5a0`](https://github.com/xarray-contrib/xeofs/commit/dfeb5a0d38e9366753983cfded65470ffea45199)) -* style: ignore some type hints ([`d03553a`](https://github.com/nicrie/xeofs/commit/d03553a75d6c3f2957524fb7fe81ecc363e61ab9)) +* style: ignore some type hints ([`d03553a`](https://github.com/xarray-contrib/xeofs/commit/d03553a75d6c3f2957524fb7fe81ecc363e61ab9)) -* style: ignore .vscode files ([`2877f1d`](https://github.com/nicrie/xeofs/commit/2877f1d6cf8b2ae6c51d80fa105e837011ae24d4)) +* style: ignore .vscode files ([`2877f1d`](https://github.com/xarray-contrib/xeofs/commit/2877f1d6cf8b2ae6c51d80fa105e837011ae24d4)) ### Test -* test: add more test cases ([`5921eb4`](https://github.com/nicrie/xeofs/commit/5921eb402dbbbc97f14dd98725e634cd124df50a)) +* test: add more test cases ([`5921eb4`](https://github.com/xarray-contrib/xeofs/commit/5921eb402dbbbc97f14dd98725e634cd124df50a)) -* test: add tests for MCA and Rotator ([`bc6d1c6`](https://github.com/nicrie/xeofs/commit/bc6d1c64faebea4302c62cdfbb5d25baad1a4dc4)) +* test: add tests for MCA and Rotator ([`bc6d1c6`](https://github.com/xarray-contrib/xeofs/commit/bc6d1c64faebea4302c62cdfbb5d25baad1a4dc4)) -* test: add test cases for ComplexEOF ([`7b6b29b`](https://github.com/nicrie/xeofs/commit/7b6b29bed1bacea10f24e803b887a15e0e97ab3a)) +* test: add test cases for ComplexEOF ([`7b6b29b`](https://github.com/xarray-contrib/xeofs/commit/7b6b29bed1bacea10f24e803b887a15e0e97ab3a)) -* test: add EOF test cases ([`ba95eb5`](https://github.com/nicrie/xeofs/commit/ba95eb50da2bb38dd0ab5fd19d31769319babced)) +* test: add EOF test cases ([`ba95eb5`](https://github.com/xarray-contrib/xeofs/commit/ba95eb50da2bb38dd0ab5fd19d31769319babced)) ### Unknown * 1.0.0 -Automatically generated by python-semantic-release ([`0533a8e`](https://github.com/nicrie/xeofs/commit/0533a8eb967f8d4e0f4af56099ddf9b675deef9e)) +Automatically generated by python-semantic-release ([`0533a8e`](https://github.com/xarray-contrib/xeofs/commit/0533a8eb967f8d4e0f4af56099ddf9b675deef9e)) * release v1.0.0 (#41) - Enable support for Dask (close provide dask support #11 ) - Complex EOF (with contributions from @mschulzie) (close #6 ) - Provide support for DataArray, Dataset and list of DataArrays (close #39 ) -- Mimic structure of sklearn (close #40 ) ([`7235ae2`](https://github.com/nicrie/xeofs/commit/7235ae29c4d5935d429d8e7ebb2b01118e8ae7f1)) +- Mimic structure of sklearn (close #40 ) ([`7235ae2`](https://github.com/xarray-contrib/xeofs/commit/7235ae29c4d5935d429d8e7ebb2b01118e8ae7f1)) -* Create semantic_release.yml ([`0fbfde6`](https://github.com/nicrie/xeofs/commit/0fbfde68d81cdfad63e0f0ceb805caf2cf6ede95)) +* Create semantic_release.yml ([`0fbfde6`](https://github.com/xarray-contrib/xeofs/commit/0fbfde68d81cdfad63e0f0ceb805caf2cf6ede95)) * Revert "fix!: n_components instead of n_modes" -This reverts commit 5d282b1fc83f150113b13d4f736838676e5d9fff. ([`430a022`](https://github.com/nicrie/xeofs/commit/430a02224de25aacf1fcda620acdd7c5a49ac7bd)) +This reverts commit 5d282b1fc83f150113b13d4f736838676e5d9fff. ([`430a022`](https://github.com/xarray-contrib/xeofs/commit/430a02224de25aacf1fcda620acdd7c5a49ac7bd)) ## v0.7.2 (2023-01-10) ### Fix -* fix: FutureWarning in coslat check (#37) ([`285fe0f`](https://github.com/nicrie/xeofs/commit/285fe0f6f6cb69cd84e3ac4c662c64d6d659ef47)) +* fix: FutureWarning in coslat check (#37) ([`285fe0f`](https://github.com/xarray-contrib/xeofs/commit/285fe0f6f6cb69cd84e3ac4c662c64d6d659ef47)) ### Unknown * 0.7.2 -Automatically generated by python-semantic-release ([`d7c67a5`](https://github.com/nicrie/xeofs/commit/d7c67a5205f58865966b6e711d0003c5d3e1fcda)) +Automatically generated by python-semantic-release ([`d7c67a5`](https://github.com/xarray-contrib/xeofs/commit/d7c67a5205f58865966b6e711d0003c5d3e1fcda)) ## v0.7.1 (2023-01-08) ### Fix -* fix: allow newer xarray version ([`49723c0`](https://github.com/nicrie/xeofs/commit/49723c0771b87b8f4b812572f51d50f71bb139e3)) +* fix: allow newer xarray version ([`49723c0`](https://github.com/xarray-contrib/xeofs/commit/49723c0771b87b8f4b812572f51d50f71bb139e3)) ### Unknown * 0.7.1 -Automatically generated by python-semantic-release ([`c85f116`](https://github.com/nicrie/xeofs/commit/c85f116ab1836b1c426378e9506b68b58c2bfde4)) +Automatically generated by python-semantic-release ([`c85f116`](https://github.com/xarray-contrib/xeofs/commit/c85f116ab1836b1c426378e9506b68b58c2bfde4)) * Merge pull request #36 from slevang/xarray-version-fix -fix: allow newer xarray version ([`1e1694f`](https://github.com/nicrie/xeofs/commit/1e1694fcac07f9ea74ead8da404dd566dea6f152)) +fix: allow newer xarray version ([`1e1694f`](https://github.com/xarray-contrib/xeofs/commit/1e1694fcac07f9ea74ead8da404dd566dea6f152)) * Merge pull request #35 from nicrie/revert-34-xarray-version -Revert "allow newer xarray versions" ([`4d7a230`](https://github.com/nicrie/xeofs/commit/4d7a230db7e65e332dde635b2c43204fcccfa28a)) +Revert "allow newer xarray versions" ([`4d7a230`](https://github.com/xarray-contrib/xeofs/commit/4d7a230db7e65e332dde635b2c43204fcccfa28a)) -* Revert "allow newer xarray versions" ([`c40100a`](https://github.com/nicrie/xeofs/commit/c40100af6a4a23dd9c6a8bd537943708b797033a)) +* Revert "allow newer xarray versions" ([`c40100a`](https://github.com/xarray-contrib/xeofs/commit/c40100af6a4a23dd9c6a8bd537943708b797033a)) * Merge pull request #34 from slevang/xarray-version -allow newer xarray versions ([`56a6700`](https://github.com/nicrie/xeofs/commit/56a670010c4e2e6c40dee1710424f1fab049a63d)) +allow newer xarray versions ([`56a6700`](https://github.com/xarray-contrib/xeofs/commit/56a670010c4e2e6c40dee1710424f1fab049a63d)) -* allow newer xarray versions ([`6949499`](https://github.com/nicrie/xeofs/commit/69494991f61cc2e9b47074a6490848f6f58d94b5)) +* allow newer xarray versions ([`6949499`](https://github.com/xarray-contrib/xeofs/commit/69494991f61cc2e9b47074a6490848f6f58d94b5)) * Merge pull request #27 from aaronspring/patch-1 -`eofs` has `xarray` interface ([`3d689e8`](https://github.com/nicrie/xeofs/commit/3d689e81a5b254f4f1f04154f5aba093de730ab1)) +`eofs` has `xarray` interface ([`3d689e8`](https://github.com/xarray-contrib/xeofs/commit/3d689e81a5b254f4f1f04154f5aba093de730ab1)) * eofs.xarray -https://ajdawson.github.io/eofs/latest/api/eofs.xarray.html ([`116de61`](https://github.com/nicrie/xeofs/commit/116de61d0eff3b636509533104e3419fc7ad6299)) +https://ajdawson.github.io/eofs/latest/api/eofs.xarray.html ([`116de61`](https://github.com/xarray-contrib/xeofs/commit/116de61d0eff3b636509533104e3419fc7ad6299)) ## v0.7.0 (2022-08-26) ### Build -* build: remove numba dependency ([`0979fcf`](https://github.com/nicrie/xeofs/commit/0979fcf4111fc82c055269b4d69bd5a237bd21c0)) +* build: remove numba dependency ([`0979fcf`](https://github.com/xarray-contrib/xeofs/commit/0979fcf4111fc82c055269b4d69bd5a237bd21c0)) -* build: add numba as dependency ([`f627d92`](https://github.com/nicrie/xeofs/commit/f627d9270ca2c850c619ba428eaeeb315740f83a)) +* build: add numba as dependency ([`f627d92`](https://github.com/xarray-contrib/xeofs/commit/f627d9270ca2c850c619ba428eaeeb315740f83a)) -* build: change conf ([`a73ef85`](https://github.com/nicrie/xeofs/commit/a73ef85739bbf38f915add70319032c4c2d3791d)) +* build: change conf ([`a73ef85`](https://github.com/xarray-contrib/xeofs/commit/a73ef85739bbf38f915add70319032c4c2d3791d)) -* build: docs do not compile properly, try changing version in conf.py ([`0a73edb`](https://github.com/nicrie/xeofs/commit/0a73edbc30578b9598f18018180af567758ac7a9)) +* build: docs do not compile properly, try changing version in conf.py ([`0a73edb`](https://github.com/xarray-contrib/xeofs/commit/0a73edbc30578b9598f18018180af567758ac7a9)) ### Documentation -* docs: bibtex not showing up on Github ;) ([`0c2a663`](https://github.com/nicrie/xeofs/commit/0c2a6635ee5942f2c38f28a1f529ec6a4a5e24bd)) +* docs: bibtex not showing up on Github ;) ([`0c2a663`](https://github.com/xarray-contrib/xeofs/commit/0c2a6635ee5942f2c38f28a1f529ec6a4a5e24bd)) -* docs: add bibtex ([`1428ebf`](https://github.com/nicrie/xeofs/commit/1428ebfc5d65a62044a3f9f9fb20a4636dbfb891)) +* docs: add bibtex ([`1428ebf`](https://github.com/xarray-contrib/xeofs/commit/1428ebfc5d65a62044a3f9f9fb20a4636dbfb891)) -* docs: fix some minor errors ([`d5d3f73`](https://github.com/nicrie/xeofs/commit/d5d3f73b27814b947903a30cf6cbde8aaf5dc67b)) +* docs: fix some minor errors ([`d5d3f73`](https://github.com/xarray-contrib/xeofs/commit/d5d3f73b27814b947903a30cf6cbde8aaf5dc67b)) -* docs: update README ([`2d28995`](https://github.com/nicrie/xeofs/commit/2d28995a9e6c5ce1424721497eef6e97a6430e45)) +* docs: update README ([`2d28995`](https://github.com/xarray-contrib/xeofs/commit/2d28995a9e6c5ce1424721497eef6e97a6430e45)) -* docs: change examples ([`1c69645`](https://github.com/nicrie/xeofs/commit/1c6964542dcfe3d794c6a01442822f57d422a681)) +* docs: change examples ([`1c69645`](https://github.com/xarray-contrib/xeofs/commit/1c6964542dcfe3d794c6a01442822f57d422a681)) -* docs: adding example for ROCK PCA ([`8c6da93`](https://github.com/nicrie/xeofs/commit/8c6da93f7c6e99780299e2687960c6a22e7c6661)) +* docs: adding example for ROCK PCA ([`8c6da93`](https://github.com/xarray-contrib/xeofs/commit/8c6da93f7c6e99780299e2687960c6a22e7c6661)) -* docs: update ROCK PCA to documentation ([`3a7394d`](https://github.com/nicrie/xeofs/commit/3a7394d57fb4e9d79dfffef5b32df5af1a52e179)) +* docs: update ROCK PCA to documentation ([`3a7394d`](https://github.com/xarray-contrib/xeofs/commit/3a7394d57fb4e9d79dfffef5b32df5af1a52e179)) -* docs: update README ([`9e3210d`](https://github.com/nicrie/xeofs/commit/9e3210d190da254850ea17c70011dab916bda24c)) +* docs: update README ([`9e3210d`](https://github.com/xarray-contrib/xeofs/commit/9e3210d190da254850ea17c70011dab916bda24c)) -* docs: add example and update docs ([`8bed38a`](https://github.com/nicrie/xeofs/commit/8bed38a79094ece72487b619aa01cd45fa276a80)) +* docs: add example and update docs ([`8bed38a`](https://github.com/xarray-contrib/xeofs/commit/8bed38a79094ece72487b619aa01cd45fa276a80)) -* docs: some minor corrections in docstrings ([`75eed31`](https://github.com/nicrie/xeofs/commit/75eed31f2cdf33a896174aca77c33ec4bc3791eb)) +* docs: some minor corrections in docstrings ([`75eed31`](https://github.com/xarray-contrib/xeofs/commit/75eed31f2cdf33a896174aca77c33ec4bc3791eb)) -* docs: more text ([`0f9c32e`](https://github.com/nicrie/xeofs/commit/0f9c32e48dd6c9069c11802a13a3f0113e5f07f5)) +* docs: more text ([`0f9c32e`](https://github.com/xarray-contrib/xeofs/commit/0f9c32e48dd6c9069c11802a13a3f0113e5f07f5)) -* docs: fix docs ([`19bb84e`](https://github.com/nicrie/xeofs/commit/19bb84e3c57c4762fb2d61b3a60df143e6c05b72)) +* docs: fix docs ([`19bb84e`](https://github.com/xarray-contrib/xeofs/commit/19bb84e3c57c4762fb2d61b3a60df143e6c05b72)) ### Feature -* feat: add support for ROCK-PCA ([`202844d`](https://github.com/nicrie/xeofs/commit/202844d0e12565bdefb39988a374c4aa20681a0d)) +* feat: add support for ROCK-PCA ([`202844d`](https://github.com/xarray-contrib/xeofs/commit/202844d0e12565bdefb39988a374c4aa20681a0d)) -* feat: Merge branch 'develop' into rock-pca ([`6a5bda8`](https://github.com/nicrie/xeofs/commit/6a5bda8ab1fdc3e0c8c2395172385e058c0b7d3d)) +* feat: Merge branch 'develop' into rock-pca ([`6a5bda8`](https://github.com/xarray-contrib/xeofs/commit/6a5bda8ab1fdc3e0c8c2395172385e058c0b7d3d)) -* feat: add ROCK PCA ([`0ba0660`](https://github.com/nicrie/xeofs/commit/0ba0660fa4f2396dc537888c80be5352dedaebc4)) +* feat: add ROCK PCA ([`0ba0660`](https://github.com/xarray-contrib/xeofs/commit/0ba0660fa4f2396dc537888c80be5352dedaebc4)) -* feat: Add Rotator class for MCA ([`0e9e8f9`](https://github.com/nicrie/xeofs/commit/0e9e8f90f00d499a385956742fc99ca0776bed83)) +* feat: Add Rotator class for MCA ([`0e9e8f9`](https://github.com/xarray-contrib/xeofs/commit/0e9e8f90f00d499a385956742fc99ca0776bed83)) -* feat: add Rotator class for MCA ([`6adf45f`](https://github.com/nicrie/xeofs/commit/6adf45fe0d4a126726c503ab45469f3e488b4890)) +* feat: add Rotator class for MCA ([`6adf45f`](https://github.com/xarray-contrib/xeofs/commit/6adf45fe0d4a126726c503ab45469f3e488b4890)) ### Fix -* fix: add stabilizer for communalities during rotation ([`462f2fe`](https://github.com/nicrie/xeofs/commit/462f2fe9b30959076a815f3236b48d94c4467f32)) +* fix: add stabilizer for communalities during rotation ([`462f2fe`](https://github.com/xarray-contrib/xeofs/commit/462f2fe9b30959076a815f3236b48d94c4467f32)) -* fix: numpy and pandas classes did not consider axis parameter ([`8b75271`](https://github.com/nicrie/xeofs/commit/8b75271be096107f8a670f97ea6afe2d4e9740a9)) +* fix: numpy and pandas classes did not consider axis parameter ([`8b75271`](https://github.com/xarray-contrib/xeofs/commit/8b75271be096107f8a670f97ea6afe2d4e9740a9)) ### Refactor -* refactor: Merge branch 'main' of github.com:nicrie/xeofs into develop ([`73e2473`](https://github.com/nicrie/xeofs/commit/73e247383bd9340d717ce4e8d09637f97d963d03)) +* refactor: Merge branch 'main' of github.com:nicrie/xeofs into develop ([`73e2473`](https://github.com/xarray-contrib/xeofs/commit/73e247383bd9340d717ce4e8d09637f97d963d03)) ### Style -* style: correct an indent that prevented xeofs being published to pypi ([`1ee531c`](https://github.com/nicrie/xeofs/commit/1ee531c83f49125c8d8ce1f40a166a4fe4f5e78b)) +* style: correct an indent that prevented xeofs being published to pypi ([`1ee531c`](https://github.com/xarray-contrib/xeofs/commit/1ee531c83f49125c8d8ce1f40a166a4fe4f5e78b)) ### Test -* test: add simple test cases for MCA Rotator ([`900d76e`](https://github.com/nicrie/xeofs/commit/900d76ec1298b3c604c8734a41d8335a9446249e)) +* test: add simple test cases for MCA Rotator ([`900d76e`](https://github.com/xarray-contrib/xeofs/commit/900d76ec1298b3c604c8734a41d8335a9446249e)) ### Unknown * 0.7.0 -Automatically generated by python-semantic-release ([`924a97b`](https://github.com/nicrie/xeofs/commit/924a97b75250f1c270fa5c4298644c4347db3c4b)) +Automatically generated by python-semantic-release ([`924a97b`](https://github.com/xarray-contrib/xeofs/commit/924a97b75250f1c270fa5c4298644c4347db3c4b)) * Merge pull request #25 from nicrie/develop -Develop ([`4ddb5db`](https://github.com/nicrie/xeofs/commit/4ddb5db0a5f0234f3378fd889164c74b4bfaf388)) +Develop ([`4ddb5db`](https://github.com/xarray-contrib/xeofs/commit/4ddb5db0a5f0234f3378fd889164c74b4bfaf388)) * Merge pull request #24 from nicrie/develop -Develop ([`b79b1cd`](https://github.com/nicrie/xeofs/commit/b79b1cd3a2ef1d7f0ccdd3ac41980eeb90682391)) +Develop ([`b79b1cd`](https://github.com/xarray-contrib/xeofs/commit/b79b1cd3a2ef1d7f0ccdd3ac41980eeb90682391)) ## v0.6.0 (2022-08-22) ### Build -* build: remove defaults from anaconda channels when building readthedocs ([`0dbcf81`](https://github.com/nicrie/xeofs/commit/0dbcf81a95a357b4a2c83a531d056c9a0cb19245)) +* build: remove defaults from anaconda channels when building readthedocs ([`0dbcf81`](https://github.com/xarray-contrib/xeofs/commit/0dbcf81a95a357b4a2c83a531d056c9a0cb19245)) -* build: repair missing tqdm dependency ([`46fd5f2`](https://github.com/nicrie/xeofs/commit/46fd5f2f40d091bada75f1e48181fd4230b1e1d5)) +* build: repair missing tqdm dependency ([`46fd5f2`](https://github.com/xarray-contrib/xeofs/commit/46fd5f2f40d091bada75f1e48181fd4230b1e1d5)) -* build: add tqdm as dependency ([`0de85e5`](https://github.com/nicrie/xeofs/commit/0de85e5aa733d81836543fb02dba34387cf6ee18)) +* build: add tqdm as dependency ([`0de85e5`](https://github.com/xarray-contrib/xeofs/commit/0de85e5aa733d81836543fb02dba34387cf6ee18)) ### Chore -* chore: Merge branch 'main' into develop ([`14839d4`](https://github.com/nicrie/xeofs/commit/14839d4c0de8ef55cbebdec93387765b69d079fd)) +* chore: Merge branch 'main' into develop ([`14839d4`](https://github.com/xarray-contrib/xeofs/commit/14839d4c0de8ef55cbebdec93387765b69d079fd)) -* chore: Merge branch 'main' of github.com:nicrie/xeofs into main ([`00eb862`](https://github.com/nicrie/xeofs/commit/00eb8629e92bf3a9ce99201966cfdeb04fbbf57d)) +* chore: Merge branch 'main' of github.com:nicrie/xeofs into main ([`00eb862`](https://github.com/xarray-contrib/xeofs/commit/00eb8629e92bf3a9ce99201966cfdeb04fbbf57d)) ### Documentation -* docs: minor restructuring ([`dbdc885`](https://github.com/nicrie/xeofs/commit/dbdc8850befe142d567181250793202dc0e68c44)) +* docs: minor restructuring ([`dbdc885`](https://github.com/xarray-contrib/xeofs/commit/dbdc8850befe142d567181250793202dc0e68c44)) -* docs: remove some old examples ([`625dd08`](https://github.com/nicrie/xeofs/commit/625dd0827cd3bda178b3c83629d399947c1b5877)) +* docs: remove some old examples ([`625dd08`](https://github.com/xarray-contrib/xeofs/commit/625dd0827cd3bda178b3c83629d399947c1b5877)) -* docs: minor changes in text and example arrangements ([`b7f1628`](https://github.com/nicrie/xeofs/commit/b7f162800f012e816a6243cfe3e321cf7d9d3aeb)) +* docs: minor changes in text and example arrangements ([`b7f1628`](https://github.com/xarray-contrib/xeofs/commit/b7f162800f012e816a6243cfe3e321cf7d9d3aeb)) -* docs: update documentation and docstrings ([`b8fffdc`](https://github.com/nicrie/xeofs/commit/b8fffdc32387ed1ceea63674675d2ac437fe85d9)) +* docs: update documentation and docstrings ([`b8fffdc`](https://github.com/xarray-contrib/xeofs/commit/b8fffdc32387ed1ceea63674675d2ac437fe85d9)) -* docs: add MCA example ([`4fb881e`](https://github.com/nicrie/xeofs/commit/4fb881edcad9e7171d8045935ef32fa6a87caff0)) +* docs: add MCA example ([`4fb881e`](https://github.com/xarray-contrib/xeofs/commit/4fb881edcad9e7171d8045935ef32fa6a87caff0)) -* docs: reorganize examples ([`68d9db0`](https://github.com/nicrie/xeofs/commit/68d9db004ff23574fafb7b69cc85c7b2b33812c0)) +* docs: reorganize examples ([`68d9db0`](https://github.com/xarray-contrib/xeofs/commit/68d9db004ff23574fafb7b69cc85c7b2b33812c0)) -* docs: add figure to bootstrapping example ([`69894a0`](https://github.com/nicrie/xeofs/commit/69894a0363eda7886969ff7544ed069067bf1f51)) +* docs: add figure to bootstrapping example ([`69894a0`](https://github.com/xarray-contrib/xeofs/commit/69894a0363eda7886969ff7544ed069067bf1f51)) -* docs: add docstrings to bootstrapping methods ([`9c8145c`](https://github.com/nicrie/xeofs/commit/9c8145ccd26d1a5150f6c33bb157501cf6d42bca)) +* docs: add docstrings to bootstrapping methods ([`9c8145c`](https://github.com/xarray-contrib/xeofs/commit/9c8145ccd26d1a5150f6c33bb157501cf6d42bca)) -* docs: add simple example for bootstrapping ([`ba62057`](https://github.com/nicrie/xeofs/commit/ba620578b379636a0fff7e914bf753c1c5397f73)) +* docs: add simple example for bootstrapping ([`ba62057`](https://github.com/xarray-contrib/xeofs/commit/ba620578b379636a0fff7e914bf753c1c5397f73)) -* docs: add install instructions for conda ([`ef293e5`](https://github.com/nicrie/xeofs/commit/ef293e5a97b294c0aeea070a9b77fa33f214dcdf)) +* docs: add install instructions for conda ([`ef293e5`](https://github.com/xarray-contrib/xeofs/commit/ef293e5a97b294c0aeea070a9b77fa33f214dcdf)) -* docs: add zenodo badge ([`4f338ef`](https://github.com/nicrie/xeofs/commit/4f338ef473ac1e742452f130fef7604d0c33dc5f)) +* docs: add zenodo badge ([`4f338ef`](https://github.com/xarray-contrib/xeofs/commit/4f338ef473ac1e742452f130fef7604d0c33dc5f)) ### Feature -* feat: add MCA ([`34a82d1`](https://github.com/nicrie/xeofs/commit/34a82d103699cb1b1607e2418eb3c0889fad96fb)) +* feat: add MCA ([`34a82d1`](https://github.com/xarray-contrib/xeofs/commit/34a82d103699cb1b1607e2418eb3c0889fad96fb)) -* feat: add MCA support for xarray ([`e816e36`](https://github.com/nicrie/xeofs/commit/e816e3699928d19e828fe0bb41b5003bba6a264e)) +* feat: add MCA support for xarray ([`e816e36`](https://github.com/xarray-contrib/xeofs/commit/e816e3699928d19e828fe0bb41b5003bba6a264e)) -* feat: add MCA support for pandas ([`834d7dd`](https://github.com/nicrie/xeofs/commit/834d7dda131ffaf4336f775519f34228ddf62d69)) +* feat: add MCA support for pandas ([`834d7dd`](https://github.com/xarray-contrib/xeofs/commit/834d7dda131ffaf4336f775519f34228ddf62d69)) -* feat: add MCA support for numpy ([`8ded4df`](https://github.com/nicrie/xeofs/commit/8ded4df531281b3e19359a5d26f3e5bf4c2db320)) +* feat: add MCA support for numpy ([`8ded4df`](https://github.com/xarray-contrib/xeofs/commit/8ded4df531281b3e19359a5d26f3e5bf4c2db320)) -* feat: add MCA base class ([`58612e4`](https://github.com/nicrie/xeofs/commit/58612e40ad225ce4ca30757904e5f7836b3202bc)) +* feat: add MCA base class ([`58612e4`](https://github.com/xarray-contrib/xeofs/commit/58612e40ad225ce4ca30757904e5f7836b3202bc)) -* feat: add bootstrap methods ([`d5f6797`](https://github.com/nicrie/xeofs/commit/d5f6797ab087baabcdf71af325b0754bb3495477)) +* feat: add bootstrap methods ([`d5f6797`](https://github.com/xarray-contrib/xeofs/commit/d5f6797ab087baabcdf71af325b0754bb3495477)) -* feat: bootstrapper for xarray ([`f807ea6`](https://github.com/nicrie/xeofs/commit/f807ea6dd374e989bab0a95f1ac3e5fb0a9dc282)) +* feat: bootstrapper for xarray ([`f807ea6`](https://github.com/xarray-contrib/xeofs/commit/f807ea6dd374e989bab0a95f1ac3e5fb0a9dc282)) -* feat: bootstrapper for pandas ([`a32b1d3`](https://github.com/nicrie/xeofs/commit/a32b1d30a33d695b4c49a121fc343d57a68ec3d4)) +* feat: bootstrapper for pandas ([`a32b1d3`](https://github.com/xarray-contrib/xeofs/commit/a32b1d30a33d695b4c49a121fc343d57a68ec3d4)) -* feat: bootstrapper for numpy class ([`c5923b3`](https://github.com/nicrie/xeofs/commit/c5923b3822178f9ad63837ea841dbe408e8cb3f0)) +* feat: bootstrapper for numpy class ([`c5923b3`](https://github.com/xarray-contrib/xeofs/commit/c5923b3822178f9ad63837ea841dbe408e8cb3f0)) -* feat: bootstrapper base class ([`f4ee31a`](https://github.com/nicrie/xeofs/commit/f4ee31a9fe83637c1a641f6d1d05844ed15c0ba7)) +* feat: bootstrapper base class ([`f4ee31a`](https://github.com/xarray-contrib/xeofs/commit/f4ee31a9fe83637c1a641f6d1d05844ed15c0ba7)) ### Fix -* fix: set informative names of Dataframes and DataArrays ([`b5b5286`](https://github.com/nicrie/xeofs/commit/b5b528678becdf80b511a3883485304341c09692)) +* fix: set informative names of Dataframes and DataArrays ([`b5b5286`](https://github.com/xarray-contrib/xeofs/commit/b5b528678becdf80b511a3883485304341c09692)) ### Style -* style: refer to issue why nodefaults is necessary ([`2aed6f3`](https://github.com/nicrie/xeofs/commit/2aed6f35e67881f8ecda291d927f7991f89aea3b)) +* style: refer to issue why nodefaults is necessary ([`2aed6f3`](https://github.com/xarray-contrib/xeofs/commit/2aed6f35e67881f8ecda291d927f7991f89aea3b)) -* style: remove some comments ([`4eae075`](https://github.com/nicrie/xeofs/commit/4eae075f13baa10677b84db608071ee859858085)) +* style: remove some comments ([`4eae075`](https://github.com/xarray-contrib/xeofs/commit/4eae075f13baa10677b84db608071ee859858085)) ### Test -* test: add MCA test wrapper ([`eb2a280`](https://github.com/nicrie/xeofs/commit/eb2a2808259454adfaba0ce35dff75a445ccab29)) +* test: add MCA test wrapper ([`eb2a280`](https://github.com/xarray-contrib/xeofs/commit/eb2a2808259454adfaba0ce35dff75a445ccab29)) -* test: simple tests for Bootstrapper to compile without error ([`ca3141a`](https://github.com/nicrie/xeofs/commit/ca3141a4eff602eb808c0ec30530bf2cddb1d14d)) +* test: simple tests for Bootstrapper to compile without error ([`ca3141a`](https://github.com/xarray-contrib/xeofs/commit/ca3141a4eff602eb808c0ec30530bf2cddb1d14d)) ### Unknown * 0.6.0 -Automatically generated by python-semantic-release ([`b03704c`](https://github.com/nicrie/xeofs/commit/b03704c458b3e38e0762a36192e6e85fa4ee18ba)) +Automatically generated by python-semantic-release ([`b03704c`](https://github.com/xarray-contrib/xeofs/commit/b03704c458b3e38e0762a36192e6e85fa4ee18ba)) * Merge pull request #23 from nicrie/develop -Develop ([`e9d02a1`](https://github.com/nicrie/xeofs/commit/e9d02a12c8b962d2892d4a15bfa657832c5ac1c9)) +Develop ([`e9d02a1`](https://github.com/xarray-contrib/xeofs/commit/e9d02a12c8b962d2892d4a15bfa657832c5ac1c9)) * Merge pull request #18 from nicrie/develop -Add conda install instructions ([`4c0ed49`](https://github.com/nicrie/xeofs/commit/4c0ed49b45794ce0abb641c98b82638b2faa4828)) +Add conda install instructions ([`4c0ed49`](https://github.com/xarray-contrib/xeofs/commit/4c0ed49b45794ce0abb641c98b82638b2faa4828)) ## v0.5.0 (2022-03-12) ### Build -* build: loose numpy version constrain ([`375d675`](https://github.com/nicrie/xeofs/commit/375d6759e388eee1597eacdc7e472b6433422db6)) +* build: loose numpy version constrain ([`375d675`](https://github.com/xarray-contrib/xeofs/commit/375d6759e388eee1597eacdc7e472b6433422db6)) ### Documentation -* docs: update README ([`fdc76ee`](https://github.com/nicrie/xeofs/commit/fdc76ee567d442cc310571b808a6947774f23e06)) +* docs: update README ([`fdc76ee`](https://github.com/xarray-contrib/xeofs/commit/fdc76ee567d442cc310571b808a6947774f23e06)) -* docs: add example for multivariate EOF analysis ([`59a1f1b`](https://github.com/nicrie/xeofs/commit/59a1f1be37bb1bed5d9288841ddde891c03c7600)) +* docs: add example for multivariate EOF analysis ([`59a1f1b`](https://github.com/xarray-contrib/xeofs/commit/59a1f1be37bb1bed5d9288841ddde891c03c7600)) -* docs: add example ([`07b3bb8`](https://github.com/nicrie/xeofs/commit/07b3bb8d72f2f850dfa61e08613954b7c11cc99a)) +* docs: add example ([`07b3bb8`](https://github.com/xarray-contrib/xeofs/commit/07b3bb8d72f2f850dfa61e08613954b7c11cc99a)) -* docs: add example for multivariate EOF analysis ([`7ae2ae8`](https://github.com/nicrie/xeofs/commit/7ae2ae8180a0f997c2f31d45eba5daa747c9900d)) +* docs: add example for multivariate EOF analysis ([`7ae2ae8`](https://github.com/xarray-contrib/xeofs/commit/7ae2ae8180a0f997c2f31d45eba5daa747c9900d)) -* docs: add zenodo badge ([`7792953`](https://github.com/nicrie/xeofs/commit/7792953e478eeb0e772563999a6ee0688d06ad76)) +* docs: add zenodo badge ([`7792953`](https://github.com/xarray-contrib/xeofs/commit/7792953e478eeb0e772563999a6ee0688d06ad76)) ### Feature -* feat: add support for multivariate EOF analysis ([`53961d9`](https://github.com/nicrie/xeofs/commit/53961d974cda8bc6b24466c496058efc4d676a4b)) +* feat: add support for multivariate EOF analysis ([`53961d9`](https://github.com/xarray-contrib/xeofs/commit/53961d974cda8bc6b24466c496058efc4d676a4b)) -* feat: Merge branch 'main' into develop ([`6d2d646`](https://github.com/nicrie/xeofs/commit/6d2d6469768d3b91c63358d561b63f9581ebf2a8)) +* feat: Merge branch 'main' into develop ([`6d2d646`](https://github.com/xarray-contrib/xeofs/commit/6d2d6469768d3b91c63358d561b63f9581ebf2a8)) -* feat: add support for multivariate EOF analysis ([`fa9503a`](https://github.com/nicrie/xeofs/commit/fa9503a2a789404471b2d85121d54e575a83128c)) +* feat: add support for multivariate EOF analysis ([`fa9503a`](https://github.com/xarray-contrib/xeofs/commit/fa9503a2a789404471b2d85121d54e575a83128c)) ### Refactor -* refactor: tests for new transformer definition ([`cf330ff`](https://github.com/nicrie/xeofs/commit/cf330ffb0dca2184398a1bb6bd49a3cc456af586)) +* refactor: tests for new transformer definition ([`cf330ff`](https://github.com/xarray-contrib/xeofs/commit/cf330ffb0dca2184398a1bb6bd49a3cc456af586)) -* refactor: consistent transformer and multi_transformer definition ([`9445769`](https://github.com/nicrie/xeofs/commit/9445769253c2014aa85ba45b73cb08f13664f4b4)) +* refactor: consistent transformer and multi_transformer definition ([`9445769`](https://github.com/xarray-contrib/xeofs/commit/9445769253c2014aa85ba45b73cb08f13664f4b4)) -* refactor: remove class MultivariateEOF ([`4fa1ff8`](https://github.com/nicrie/xeofs/commit/4fa1ff873557ad63659507a94a0e0f6f3ff5a1f7)) +* refactor: remove class MultivariateEOF ([`4fa1ff8`](https://github.com/xarray-contrib/xeofs/commit/4fa1ff873557ad63659507a94a0e0f6f3ff5a1f7)) ### Test -* test: multivariate EOF analysis ([`b0d0b33`](https://github.com/nicrie/xeofs/commit/b0d0b33ea75b1359d110b531aa7da0d884a06acd)) +* test: multivariate EOF analysis ([`b0d0b33`](https://github.com/xarray-contrib/xeofs/commit/b0d0b33ea75b1359d110b531aa7da0d884a06acd)) ### Unknown * 0.5.0 -Automatically generated by python-semantic-release ([`501b330`](https://github.com/nicrie/xeofs/commit/501b330ae7905cd0ebe92b8fa3a0153fcd6755b1)) +Automatically generated by python-semantic-release ([`501b330`](https://github.com/xarray-contrib/xeofs/commit/501b330ae7905cd0ebe92b8fa3a0153fcd6755b1)) * Merge pull request #17 from nicrie/develop -Release 0.5.0 ([`a830a54`](https://github.com/nicrie/xeofs/commit/a830a5435b01faf6609f2297f6e3669e6c0c9891)) +Release 0.5.0 ([`a830a54`](https://github.com/xarray-contrib/xeofs/commit/a830a5435b01faf6609f2297f6e3669e6c0c9891)) ## v0.4.0 (2022-03-02) ### Documentation -* docs: update README ([`5693fe9`](https://github.com/nicrie/xeofs/commit/5693fe9f2e2b10f1d0c364d0aba1eb47c84e9bc9)) +* docs: update README ([`5693fe9`](https://github.com/xarray-contrib/xeofs/commit/5693fe9f2e2b10f1d0c364d0aba1eb47c84e9bc9)) -* docs: fix typo ([`d5505c6`](https://github.com/nicrie/xeofs/commit/d5505c6c6e9a010cb836b609ebbf7dac6b38f67e)) +* docs: fix typo ([`d5505c6`](https://github.com/xarray-contrib/xeofs/commit/d5505c6c6e9a010cb836b609ebbf7dac6b38f67e)) -* docs: update README ([`982d7e3`](https://github.com/nicrie/xeofs/commit/982d7e3520937b4b696beaa5a4753267a2278280)) +* docs: update README ([`982d7e3`](https://github.com/xarray-contrib/xeofs/commit/982d7e3520937b4b696beaa5a4753267a2278280)) -* docs: update README ([`c52763b`](https://github.com/nicrie/xeofs/commit/c52763bbdb4de3f261d996db47125cf44edb6113)) +* docs: update README ([`c52763b`](https://github.com/xarray-contrib/xeofs/commit/c52763bbdb4de3f261d996db47125cf44edb6113)) -* docs: update README ([`2d00a71`](https://github.com/nicrie/xeofs/commit/2d00a7126f5248dd766815071857e5c1af63bd28)) +* docs: update README ([`2d00a71`](https://github.com/xarray-contrib/xeofs/commit/2d00a7126f5248dd766815071857e5c1af63bd28)) -* docs: update README ([`8c8cb29`](https://github.com/nicrie/xeofs/commit/8c8cb29a52496302fa2893f74aa05a9d855fb005)) +* docs: update README ([`8c8cb29`](https://github.com/xarray-contrib/xeofs/commit/8c8cb29a52496302fa2893f74aa05a9d855fb005)) -* docs: update README ([`58f539b`](https://github.com/nicrie/xeofs/commit/58f539b2d353875d3a3d6da7707f4a1b69079755)) +* docs: update README ([`58f539b`](https://github.com/xarray-contrib/xeofs/commit/58f539b2d353875d3a3d6da7707f4a1b69079755)) -* docs: add project_onto_eofs to autosummary ([`af7d1f2`](https://github.com/nicrie/xeofs/commit/af7d1f29a33e0e782c9f1cc58932f95f729ee1a6)) +* docs: add project_onto_eofs to autosummary ([`af7d1f2`](https://github.com/xarray-contrib/xeofs/commit/af7d1f29a33e0e782c9f1cc58932f95f729ee1a6)) -* docs: update docs ([`28e248b`](https://github.com/nicrie/xeofs/commit/28e248b26b840e487370bf7d33ab73fb6b445ce4)) +* docs: update docs ([`28e248b`](https://github.com/xarray-contrib/xeofs/commit/28e248b26b840e487370bf7d33ab73fb6b445ce4)) -* docs: add eofs as correlations ([`64c60c1`](https://github.com/nicrie/xeofs/commit/64c60c136ba39805ac9c4886f2f635efdc1e7eb4)) +* docs: add eofs as correlations ([`64c60c1`](https://github.com/xarray-contrib/xeofs/commit/64c60c136ba39805ac9c4886f2f635efdc1e7eb4)) -* docs: update README ([`29f1b4d`](https://github.com/nicrie/xeofs/commit/29f1b4d7c592038d9402ba68fe61cd94b9f72045)) +* docs: update README ([`29f1b4d`](https://github.com/xarray-contrib/xeofs/commit/29f1b4d7c592038d9402ba68fe61cd94b9f72045)) -* docs: remove older version of sphinx-gallery ([`938f294`](https://github.com/nicrie/xeofs/commit/938f2947a91074ebafb4d031403d5c7b2ee3e539)) +* docs: remove older version of sphinx-gallery ([`938f294`](https://github.com/xarray-contrib/xeofs/commit/938f2947a91074ebafb4d031403d5c7b2ee3e539)) -* docs: too many "install" ;) ([`ea66ba6`](https://github.com/nicrie/xeofs/commit/ea66ba65be9a33fa99d6b648cec5fc69cde64b85)) +* docs: too many "install" ;) ([`ea66ba6`](https://github.com/xarray-contrib/xeofs/commit/ea66ba65be9a33fa99d6b648cec5fc69cde64b85)) -* docs: forgot to specifiy master branch ([`2c827ba`](https://github.com/nicrie/xeofs/commit/2c827ba0e73526cd711f280911025807d2e40837)) +* docs: forgot to specifiy master branch ([`2c827ba`](https://github.com/xarray-contrib/xeofs/commit/2c827ba0e73526cd711f280911025807d2e40837)) -* docs: install current master branch of sphinx-gallery ([`8426033`](https://github.com/nicrie/xeofs/commit/8426033b89b01bac1154532d82967f07c694db42)) +* docs: install current master branch of sphinx-gallery ([`8426033`](https://github.com/xarray-contrib/xeofs/commit/8426033b89b01bac1154532d82967f07c694db42)) -* docs: update links to examples ([`44a4353`](https://github.com/nicrie/xeofs/commit/44a4353c648080aedaa62701d1efba7f757b3e32)) +* docs: update links to examples ([`44a4353`](https://github.com/xarray-contrib/xeofs/commit/44a4353c648080aedaa62701d1efba7f757b3e32)) -* docs: add matplotlib to environment to generate example ([`2346fcb`](https://github.com/nicrie/xeofs/commit/2346fcb0b2f8b4b4c62d3bd87891ed107914634c)) +* docs: add matplotlib to environment to generate example ([`2346fcb`](https://github.com/xarray-contrib/xeofs/commit/2346fcb0b2f8b4b4c62d3bd87891ed107914634c)) -* docs: update examples ([`5795ffa`](https://github.com/nicrie/xeofs/commit/5795ffa0e6902abb536c8912f7b55874b9a141b6)) +* docs: update examples ([`5795ffa`](https://github.com/xarray-contrib/xeofs/commit/5795ffa0e6902abb536c8912f7b55874b9a141b6)) ### Feature -* feat: add base and xarray class for multivariate EOF analysis ([`5ba07f0`](https://github.com/nicrie/xeofs/commit/5ba07f0e7c211e9b1a19a44d66d85d3ffc30a4d3)) +* feat: add base and xarray class for multivariate EOF analysis ([`5ba07f0`](https://github.com/xarray-contrib/xeofs/commit/5ba07f0e7c211e9b1a19a44d66d85d3ffc30a4d3)) -* feat: project new data onto EOFs and rotated EOFs ([`d8b0e57`](https://github.com/nicrie/xeofs/commit/d8b0e57622bc6dec1b45ac94821eaf369a335704)) +* feat: project new data onto EOFs and rotated EOFs ([`d8b0e57`](https://github.com/xarray-contrib/xeofs/commit/d8b0e57622bc6dec1b45ac94821eaf369a335704)) -* feat: project unseen data onto rotated EOFs ([`63b2d3a`](https://github.com/nicrie/xeofs/commit/63b2d3afdcb9b170b3fdbe5d38a6386463423e4a)) +* feat: project unseen data onto rotated EOFs ([`63b2d3a`](https://github.com/xarray-contrib/xeofs/commit/63b2d3afdcb9b170b3fdbe5d38a6386463423e4a)) -* feat: project unseen data onto EOFs ([`341546b`](https://github.com/nicrie/xeofs/commit/341546b8b74cb1f91105aefd409fab8a087cca9a)) +* feat: project unseen data onto EOFs ([`341546b`](https://github.com/xarray-contrib/xeofs/commit/341546b8b74cb1f91105aefd409fab8a087cca9a)) -* feat: project unseen data onto EOFs ([`64e38b1`](https://github.com/nicrie/xeofs/commit/64e38b120a5c7e16431551e4c80f9b4a2a515eb4)) +* feat: project unseen data onto EOFs ([`64e38b1`](https://github.com/xarray-contrib/xeofs/commit/64e38b120a5c7e16431551e4c80f9b4a2a515eb4)) -* feat: allow to reconstruct original data with arbitrary mode combination ([`be095d7`](https://github.com/nicrie/xeofs/commit/be095d77d5d452853a36a6719c7de8edf17bed5b)) +* feat: allow to reconstruct original data with arbitrary mode combination ([`be095d7`](https://github.com/xarray-contrib/xeofs/commit/be095d77d5d452853a36a6719c7de8edf17bed5b)) -* feat: reconstruct input data after rotation ([`0c9479e`](https://github.com/nicrie/xeofs/commit/0c9479e59a4a016f442b532889437e38c4a0e9bf)) +* feat: reconstruct input data after rotation ([`0c9479e`](https://github.com/xarray-contrib/xeofs/commit/0c9479e59a4a016f442b532889437e38c4a0e9bf)) -* feat: reconstruct input data for EOF analysis ([`7ed306a`](https://github.com/nicrie/xeofs/commit/7ed306add5bd7cc9ef9b2e14d486fd7887c1d388)) +* feat: reconstruct input data for EOF analysis ([`7ed306a`](https://github.com/xarray-contrib/xeofs/commit/7ed306add5bd7cc9ef9b2e14d486fd7887c1d388)) -* feat: allow different scalings of EOFs an PCs ([`ea39f02`](https://github.com/nicrie/xeofs/commit/ea39f023e1c0cf980063caf2bc2fa7daaac7c8ab)) +* feat: allow different scalings of EOFs an PCs ([`ea39f02`](https://github.com/xarray-contrib/xeofs/commit/ea39f023e1c0cf980063caf2bc2fa7daaac7c8ab)) -* feat: add scaling for PCs and EOFs ([`c2c6fe1`](https://github.com/nicrie/xeofs/commit/c2c6fe190b7a481f3c9193b1ce541c57e3a80e94)) +* feat: add scaling for PCs and EOFs ([`c2c6fe1`](https://github.com/xarray-contrib/xeofs/commit/c2c6fe190b7a481f3c9193b1ce541c57e3a80e94)) -* feat: add eofs as correlation ([`85960ab`](https://github.com/nicrie/xeofs/commit/85960abf96283978748e283053175577211ade74)) +* feat: add eofs as correlation ([`85960ab`](https://github.com/xarray-contrib/xeofs/commit/85960abf96283978748e283053175577211ade74)) -* feat: eofs as correlation for rotated EOF analysis ([`cb8c472`](https://github.com/nicrie/xeofs/commit/cb8c472f12906d8b2d2750847b1ae62a741fb4f8)) +* feat: eofs as correlation for rotated EOF analysis ([`cb8c472`](https://github.com/xarray-contrib/xeofs/commit/cb8c472f12906d8b2d2750847b1ae62a741fb4f8)) -* feat: eofs as correlation for EOF analysis ([`e53d449`](https://github.com/nicrie/xeofs/commit/e53d4494c96b6335911a79c325382ddc0a57fae4)) +* feat: eofs as correlation for EOF analysis ([`e53d449`](https://github.com/xarray-contrib/xeofs/commit/e53d4494c96b6335911a79c325382ddc0a57fae4)) ### Fix -* fix: fix incorrect dof for rotated PC scaling ([`addeb82`](https://github.com/nicrie/xeofs/commit/addeb82b0c68f5ffbd6c3f9559503cf88c1ba525)) +* fix: fix incorrect dof for rotated PC scaling ([`addeb82`](https://github.com/xarray-contrib/xeofs/commit/addeb82b0c68f5ffbd6c3f9559503cf88c1ba525)) -* fix: PC projections was missing -1 correction for degrees of freedom ([`a243a26`](https://github.com/nicrie/xeofs/commit/a243a26cce09d29b318cb28011e815916f25c2e4)) +* fix: PC projections was missing -1 correction for degrees of freedom ([`a243a26`](https://github.com/xarray-contrib/xeofs/commit/a243a26cce09d29b318cb28011e815916f25c2e4)) -* fix: back_transform automatically add feature coords ([`0fef30d`](https://github.com/nicrie/xeofs/commit/0fef30da1bfea0d5b26070474fbe2ee826997dd4)) +* fix: back_transform automatically add feature coords ([`0fef30d`](https://github.com/xarray-contrib/xeofs/commit/0fef30da1bfea0d5b26070474fbe2ee826997dd4)) ### Refactor -* refactor: consistent class names in tests ([`40416fa`](https://github.com/nicrie/xeofs/commit/40416fa8adde618932128721f81d0368e544da60)) +* refactor: consistent class names in tests ([`40416fa`](https://github.com/xarray-contrib/xeofs/commit/40416fa8adde618932128721f81d0368e544da60)) -* refactor: consistent class names ([`5d59fad`](https://github.com/nicrie/xeofs/commit/5d59fade36e76b740a09591b3223dcd82e24392d)) +* refactor: consistent class names ([`5d59fad`](https://github.com/xarray-contrib/xeofs/commit/5d59fade36e76b740a09591b3223dcd82e24392d)) -* refactor: dataframe and dataarray transformer return index and coords ([`1c6252a`](https://github.com/nicrie/xeofs/commit/1c6252aa0b9556972d9268d2a9232c3f006e9c7b)) +* refactor: dataframe and dataarray transformer return index and coords ([`1c6252a`](https://github.com/xarray-contrib/xeofs/commit/1c6252aa0b9556972d9268d2a9232c3f006e9c7b)) -* refactor: helper fuction for mode selection ([`318e8ea`](https://github.com/nicrie/xeofs/commit/318e8ea68a559574721bb6c2eecf6b3bbfdcf7ab)) +* refactor: helper fuction for mode selection ([`318e8ea`](https://github.com/xarray-contrib/xeofs/commit/318e8ea68a559574721bb6c2eecf6b3bbfdcf7ab)) ### Style -* style: remove comments ([`835951b`](https://github.com/nicrie/xeofs/commit/835951b8033c7e4960779f4356b8b81a94d83f8b)) +* style: remove comments ([`835951b`](https://github.com/xarray-contrib/xeofs/commit/835951b8033c7e4960779f4356b8b81a94d83f8b)) ### Test -* test: projection onto EOFs ([`49dc6d8`](https://github.com/nicrie/xeofs/commit/49dc6d8e7a885ee22c881b4726c931615485920d)) +* test: projection onto EOFs ([`49dc6d8`](https://github.com/xarray-contrib/xeofs/commit/49dc6d8e7a885ee22c881b4726c931615485920d)) -* test: add tests for reconstruct_X ([`1029f0c`](https://github.com/nicrie/xeofs/commit/1029f0c9a59cfc17b8ecc3d486eb9de349d8626c)) +* test: add tests for reconstruct_X ([`1029f0c`](https://github.com/xarray-contrib/xeofs/commit/1029f0c9a59cfc17b8ecc3d486eb9de349d8626c)) -* test: add scaling to wrapper tests ([`7cad9fe`](https://github.com/nicrie/xeofs/commit/7cad9fe6816e42384676e4259edf4e93f743dd85)) +* test: add scaling to wrapper tests ([`7cad9fe`](https://github.com/xarray-contrib/xeofs/commit/7cad9fe6816e42384676e4259edf4e93f743dd85)) -* test: eof as correlation ([`d84454c`](https://github.com/nicrie/xeofs/commit/d84454c6ab9ef547b80b8911b6278780b141bd49)) +* test: eof as correlation ([`d84454c`](https://github.com/xarray-contrib/xeofs/commit/d84454c6ab9ef547b80b8911b6278780b141bd49)) ### Unknown * 0.4.0 -Automatically generated by python-semantic-release ([`934677b`](https://github.com/nicrie/xeofs/commit/934677bacb4262bc1ddb93a109a0f9e0eeb157ed)) +Automatically generated by python-semantic-release ([`934677b`](https://github.com/xarray-contrib/xeofs/commit/934677bacb4262bc1ddb93a109a0f9e0eeb157ed)) * Merge pull request #16 from nicrie/develop -Develop ([`6a645c9`](https://github.com/nicrie/xeofs/commit/6a645c98f90f64beeff4e10f2c3f7cacddc47f35)) +Develop ([`6a645c9`](https://github.com/xarray-contrib/xeofs/commit/6a645c98f90f64beeff4e10f2c3f7cacddc47f35)) * Merge pull request #15 from nicrie/develop -docs: update README ([`d3bcac2`](https://github.com/nicrie/xeofs/commit/d3bcac2b5fa7ccfb6f2d8d302a7acc624c11197b)) +docs: update README ([`d3bcac2`](https://github.com/xarray-contrib/xeofs/commit/d3bcac2b5fa7ccfb6f2d8d302a7acc624c11197b)) ## v0.3.0 (2022-02-20) ### Documentation -* docs: add example for rotated EOF analysis ([`efc364a`](https://github.com/nicrie/xeofs/commit/efc364a925b33a167bfdfdbb71fd73ebd7b6c6f7)) +* docs: add example for rotated EOF analysis ([`efc364a`](https://github.com/xarray-contrib/xeofs/commit/efc364a925b33a167bfdfdbb71fd73ebd7b6c6f7)) -* docs: add example for weigted EOF analysis ([`9dedab2`](https://github.com/nicrie/xeofs/commit/9dedab2a25a0f18595e618ca986abe0b57b5a23f)) +* docs: add example for weigted EOF analysis ([`9dedab2`](https://github.com/xarray-contrib/xeofs/commit/9dedab2a25a0f18595e618ca986abe0b57b5a23f)) -* docs: some minor changes in examples ([`9611eea`](https://github.com/nicrie/xeofs/commit/9611eeac466078ac4e008373005e7cd0c98607bd)) +* docs: some minor changes in examples ([`9611eea`](https://github.com/xarray-contrib/xeofs/commit/9611eeac466078ac4e008373005e7cd0c98607bd)) -* docs: add EOF s-mode and t-mode gallery example ([`5f371b7`](https://github.com/nicrie/xeofs/commit/5f371b7ee52b64315a8c7940bb993605823e4455)) +* docs: add EOF s-mode and t-mode gallery example ([`5f371b7`](https://github.com/xarray-contrib/xeofs/commit/5f371b7ee52b64315a8c7940bb993605823e4455)) ### Feature -* feat: add Varimax and Promax rotation ([`b42ba16`](https://github.com/nicrie/xeofs/commit/b42ba160f183d7a22a8555b19bf7de340663742b)) +* feat: add Varimax and Promax rotation ([`b42ba16`](https://github.com/xarray-contrib/xeofs/commit/b42ba160f183d7a22a8555b19bf7de340663742b)) -* feat: add Rotator interface for numpy, pandas, xarray ([`050b883`](https://github.com/nicrie/xeofs/commit/050b883113166811bd5f8e6dc35cfcb162fa7503)) +* feat: add Rotator interface for numpy, pandas, xarray ([`050b883`](https://github.com/xarray-contrib/xeofs/commit/050b883113166811bd5f8e6dc35cfcb162fa7503)) -* feat: add varimax and promax algorithms ([`f1e928f`](https://github.com/nicrie/xeofs/commit/f1e928fcb20f2ccfa2f450d2ba45230d01ba1e4c)) +* feat: add varimax and promax algorithms ([`f1e928f`](https://github.com/xarray-contrib/xeofs/commit/f1e928fcb20f2ccfa2f450d2ba45230d01ba1e4c)) -* feat: add Rotator base class ([`d024d81`](https://github.com/nicrie/xeofs/commit/d024d8151429d4bfd6a374207168421ac02242c2)) +* feat: add Rotator base class ([`d024d81`](https://github.com/xarray-contrib/xeofs/commit/d024d8151429d4bfd6a374207168421ac02242c2)) -* feat: Add support for weighted EOF analysis including coslat weighting ([`654b437`](https://github.com/nicrie/xeofs/commit/654b437f64bf5c6dc9be811e891de2c5d1a3d2d9)) +* feat: Add support for weighted EOF analysis including coslat weighting ([`654b437`](https://github.com/xarray-contrib/xeofs/commit/654b437f64bf5c6dc9be811e891de2c5d1a3d2d9)) -* feat: add weight support to EOF classes ([`8821108`](https://github.com/nicrie/xeofs/commit/882110879a31af5b632efb5a39bf6d6afebe2fb7)) +* feat: add weight support to EOF classes ([`8821108`](https://github.com/xarray-contrib/xeofs/commit/882110879a31af5b632efb5a39bf6d6afebe2fb7)) -* feat: add weight transformer ([`52b98e6`](https://github.com/nicrie/xeofs/commit/52b98e6189d144bba4320ceb0dd2c43c1548e8c9)) +* feat: add weight transformer ([`52b98e6`](https://github.com/xarray-contrib/xeofs/commit/52b98e6189d144bba4320ceb0dd2c43c1548e8c9)) ### Fix -* fix: incorrect number of mode index for DataArray caller ([`4e610ac`](https://github.com/nicrie/xeofs/commit/4e610aca9b2db726c6351f2615adbb482d011722)) +* fix: incorrect number of mode index for DataArray caller ([`4e610ac`](https://github.com/xarray-contrib/xeofs/commit/4e610aca9b2db726c6351f2615adbb482d011722)) -* fix: always center data X ([`4a58dfc`](https://github.com/nicrie/xeofs/commit/4a58dfc0cc400aa3b20ae0d2c904969d0e19109b)) +* fix: always center data X ([`4a58dfc`](https://github.com/xarray-contrib/xeofs/commit/4a58dfc0cc400aa3b20ae0d2c904969d0e19109b)) -* fix: coslat error was too restrictive ([`faece55`](https://github.com/nicrie/xeofs/commit/faece55ccdfaa91f73b6dcce74959dead9736388)) +* fix: coslat error was too restrictive ([`faece55`](https://github.com/xarray-contrib/xeofs/commit/faece55ccdfaa91f73b6dcce74959dead9736388)) -* fix: add error messages when calling invalid coslat weighting ([`6104e69`](https://github.com/nicrie/xeofs/commit/6104e69b297f42c7aef68e20ca753394fc9a50c8)) +* fix: add error messages when calling invalid coslat weighting ([`6104e69`](https://github.com/xarray-contrib/xeofs/commit/6104e69b297f42c7aef68e20ca753394fc9a50c8)) ### Style -* style: rename mode_idx to idx_mode ([`ac89e3b`](https://github.com/nicrie/xeofs/commit/ac89e3bc07c0d0a64bd50442e54c15f95715629c)) +* style: rename mode_idx to idx_mode ([`ac89e3b`](https://github.com/xarray-contrib/xeofs/commit/ac89e3bc07c0d0a64bd50442e54c15f95715629c)) -* style: rename mode_idx to idx_mode ([`d0508b1`](https://github.com/nicrie/xeofs/commit/d0508b1f9be2be897f644aaa69807c9adeed0ea1)) +* style: rename mode_idx to idx_mode ([`d0508b1`](https://github.com/xarray-contrib/xeofs/commit/d0508b1f9be2be897f644aaa69807c9adeed0ea1)) ### Test -* test: add test for Rotator classes ([`bb783e7`](https://github.com/nicrie/xeofs/commit/bb783e727b6bfed92eba38ca54a314d90963f838)) +* test: add test for Rotator classes ([`bb783e7`](https://github.com/xarray-contrib/xeofs/commit/bb783e727b6bfed92eba38ca54a314d90963f838)) -* test: verify against normalized PCs ([`48f054f`](https://github.com/nicrie/xeofs/commit/48f054fbf34bf25b71de965f2390fbfae7d247f1)) +* test: verify against normalized PCs ([`48f054f`](https://github.com/xarray-contrib/xeofs/commit/48f054fbf34bf25b71de965f2390fbfae7d247f1)) -* test: add simple test for coslat weighting ([`793148b`](https://github.com/nicrie/xeofs/commit/793148ba0af84dbe21add0d0c25dfebe5e402889)) +* test: add simple test for coslat weighting ([`793148b`](https://github.com/xarray-contrib/xeofs/commit/793148ba0af84dbe21add0d0c25dfebe5e402889)) -* test: add tests for weights ([`318b225`](https://github.com/nicrie/xeofs/commit/318b225a43939b2f23cf38f937c68e6fb1c91bb5)) +* test: add tests for weights ([`318b225`](https://github.com/xarray-contrib/xeofs/commit/318b225a43939b2f23cf38f937c68e6fb1c91bb5)) -* test: add array fixtures with arbitrary shapes ([`7021ef6`](https://github.com/nicrie/xeofs/commit/7021ef665faedd3540bc02a478ac0d37b0db1876)) +* test: add array fixtures with arbitrary shapes ([`7021ef6`](https://github.com/xarray-contrib/xeofs/commit/7021ef665faedd3540bc02a478ac0d37b0db1876)) ### Unknown * 0.3.0 -Automatically generated by python-semantic-release ([`fa9c69d`](https://github.com/nicrie/xeofs/commit/fa9c69d11c12028946bf87bea4869041c4c56207)) +Automatically generated by python-semantic-release ([`fa9c69d`](https://github.com/xarray-contrib/xeofs/commit/fa9c69d11c12028946bf87bea4869041c4c56207)) * Merge pull request #13 from nicrie/develop -Develop ([`0128e40`](https://github.com/nicrie/xeofs/commit/0128e409983aa80908f1ce244a5254e68419f388)) +Develop ([`0128e40`](https://github.com/xarray-contrib/xeofs/commit/0128e409983aa80908f1ce244a5254e68419f388)) * Merge pull request #10 from nicrie/develop -docs: add EOF s-mode and t-mode gallery example ([`a446135`](https://github.com/nicrie/xeofs/commit/a446135962c1a5a3f3588a08c2e572cf8d19ac2f)) +docs: add EOF s-mode and t-mode gallery example ([`a446135`](https://github.com/xarray-contrib/xeofs/commit/a446135962c1a5a3f3588a08c2e572cf8d19ac2f)) -* Merge branch 'main' into develop ([`7049abd`](https://github.com/nicrie/xeofs/commit/7049abddda7f07263a7409603007d2d5dc76ae59)) +* Merge branch 'main' into develop ([`7049abd`](https://github.com/xarray-contrib/xeofs/commit/7049abddda7f07263a7409603007d2d5dc76ae59)) ## v0.2.0 (2022-02-17) ### Chore -* chore: Merge branch 'main' into develop ([`e1c3534`](https://github.com/nicrie/xeofs/commit/e1c3534940473a266be52686ae01307a0109e548)) +* chore: Merge branch 'main' into develop ([`e1c3534`](https://github.com/xarray-contrib/xeofs/commit/e1c3534940473a266be52686ae01307a0109e548)) ### Documentation -* docs: add download badge ([`9a96fd1`](https://github.com/nicrie/xeofs/commit/9a96fd1e8d589b4c80b4498224f1851ec0428565)) +* docs: add download badge ([`9a96fd1`](https://github.com/xarray-contrib/xeofs/commit/9a96fd1e8d589b4c80b4498224f1851ec0428565)) -* docs: solve readthedoc version issue by installing xeofs first ([`7afdd78`](https://github.com/nicrie/xeofs/commit/7afdd78af786ca5048c748ea09985aecc0d9b7b0)) +* docs: solve readthedoc version issue by installing xeofs first ([`7afdd78`](https://github.com/xarray-contrib/xeofs/commit/7afdd78af786ca5048c748ea09985aecc0d9b7b0)) -* docs: try to solve the readthedocs issue with importlib ([`b4cdd9e`](https://github.com/nicrie/xeofs/commit/b4cdd9ec4ca4d75df9e8a3ba7910163c42970cbe)) +* docs: try to solve the readthedocs issue with importlib ([`b4cdd9e`](https://github.com/xarray-contrib/xeofs/commit/b4cdd9ec4ca4d75df9e8a3ba7910163c42970cbe)) -* docs: try to solve readthedoc version number ([`981bcdd`](https://github.com/nicrie/xeofs/commit/981bcdd4865219574bf154bbd6c237c23ee48563)) +* docs: try to solve readthedoc version number ([`981bcdd`](https://github.com/xarray-contrib/xeofs/commit/981bcdd4865219574bf154bbd6c237c23ee48563)) -* docs: update docstrings ([`e02b6ec`](https://github.com/nicrie/xeofs/commit/e02b6ec4545bc9b13b48f27a00b4da77e1358037)) +* docs: update docstrings ([`e02b6ec`](https://github.com/xarray-contrib/xeofs/commit/e02b6ec4545bc9b13b48f27a00b4da77e1358037)) -* docs: update docs ([`7b19b5b`](https://github.com/nicrie/xeofs/commit/7b19b5bc35564317f49311c1a3705ce0893291dc)) +* docs: update docs ([`7b19b5b`](https://github.com/xarray-contrib/xeofs/commit/7b19b5bc35564317f49311c1a3705ce0893291dc)) -* docs: add installation instructions ([`43e2563`](https://github.com/nicrie/xeofs/commit/43e2563e986f3217bce6e9fcd643ea0df0297cc4)) +* docs: add installation instructions ([`43e2563`](https://github.com/xarray-contrib/xeofs/commit/43e2563e986f3217bce6e9fcd643ea0df0297cc4)) -* docs: remove conflicting package versions ([`49636ae`](https://github.com/nicrie/xeofs/commit/49636ae4f456ace63ed19bf081ce2fdf35dbbc42)) +* docs: remove conflicting package versions ([`49636ae`](https://github.com/xarray-contrib/xeofs/commit/49636ae4f456ace63ed19bf081ce2fdf35dbbc42)) -* docs: repair docs due to importlib being installed twice ([`0e21ebd`](https://github.com/nicrie/xeofs/commit/0e21ebd0551ba7813ab5219febfda79dd26aec1a)) +* docs: repair docs due to importlib being installed twice ([`0e21ebd`](https://github.com/xarray-contrib/xeofs/commit/0e21ebd0551ba7813ab5219febfda79dd26aec1a)) -* docs: place badges on same line ([`e2d4dc3`](https://github.com/nicrie/xeofs/commit/e2d4dc380accca197a76c16f815b35f889140150)) +* docs: place badges on same line ([`e2d4dc3`](https://github.com/xarray-contrib/xeofs/commit/e2d4dc380accca197a76c16f815b35f889140150)) -* docs: add installation instruction ([`9512d34`](https://github.com/nicrie/xeofs/commit/9512d3450651384f48582458d2896c4d1ba355cc)) +* docs: add installation instruction ([`9512d34`](https://github.com/xarray-contrib/xeofs/commit/9512d3450651384f48582458d2896c4d1ba355cc)) ### Feature * feat: add support for multidimensional axes -EOF analysis can now be performed along more than one axis/dimension (S-mode, T-mode EOF analysis) ([`7c31c58`](https://github.com/nicrie/xeofs/commit/7c31c58f60376bac57fe42bef58ad9e46942fcb7)) +EOF analysis can now be performed along more than one axis/dimension (S-mode, T-mode EOF analysis) ([`7c31c58`](https://github.com/xarray-contrib/xeofs/commit/7c31c58f60376bac57fe42bef58ad9e46942fcb7)) ### Fix -* fix: allow multidimensional axis for decomposition ([`e09a420`](https://github.com/nicrie/xeofs/commit/e09a420561c41c83483ecd1a718d0d6c86ed8c78)) +* fix: allow multidimensional axis for decomposition ([`e09a420`](https://github.com/xarray-contrib/xeofs/commit/e09a420561c41c83483ecd1a718d0d6c86ed8c78)) ### Style -* style: change error message ([`ad13409`](https://github.com/nicrie/xeofs/commit/ad134098f60a77fcb781336259301d82cfa0b097)) +* style: change error message ([`ad13409`](https://github.com/xarray-contrib/xeofs/commit/ad134098f60a77fcb781336259301d82cfa0b097)) -* style: correct invalid typing ([`3745308`](https://github.com/nicrie/xeofs/commit/374530886fde4a30fe1ec41f1fac692f44a4b4ce)) +* style: correct invalid typing ([`3745308`](https://github.com/xarray-contrib/xeofs/commit/374530886fde4a30fe1ec41f1fac692f44a4b4ce)) -* style: update typings of EOF techniques ([`668a375`](https://github.com/nicrie/xeofs/commit/668a375ffe3e16ce557e52d730e39ce24c393bea)) +* style: update typings of EOF techniques ([`668a375`](https://github.com/xarray-contrib/xeofs/commit/668a375ffe3e16ce557e52d730e39ce24c393bea)) ### Test -* test: update tests for _array_transformer ([`47fe5d2`](https://github.com/nicrie/xeofs/commit/47fe5d2134431b132875395564a080b2a5fcc36d)) +* test: update tests for _array_transformer ([`47fe5d2`](https://github.com/xarray-contrib/xeofs/commit/47fe5d2134431b132875395564a080b2a5fcc36d)) ### Unknown * 0.2.0 -Automatically generated by python-semantic-release ([`0c7fc62`](https://github.com/nicrie/xeofs/commit/0c7fc629d94b6af3e78cdb7d783047d8d0ef2bbe)) +Automatically generated by python-semantic-release ([`0c7fc62`](https://github.com/xarray-contrib/xeofs/commit/0c7fc629d94b6af3e78cdb7d783047d8d0ef2bbe)) * Merge pull request #9 from nicrie/develop -Develop ([`c742987`](https://github.com/nicrie/xeofs/commit/c7429875b42fc65c530656bab308f3ac5fe414e4)) +Develop ([`c742987`](https://github.com/xarray-contrib/xeofs/commit/c7429875b42fc65c530656bab308f3ac5fe414e4)) * Merge pull request #8 from nicrie/develop -Develop ([`c910109`](https://github.com/nicrie/xeofs/commit/c910109b032a64bf578f2edf666852845de47905)) +Develop ([`c910109`](https://github.com/xarray-contrib/xeofs/commit/c910109b032a64bf578f2edf666852845de47905)) ## v0.1.2 (2022-02-15) ### Chore -* chore: add netcdf4 as dev-dependency ([`4c4897c`](https://github.com/nicrie/xeofs/commit/4c4897ce65c39132989a3daede2c144d805d5dc5)) +* chore: add netcdf4 as dev-dependency ([`4c4897c`](https://github.com/xarray-contrib/xeofs/commit/4c4897ce65c39132989a3daede2c144d805d5dc5)) -* chore: Merge branch 'main' into develop ([`f51e4d2`](https://github.com/nicrie/xeofs/commit/f51e4d2fa90ae41d4c390bffa4b1a09c32efd914)) +* chore: Merge branch 'main' into develop ([`f51e4d2`](https://github.com/xarray-contrib/xeofs/commit/f51e4d2fa90ae41d4c390bffa4b1a09c32efd914)) -* chore: upload package to pypi ([`989a278`](https://github.com/nicrie/xeofs/commit/989a2784694e5880646e6d16362eb291a17d1fec)) +* chore: upload package to pypi ([`989a278`](https://github.com/xarray-contrib/xeofs/commit/989a2784694e5880646e6d16362eb291a17d1fec)) -* chore: Merge branch 'main' into develop ([`9cdef9b`](https://github.com/nicrie/xeofs/commit/9cdef9b2eac6a3a997d86506a8ea1ad48395cef7)) +* chore: Merge branch 'main' into develop ([`9cdef9b`](https://github.com/xarray-contrib/xeofs/commit/9cdef9b2eac6a3a997d86506a8ea1ad48395cef7)) ### Documentation -* docs: add batches and link to documentation ([`a7dd2d0`](https://github.com/nicrie/xeofs/commit/a7dd2d0d6cdde42c6c9e9367bfd55d2aa077ba4d)) +* docs: add batches and link to documentation ([`a7dd2d0`](https://github.com/xarray-contrib/xeofs/commit/a7dd2d0d6cdde42c6c9e9367bfd55d2aa077ba4d)) -* docs: update dependencies ([`05ceb68`](https://github.com/nicrie/xeofs/commit/05ceb68bc77586663d9ddcf36c3e6c42d3947c72)) +* docs: update dependencies ([`05ceb68`](https://github.com/xarray-contrib/xeofs/commit/05ceb68bc77586663d9ddcf36c3e6c42d3947c72)) ### Fix -* fix: pandas and xarray eofs back_transform was called twice ([`4fa2bfb`](https://github.com/nicrie/xeofs/commit/4fa2bfb3f3a669ad1fd2b8a72f2fb6a64eab927a)) +* fix: pandas and xarray eofs back_transform was called twice ([`4fa2bfb`](https://github.com/xarray-contrib/xeofs/commit/4fa2bfb3f3a669ad1fd2b8a72f2fb6a64eab927a)) ### Test -* test: add tests for xarray wrapper ([`d5f20cb`](https://github.com/nicrie/xeofs/commit/d5f20cbb76299ead56ad82d27d8b53223a156773)) +* test: add tests for xarray wrapper ([`d5f20cb`](https://github.com/xarray-contrib/xeofs/commit/d5f20cbb76299ead56ad82d27d8b53223a156773)) -* test: add tests for pandas wrapper ([`7a8786d`](https://github.com/nicrie/xeofs/commit/7a8786da3b0a854766481516cacd4bee7301ca92)) +* test: add tests for pandas wrapper ([`7a8786d`](https://github.com/xarray-contrib/xeofs/commit/7a8786da3b0a854766481516cacd4bee7301ca92)) -* test: add more test cases for numpy wrapper ([`d9ca6ae`](https://github.com/nicrie/xeofs/commit/d9ca6ae97c3421bc352fe89cbd22b44bc6e9d548)) +* test: add more test cases for numpy wrapper ([`d9ca6ae`](https://github.com/xarray-contrib/xeofs/commit/d9ca6ae97c3421bc352fe89cbd22b44bc6e9d548)) -* test: add EOF numpy interface ([`b5ff975`](https://github.com/nicrie/xeofs/commit/b5ff975621a271bf1c78d04fcc5607cb5ef46421)) +* test: add EOF numpy interface ([`b5ff975`](https://github.com/xarray-contrib/xeofs/commit/b5ff975621a271bf1c78d04fcc5607cb5ef46421)) ### Unknown * 0.1.2 -Automatically generated by python-semantic-release ([`2e40714`](https://github.com/nicrie/xeofs/commit/2e407145e2cb0df9ec6b9347c338d066e0957caf)) +Automatically generated by python-semantic-release ([`2e40714`](https://github.com/xarray-contrib/xeofs/commit/2e407145e2cb0df9ec6b9347c338d066e0957caf)) * Merge pull request #3 from nicrie/develop -Develop ([`6e61f1b`](https://github.com/nicrie/xeofs/commit/6e61f1bfc0602135497a0a1ab791f68e5a08aebf)) +Develop ([`6e61f1b`](https://github.com/xarray-contrib/xeofs/commit/6e61f1bfc0602135497a0a1ab791f68e5a08aebf)) ## v0.1.1 (2022-02-15) ### Build -* build: migrate to poetry ([`f7def8a`](https://github.com/nicrie/xeofs/commit/f7def8a8b2e6ca5830c2edd6a81d612b15563189)) +* build: migrate to poetry ([`f7def8a`](https://github.com/xarray-contrib/xeofs/commit/f7def8a8b2e6ca5830c2edd6a81d612b15563189)) ### Ci -* ci: migrate python-semantic-release to github workflows ([`c27de9a`](https://github.com/nicrie/xeofs/commit/c27de9acc08fab78d26eae4aced65eb1078a282b)) +* ci: migrate python-semantic-release to github workflows ([`c27de9a`](https://github.com/xarray-contrib/xeofs/commit/c27de9acc08fab78d26eae4aced65eb1078a282b)) -* ci: semantic-release is triggered for PR on main ([`e9077a2`](https://github.com/nicrie/xeofs/commit/e9077a2369f5ceb8c64e7909fcb648dfcb5a4191)) +* ci: semantic-release is triggered for PR on main ([`e9077a2`](https://github.com/xarray-contrib/xeofs/commit/e9077a2369f5ceb8c64e7909fcb648dfcb5a4191)) -* ci: fix incorrect call of coverage ([`d9ee80e`](https://github.com/nicrie/xeofs/commit/d9ee80e9984411252fe9570f8b2ea6cc86844afc)) +* ci: fix incorrect call of coverage ([`d9ee80e`](https://github.com/xarray-contrib/xeofs/commit/d9ee80e9984411252fe9570f8b2ea6cc86844afc)) -* ci: use pre-commit hooks to ensure conventional commits ([`1c04785`](https://github.com/nicrie/xeofs/commit/1c0478579c9d225a11f32ae03b4233a48f7633ed)) +* ci: use pre-commit hooks to ensure conventional commits ([`1c04785`](https://github.com/xarray-contrib/xeofs/commit/1c0478579c9d225a11f32ae03b4233a48f7633ed)) -* ci: migrate to poetry ([`a5db259`](https://github.com/nicrie/xeofs/commit/a5db25927ceac66ddab1f0324b777316c09d22a2)) +* ci: migrate to poetry ([`a5db259`](https://github.com/xarray-contrib/xeofs/commit/a5db25927ceac66ddab1f0324b777316c09d22a2)) ### Fix -* fix: typo in CI ([`b34ccc5`](https://github.com/nicrie/xeofs/commit/b34ccc511a412dd5920ec6a30d764794ca52aad9)) +* fix: typo in CI ([`b34ccc5`](https://github.com/xarray-contrib/xeofs/commit/b34ccc511a412dd5920ec6a30d764794ca52aad9)) -* fix: allow standardized EOF analysis ([`6e80f78`](https://github.com/nicrie/xeofs/commit/6e80f7867a35079b64a447604701f9e689e63f5f)) +* fix: allow standardized EOF analysis ([`6e80f78`](https://github.com/xarray-contrib/xeofs/commit/6e80f7867a35079b64a447604701f9e689e63f5f)) -* fix: wrong pytest version ([`774b2d6`](https://github.com/nicrie/xeofs/commit/774b2d64af46cc6731e270a25c3e4c524c3d0d94)) +* fix: wrong pytest version ([`774b2d6`](https://github.com/xarray-contrib/xeofs/commit/774b2d64af46cc6731e270a25c3e4c524c3d0d94)) -* fix: add development dependencies ([`e1cc1f6`](https://github.com/nicrie/xeofs/commit/e1cc1f669fd218aadf1665b54f441ed1265c6395)) +* fix: add development dependencies ([`e1cc1f6`](https://github.com/xarray-contrib/xeofs/commit/e1cc1f669fd218aadf1665b54f441ed1265c6395)) -* fix: add flake8 dependency ([`483cf42`](https://github.com/nicrie/xeofs/commit/483cf4294e5fda29da1477bee073ba552bb40de9)) +* fix: add flake8 dependency ([`483cf42`](https://github.com/xarray-contrib/xeofs/commit/483cf4294e5fda29da1477bee073ba552bb40de9)) -* fix: add __version__ ([`739ae74`](https://github.com/nicrie/xeofs/commit/739ae740e8a8f740bd69d73a28daebec7117bcb1)) +* fix: add __version__ ([`739ae74`](https://github.com/xarray-contrib/xeofs/commit/739ae740e8a8f740bd69d73a28daebec7117bcb1)) ### Unknown * 0.1.1 -Automatically generated by python-semantic-release ([`87931f5`](https://github.com/nicrie/xeofs/commit/87931f5bb184559156393aa302c63480eb6d149d)) +Automatically generated by python-semantic-release ([`87931f5`](https://github.com/xarray-contrib/xeofs/commit/87931f5bb184559156393aa302c63480eb6d149d)) * Merge branch 'main' into develop -chore: merge main into develop ([`1c79ce1`](https://github.com/nicrie/xeofs/commit/1c79ce16d45928cb7df062dd8bbb17cf6d119f10)) +chore: merge main into develop ([`1c79ce1`](https://github.com/xarray-contrib/xeofs/commit/1c79ce16d45928cb7df062dd8bbb17cf6d119f10)) * Merge pull request #2 from nicrie/develop -Develop ([`fa79596`](https://github.com/nicrie/xeofs/commit/fa79596605eb5cb07d430ac06bc870d5fc0b720e)) +Develop ([`fa79596`](https://github.com/xarray-contrib/xeofs/commit/fa79596605eb5cb07d430ac06bc870d5fc0b720e)) -* add tests for _Array_Transformer and pandas xarray wrapper ([`8d97acf`](https://github.com/nicrie/xeofs/commit/8d97acf674ffd85da85f52260eb327d7a74ec611)) +* add tests for _Array_Transformer and pandas xarray wrapper ([`8d97acf`](https://github.com/xarray-contrib/xeofs/commit/8d97acf674ffd85da85f52260eb327d7a74ec611)) -* add pandas and xarray support for standard EOF ([`290b87a`](https://github.com/nicrie/xeofs/commit/290b87a7271e93b9c8695f82330ee32442e10130)) +* add pandas and xarray support for standard EOF ([`290b87a`](https://github.com/xarray-contrib/xeofs/commit/290b87a7271e93b9c8695f82330ee32442e10130)) -* update README and docs ([`160bd46`](https://github.com/nicrie/xeofs/commit/160bd468e65b79b4d7f5ad7d0b0019bea5ce73da)) +* update README and docs ([`160bd46`](https://github.com/xarray-contrib/xeofs/commit/160bd468e65b79b4d7f5ad7d0b0019bea5ce73da)) -* add dependencies for readthedocs ([`fe96401`](https://github.com/nicrie/xeofs/commit/fe96401ee32abe29068e3f84ea11789efbe3d58c)) +* add dependencies for readthedocs ([`fe96401`](https://github.com/xarray-contrib/xeofs/commit/fe96401ee32abe29068e3f84ea11789efbe3d58c)) -* add readthedocs ([`cc2209d`](https://github.com/nicrie/xeofs/commit/cc2209da410dde0b50ba1747ac838a1dc2583961)) +* add readthedocs ([`cc2209d`](https://github.com/xarray-contrib/xeofs/commit/cc2209da410dde0b50ba1747ac838a1dc2583961)) -* try again and again ([`36870ea`](https://github.com/nicrie/xeofs/commit/36870eaf11203ba697c7e91e7d9c6c84e56e6953)) +* try again and again ([`36870ea`](https://github.com/xarray-contrib/xeofs/commit/36870eaf11203ba697c7e91e7d9c6c84e56e6953)) -* try again ([`a775cbd`](https://github.com/nicrie/xeofs/commit/a775cbda8a190b3df48c06bb274b3b9ad2f8a945)) +* try again ([`a775cbd`](https://github.com/xarray-contrib/xeofs/commit/a775cbda8a190b3df48c06bb274b3b9ad2f8a945)) -* fix bug in codecov ([`6d3548b`](https://github.com/nicrie/xeofs/commit/6d3548b4af75eede52377f3836abe1023032a768)) +* fix bug in codecov ([`6d3548b`](https://github.com/xarray-contrib/xeofs/commit/6d3548b4af75eede52377f3836abe1023032a768)) -* update codecov v2 ([`50c10eb`](https://github.com/nicrie/xeofs/commit/50c10eb24df37912433ba476aa4caa84b291d8ad)) +* update codecov v2 ([`50c10eb`](https://github.com/xarray-contrib/xeofs/commit/50c10eb24df37912433ba476aa4caa84b291d8ad)) -* structure for test, docs, coverage ([`d30ee79`](https://github.com/nicrie/xeofs/commit/d30ee796ee74c3620a66704fee4fb74dd79a9499)) +* structure for test, docs, coverage ([`d30ee79`](https://github.com/xarray-contrib/xeofs/commit/d30ee796ee74c3620a66704fee4fb74dd79a9499)) -* add MIT license ([`5d960ae`](https://github.com/nicrie/xeofs/commit/5d960ae8e1bf2237301200fc42e541afb97155d9)) +* add MIT license ([`5d960ae`](https://github.com/xarray-contrib/xeofs/commit/5d960ae8e1bf2237301200fc42e541afb97155d9)) -* change output dimensions of EOFs ([`0aca5e4`](https://github.com/nicrie/xeofs/commit/0aca5e420d9b7d1a8a65e0b2e6edd4025fe9cf1b)) +* change output dimensions of EOFs ([`0aca5e4`](https://github.com/xarray-contrib/xeofs/commit/0aca5e420d9b7d1a8a65e0b2e6edd4025fe9cf1b)) -* add standard EOF for numpy ([`41348d2`](https://github.com/nicrie/xeofs/commit/41348d20d4c82ed7966e4ad76e508587a0129dc4)) +* add standard EOF for numpy ([`41348d2`](https://github.com/xarray-contrib/xeofs/commit/41348d20d4c82ed7966e4ad76e508587a0129dc4)) -* first commit ([`bc79e3b`](https://github.com/nicrie/xeofs/commit/bc79e3bd3e9d36c60c1460e1139377c5ade58ac3)) +* first commit ([`bc79e3b`](https://github.com/xarray-contrib/xeofs/commit/bc79e3bd3e9d36c60c1460e1139377c5ade58ac3)) diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..ba25c07b --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,33 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +authors: +- family-names: "Rieger" + given-names: "Niclas" + orcid: "https://orcid.org/0000-0003-3357-1742" +- family-names: "Levang" + given-names: "Samuel J." +title: "xeofs" +abstract: "Comprehensive EOF analysis in Python with xarray." +license: MIT +doi: 10.5281/zenodo.6323011 +url: "https://xeofs.readthedocs.io/en/latest/" +repository-code: "https://github.com/xarray-contrib/xeofs" +preferred-citation: + authors: + - family-names: "Rieger" + given-names: "Niclas" + orcid: "https://orcid.org/0000-0003-3357-1742" + - family-names: "Levang" + given-names: "Samuel J." + date-published: "2024-01-02" + doi: 10.21105/joss.06060 + issn: 2475-9066 + issue: 93 + journal: "Journal of Open Source Software" + publisher: + name: "Open Journals" + start: 6060 + title: "xeofs: Comprehensive EOF analysis in Python with xarray" + type: article + url: "https://joss.theoj.org/papers/10.21105/joss.06060" + volume: 9 diff --git a/README.md b/README.md index 5ee0230a..9c1015cc 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ | Versions | ![PyPI](https://img.shields.io/pypi/v/xeofs) ![Conda](https://img.shields.io/conda/vn/conda-forge/xeofs) | |----------------------------|:---------------------------------------------------------------------------------------------:| -| Build & Testing | ![Build](https://img.shields.io/github/actions/workflow/status/nicrie/xeofs/ci.yml?branch=main) ![Coverage](https://codecov.io/gh/nicrie/xeofs/branch/main/graph/badge.svg?token=8040ZDH6U7) | -| Code Quality | ![Black](https://img.shields.io/badge/code%20style-black-000000.svg) | +| Build & Testing | ![Build](https://img.shields.io/github/actions/workflow/status/xarray-contrib/xeofs/ci.yml?branch=main) ![Coverage](https://codecov.io/gh/xarray-contrib/xeofs/branch/main/graph/badge.svg?token=8040ZDH6U7) | +| Code Quality | ![Black](https://img.shields.io/badge/code%20style-black-000000.svg) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v0.json)](https://github.com/charliermarsh/ruff) | | Documentation | ![Docs](https://readthedocs.org/projects/xeofs/badge/?version=latest) | -| Citation & Licensing | ![Zenodo](https://zenodo.org/badge/DOI/10.5281/zenodo.6323012.svg) ![License](https://img.shields.io/pypi/l/xeofs) | -| User Engagement | ![Downloads](https://img.shields.io/pypi/dw/xeofs) [![All Contributors](https://img.shields.io/github/all-contributors/nicrie/xeofs?color=ee8449&style=flat-square)](#contributors) | +| Citation & Licensing | [![JOSS](https://joss.theoj.org/papers/4f50349ee1777b8a61761183047b1180/status.svg)](https://joss.theoj.org/papers/4f50349ee1777b8a61761183047b1180) ![Zenodo](https://zenodo.org/badge/DOI/10.5281/zenodo.6323012.svg) ![License](https://img.shields.io/pypi/l/xeofs) | +| User Engagement | ![Downloads](https://img.shields.io/pypi/dw/xeofs) | ## Overview @@ -42,43 +42,72 @@ In order to get started with `xeofs`, follow these simple steps: **Import the package** ```python -import xeofs as xe +>>> import xarray as xr # for example data only +>>> import xeofs as xe + +``` + +**Load example data** + +```python +>>> t2m = xr.tutorial.open_dataset("air_temperature") +>>> t2m_west = t2m.isel(lon=slice(None, 20)) +>>> t2m_east = t2m.isel(lon=slice(21, None)) + ``` **EOF analysis** +Initiate and fit the EOF/PCA model to the data ```python -model = xe.models.EOF(n_modes=10) -model.fit(data, dim="time") -comps = model.components() # EOFs (spatial patterns) -scores = model.scores() # PCs (temporal patterns) +>>> eof = xe.models.EOF(n_modes=10) +>>> eof.fit(t2m, dim="time") # doctest: +ELLIPSIS + + +``` +Now, you can access the model's EOF components and PC scores: + +```py +>>> comps = eof.components() # EOFs (spatial patterns) +>>> scores = eof.scores() # PCs (temporal patterns) + ``` **Varimax-rotated EOF analysis** +Initiate and fit an `EOFRotator` class to the model to obtain a varimax-rotated EOF analysis ```python -rotator = xe.models.EOFRotator(n_modes=10) -rotator.fit(model) -rot_comps = rotator.components() # Rotated EOFs (spatial patterns) -rot_scores = rotator.scores() # Rotated PCs (temporal patterns) +>>> rotator = xe.models.EOFRotator(n_modes=3) +>>> rotator.fit(eof) # doctest: +ELLIPSIS + + +>>> rot_comps = rotator.components() # Rotated EOFs (spatial patterns) +>>> rot_scores = rotator.scores() # Rotated PCs (temporal patterns) + ``` **Maximum Covariance Analysis (MCA)** ```python -model = xe.models.MCA(n_modes=10) -model.fit(data1, data2, dim="time") -comps1, comps2 = model.components() # Singular vectors (spatial patterns) -scores1, scores2 = model.scores() # Expansion coefficients (temporal patterns) +>>> mca = xe.models.MCA(n_modes=10) +>>> mca.fit(t2m_west, t2m_east, dim="time") # doctest: +ELLIPSIS + + +>>> comps1, comps2 = mca.components() # Singular vectors (spatial patterns) +>>> scores1, scores2 = mca.scores() # Expansion coefficients (temporal patterns) + ``` **Varimax-rotated MCA** ```python -rotator = xe.models.MCARotator(n_modes=10) -rotator.fit(model) -rot_comps = rotator.components() # Rotated singular vectors (spatial patterns) -rot_scores = rotator.scores() # Rotated expansion coefficients (temporal patterns) +>>> rotator = xe.models.MCARotator(n_modes=10) +>>> rotator.fit(mca) # doctest: +ELLIPSIS + + +>>> rot_comps = rotator.components() # Rotated singular vectors (spatial patterns) +>>> rot_scores = rotator.scores() # Rotated expansion coefficients (temporal patterns) + ``` To further explore the capabilities of `xeofs`, check out the [available documentation](https://xeofs.readthedocs.io/en/latest/) and [examples](https://xeofs.readthedocs.io/en/latest/auto_examples/index.html). @@ -94,11 +123,11 @@ Contributions are highly welcomed and appreciated. If you're interested in impro ## License -This project is licensed under the terms of the [MIT license](https://github.com/nicrie/xeofs/blob/main/LICENSE). +This project is licensed under the terms of the [MIT license](https://github.com/xarray-contrib/xeofs/blob/main/LICENSE). ## Contact -For questions or support, please open a [Github issue](https://github.com/nicrie/xeofs/issues). +For questions or support, please open a [Github issue](https://github.com/xarray-contrib/xeofs/issues). ## Credits @@ -113,22 +142,20 @@ For questions or support, please open a [Github issue](https://github.com/nicrie When using `xeofs`, kindly remember to cite the original references of the methods employed in your work. Additionally, if `xeofs` is proving useful in your research, we'd appreciate if you could acknowledge its use with the following citation: ```bibtex -@software{rieger_xeofs_2023, -title = {xeofs: Comprehensive EOF analysis in Python with xarray: A versatile, multidimensional, and scalable tool for advanced climate data analysis}, -url = {https://github.com/nicrie/xeofs} -version = {x.y.z}, -author = {Rieger, N. and Levang, S. J.}, -date = {2023}, -doi = {10.5281/zenodo.6323011} +@article{rieger_xeofs_2024, +author = {Rieger, Niclas and Levang, Samuel J.}, +doi = {10.21105/joss.06060}, +journal = {Journal of Open Source Software}, +month = jan, +number = {93}, +pages = {6060}, +title = {{xeofs: Comprehensive EOF analysis in Python with xarray}}, +url = {https://joss.theoj.org/papers/10.21105/joss.06060}, +volume = {9}, +year = {2024} +} ``` ## Contributors - - - - - - - - +[![Contributors](https://contrib.rocks/image?repo=xarray-contrib/xeofs)](https://github.com/xarray-contrib/xeofs/graphs/contributors) diff --git a/docs/_autosummary/xeofs.models.ComplexEOF.rst b/docs/_autosummary/xeofs.models.ComplexEOF.rst index 64ec37a3..7eb1f432 100644 --- a/docs/_autosummary/xeofs.models.ComplexEOF.rst +++ b/docs/_autosummary/xeofs.models.ComplexEOF.rst @@ -27,6 +27,7 @@ ~ComplexEOF.fit ~ComplexEOF.fit_transform ~ComplexEOF.get_params + ~ComplexEOF.get_serialization_attrs ~ComplexEOF.inverse_transform ~ComplexEOF.load ~ComplexEOF.save diff --git a/docs/_autosummary/xeofs.models.ComplexEOFRotator.rst b/docs/_autosummary/xeofs.models.ComplexEOFRotator.rst index 67740888..41edbcde 100644 --- a/docs/_autosummary/xeofs.models.ComplexEOFRotator.rst +++ b/docs/_autosummary/xeofs.models.ComplexEOFRotator.rst @@ -27,6 +27,7 @@ ~ComplexEOFRotator.fit ~ComplexEOFRotator.fit_transform ~ComplexEOFRotator.get_params + ~ComplexEOFRotator.get_serialization_attrs ~ComplexEOFRotator.inverse_transform ~ComplexEOFRotator.load ~ComplexEOFRotator.save diff --git a/docs/_autosummary/xeofs.models.ComplexMCA.rst b/docs/_autosummary/xeofs.models.ComplexMCA.rst index 6e46f1f2..9d8c7f53 100644 --- a/docs/_autosummary/xeofs.models.ComplexMCA.rst +++ b/docs/_autosummary/xeofs.models.ComplexMCA.rst @@ -25,6 +25,7 @@ ~ComplexMCA.deserialize ~ComplexMCA.fit ~ComplexMCA.get_params + ~ComplexMCA.get_serialization_attrs ~ComplexMCA.heterogeneous_patterns ~ComplexMCA.homogeneous_patterns ~ComplexMCA.inverse_transform diff --git a/docs/_autosummary/xeofs.models.ComplexMCARotator.rst b/docs/_autosummary/xeofs.models.ComplexMCARotator.rst index e9ab0556..4c647104 100644 --- a/docs/_autosummary/xeofs.models.ComplexMCARotator.rst +++ b/docs/_autosummary/xeofs.models.ComplexMCARotator.rst @@ -25,6 +25,7 @@ ~ComplexMCARotator.deserialize ~ComplexMCARotator.fit ~ComplexMCARotator.get_params + ~ComplexMCARotator.get_serialization_attrs ~ComplexMCARotator.heterogeneous_patterns ~ComplexMCARotator.homogeneous_patterns ~ComplexMCARotator.inverse_transform diff --git a/docs/_autosummary/xeofs.models.EOF.rst b/docs/_autosummary/xeofs.models.EOF.rst index 9e57a1eb..90da1cde 100644 --- a/docs/_autosummary/xeofs.models.EOF.rst +++ b/docs/_autosummary/xeofs.models.EOF.rst @@ -25,6 +25,7 @@ ~EOF.fit ~EOF.fit_transform ~EOF.get_params + ~EOF.get_serialization_attrs ~EOF.inverse_transform ~EOF.load ~EOF.save diff --git a/docs/_autosummary/xeofs.models.EOFRotator.rst b/docs/_autosummary/xeofs.models.EOFRotator.rst index 82f100c9..c1f06783 100644 --- a/docs/_autosummary/xeofs.models.EOFRotator.rst +++ b/docs/_autosummary/xeofs.models.EOFRotator.rst @@ -25,6 +25,7 @@ ~EOFRotator.fit ~EOFRotator.fit_transform ~EOFRotator.get_params + ~EOFRotator.get_serialization_attrs ~EOFRotator.inverse_transform ~EOFRotator.load ~EOFRotator.save diff --git a/docs/_autosummary/xeofs.models.ExtendedEOF.rst b/docs/_autosummary/xeofs.models.ExtendedEOF.rst index f26fe9cb..b1740349 100644 --- a/docs/_autosummary/xeofs.models.ExtendedEOF.rst +++ b/docs/_autosummary/xeofs.models.ExtendedEOF.rst @@ -25,6 +25,7 @@ ~ExtendedEOF.fit ~ExtendedEOF.fit_transform ~ExtendedEOF.get_params + ~ExtendedEOF.get_serialization_attrs ~ExtendedEOF.inverse_transform ~ExtendedEOF.load ~ExtendedEOF.save diff --git a/docs/_autosummary/xeofs.models.GWPCA.rst b/docs/_autosummary/xeofs.models.GWPCA.rst index afe9dc6e..2bc03eb9 100644 --- a/docs/_autosummary/xeofs.models.GWPCA.rst +++ b/docs/_autosummary/xeofs.models.GWPCA.rst @@ -25,6 +25,7 @@ ~GWPCA.fit ~GWPCA.fit_transform ~GWPCA.get_params + ~GWPCA.get_serialization_attrs ~GWPCA.inverse_transform ~GWPCA.largest_locally_weighted_components ~GWPCA.load diff --git a/docs/_autosummary/xeofs.models.MCA.rst b/docs/_autosummary/xeofs.models.MCA.rst index 62358221..16b58d96 100644 --- a/docs/_autosummary/xeofs.models.MCA.rst +++ b/docs/_autosummary/xeofs.models.MCA.rst @@ -23,6 +23,7 @@ ~MCA.deserialize ~MCA.fit ~MCA.get_params + ~MCA.get_serialization_attrs ~MCA.heterogeneous_patterns ~MCA.homogeneous_patterns ~MCA.inverse_transform diff --git a/docs/_autosummary/xeofs.models.OPA.rst b/docs/_autosummary/xeofs.models.OPA.rst index 8c07fd27..53000a77 100644 --- a/docs/_autosummary/xeofs.models.OPA.rst +++ b/docs/_autosummary/xeofs.models.OPA.rst @@ -25,6 +25,7 @@ ~OPA.fit ~OPA.fit_transform ~OPA.get_params + ~OPA.get_serialization_attrs ~OPA.inverse_transform ~OPA.load ~OPA.save diff --git a/docs/_autosummary/xeofs.validation.EOFBootstrapper.rst b/docs/_autosummary/xeofs.validation.EOFBootstrapper.rst index d7d044d3..748247b8 100644 --- a/docs/_autosummary/xeofs.validation.EOFBootstrapper.rst +++ b/docs/_autosummary/xeofs.validation.EOFBootstrapper.rst @@ -25,6 +25,7 @@ ~EOFBootstrapper.fit ~EOFBootstrapper.fit_transform ~EOFBootstrapper.get_params + ~EOFBootstrapper.get_serialization_attrs ~EOFBootstrapper.inverse_transform ~EOFBootstrapper.load ~EOFBootstrapper.save diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_001.png index 88fcf24c..dd107e59 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_002.png b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_002.png index 662e7367..987da8bd 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_002.png and b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_002.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_003.png b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_003.png index dd415ed2..e8c8f2ab 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_003.png and b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_003.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_004.png b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_004.png index 3b1a3ba2..b225380b 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_004.png and b/docs/auto_examples/1single/images/sphx_glr_plot_complex_eof_004.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_eeof_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_eeof_001.png index 5738db32..5535ac43 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_eeof_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_eeof_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_eeof_002.png b/docs/auto_examples/1single/images/sphx_glr_plot_eeof_002.png index 6ebf3b99..3a57887f 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_eeof_002.png and b/docs/auto_examples/1single/images/sphx_glr_plot_eeof_002.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_eeof_003.png b/docs/auto_examples/1single/images/sphx_glr_plot_eeof_003.png index 2947ef7a..fa6e1144 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_eeof_003.png and b/docs/auto_examples/1single/images/sphx_glr_plot_eeof_003.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_eof-smode_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_eof-smode_001.png index 91f395e0..8edbe22d 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_eof-smode_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_eof-smode_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_eof-tmode_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_eof-tmode_001.png index 85c0067f..48a24ea6 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_eof-tmode_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_eof-tmode_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_001.png index 1512e549..080b2db8 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_002.png b/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_002.png index 101ecca7..a78ea394 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_002.png and b/docs/auto_examples/1single/images/sphx_glr_plot_gwpca_002.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_mreof_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_mreof_001.png index 135ec639..445d06f5 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_mreof_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_mreof_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_multivariate-eof_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_multivariate-eof_001.png index caf0a892..3ed35002 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_multivariate-eof_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_multivariate-eof_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_rotated_eof_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_rotated_eof_001.png index 8d52fc0c..ce7389fd 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_rotated_eof_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_rotated_eof_001.png differ diff --git a/docs/auto_examples/1single/images/sphx_glr_plot_weighted-eof_001.png b/docs/auto_examples/1single/images/sphx_glr_plot_weighted-eof_001.png index 3ff9a233..e99e6a9e 100644 Binary files a/docs/auto_examples/1single/images/sphx_glr_plot_weighted-eof_001.png and b/docs/auto_examples/1single/images/sphx_glr_plot_weighted-eof_001.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_complex_eof_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_complex_eof_thumb.png index 29d24ef4..f817916d 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_complex_eof_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_complex_eof_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eeof_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eeof_thumb.png index fedce0de..db423829 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eeof_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eeof_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-smode_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-smode_thumb.png index abd7f252..8f5a2688 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-smode_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-smode_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-tmode_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-tmode_thumb.png index 81877179..e1a73f04 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-tmode_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_eof-tmode_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_gwpca_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_gwpca_thumb.png index b7a9a0fd..32f370d6 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_gwpca_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_gwpca_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_mreof_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_mreof_thumb.png index 0796f3dd..b1a2f9ca 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_mreof_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_mreof_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_multivariate-eof_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_multivariate-eof_thumb.png index 004af918..012f0e98 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_multivariate-eof_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_multivariate-eof_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_rotated_eof_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_rotated_eof_thumb.png index 8528e8a6..a75cd05d 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_rotated_eof_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_rotated_eof_thumb.png differ diff --git a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_weighted-eof_thumb.png b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_weighted-eof_thumb.png index 0e2525fb..0d76d4f7 100644 Binary files a/docs/auto_examples/1single/images/thumb/sphx_glr_plot_weighted-eof_thumb.png and b/docs/auto_examples/1single/images/thumb/sphx_glr_plot_weighted-eof_thumb.png differ diff --git a/docs/auto_examples/1single/index.rst b/docs/auto_examples/1single/index.rst index 7de09340..1e33d6f0 100644 --- a/docs/auto_examples/1single/index.rst +++ b/docs/auto_examples/1single/index.rst @@ -14,7 +14,7 @@ .. raw:: html -
+
.. only:: html @@ -48,7 +48,7 @@ .. raw:: html -
+
.. only:: html diff --git a/docs/auto_examples/1single/plot_complex_eof.ipynb b/docs/auto_examples/1single/plot_complex_eof.ipynb index 8fec86d3..aab0c5d6 100644 --- a/docs/auto_examples/1single/plot_complex_eof.ipynb +++ b/docs/auto_examples/1single/plot_complex_eof.ipynb @@ -1,187 +1,236 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Complex/Hilbert EOF analysis\n\nWe demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_. \nThis method extends traditional EOF analysis into the complex domain, allowing \nthe EOF components to have real and imaginary parts. This capability can reveal\noscillatory patterns in datasets, which are common in Earth observations. \nFor example, beyond typical examples like seasonal cycles, you can think of\ninternal waves in the ocean, or the Quasi-Biennial Oscillation in the atmosphere.\n\nUsing monthly sea surface temperature data from 1970 to 2021 as an example, we \nhighlight the method's key features and address edge effects as a common challenge.\n\n.. [1] Rasmusson, E. M., Arkin, P. A., Chen, W.-Y. & Jalickee, J. B. Biennial variations in surface temperature over the United States as revealed by singular decomposition. Monthly Weather Review 109, 587\u2013598 (1981).\n.. [2] Barnett, T. P. Interaction of the Monsoon and Pacific Trade Wind System at Interannual Time Scales Part I: The Equatorial Zone. Monthly Weather Review 111, 756\u2013773 (1983).\n.. [3] Horel, J. Complex Principal Component Analysis: Theory and Examples. J. Climate Appl. Meteor. 23, 1660\u20131673 (1984).\n\nLet's start by importing the necessary packages and loading the data:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import xeofs as xe\nimport xarray as xr\n\nxr.set_options(display_expand_attrs=False)\n\nsst = xr.tutorial.open_dataset(\"ersstv5\").sst\nsst" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We fit the Complex EOF model directly to the raw data, retaining the seasonal\ncycle for study. The model initialization specifies the desired number of\nmodes. The ``use_coslat`` parameter is set to ``True`` to adjust for grid\nconvergence at the poles. While the ``ComplexEOF`` class offers padding options\nto mitigate potential edge effects, we'll begin with no padding.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "kwargs = dict(n_modes=4, use_coslat=True, random_state=7)\nmodel = xe.models.ComplexEOF(padding=\"none\", **kwargs)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we fit the model to the data and extract the explained variance.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model.fit(sst, dim=\"time\")\nexpvar = model.explained_variance()\nexpvar_ratio = model.explained_variance_ratio()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's have a look at the explained variance of the first five modes:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "expvar.round(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Clearly, the first mode completely dominates and already explains a substantial amount of variance.\nIf we look at the fraction of explained variance, we see that the first mode explains about 88.8 %.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "(expvar_ratio * 100).round(1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In comparison to standard EOF analysis (check the corresponding example,\nS-mode), the first complex mode seems to integrate the first two standard\nmodes in terms of explained variance.\nThis makes sense as the two modes in standard EOF are both showing parts of\nan annual cycle (which are in quadrature) and thus the complex mode combines both of them.\nLet's confirm our hypothesis by looking at the real part the complex-valued scores:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "scores = model.scores()\nscores.real.plot.line(x=\"time\", col=\"mode\", lw=1, ylim=(-0.1, 0.1))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And indeed the annual cycle is completed incorporated into the first mode,\nwhile the second mode shows a semi-annual cycle (mode 3 in standard EOF).\n\nHowever, mode three and four look unusual. While showing some similarity to\nENSO (e.g. in mode 3 peaks in 1982, 1998 and 2016), they exhibit a \"running away\"\nbehaviour towards the boundaries of the time series.\nThis a common issue in complex EOF analysis which is based on the Hilbert transform (a convolution)\nthat suffers from the absence of information at the time series boundaries. One way to mitigate this\nis to artificially extend the time series also known as *padding*. In ``xeofs``, you can enable\nsuch a padding by setting the ``padding`` parameter to ``\"exp\"`` which will extent the boundaries by an exponential\ndecaying function. The ``decay_factor`` parameter controls the decay rate of the exponential function measured in\nmultiples of the time series length. Let's see how the decay parameter impacts the results:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model_ext = xe.models.ComplexEOF(padding=\"exp\", decay_factor=0.01, **kwargs)\nmodel_ext.fit(sst, dim=\"time\")\nscores_ext = model_ext.scores().sel(mode=slice(1, 4))\n\nscores_ext.real.plot.line(x=\"time\", col=\"mode\", lw=1, ylim=(-0.1, 0.1))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And indeed, padding the time series effectively reduced the artifacts at the boundaries.\nLastly, we examine the complex component amplitudes and phases.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "comp_amps = model.components_amplitude()\ncomp_amps.plot(col=\"mode\", vmin=0, vmax=0.025)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The component phases of the first mode clearly show the seasonal cycle as\nthe northern and southern hemisphere are phase shifted by 180 degrees (white and black).\nNote the blueish regions in the central East Pacific and Indian Ocean which indicate\na phase shift of 90 degrees compared to the main annual cycle. This is in agreement\nwith mode 3 of the standard EOF analysis.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "comp_phases = model.components_phase()\ncomp_phases.plot(col=\"mode\", cmap=\"twilight\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Complex/Hilbert EOF analysis\n", + "\n", + "We demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_.\n", + "This method extends traditional EOF analysis into the complex domain, allowing\n", + "the EOF components to have real and imaginary parts. This capability can reveal\n", + "oscillatory patterns in datasets, which are common in Earth observations.\n", + "For example, beyond typical examples like seasonal cycles, you can think of\n", + "internal waves in the ocean, or the Quasi-Biennial Oscillation in the atmosphere.\n", + "\n", + "Using monthly sea surface temperature data from 1970 to 2021 as an example, we\n", + "highlight the method's key features and address edge effects as a common challenge.\n", + "\n", + ".. [1] Rasmusson, E. M., Arkin, P. A., Chen, W.-Y. & Jalickee, J. B. Biennial variations in surface temperature over the United States as revealed by singular decomposition. Monthly Weather Review 109, 587–598 (1981).\n", + ".. [2] Barnett, T. P. Interaction of the Monsoon and Pacific Trade Wind System at Interannual Time Scales Part I: The Equatorial Zone. Monthly Weather Review 111, 756–773 (1983).\n", + ".. [3] Horel, J. Complex Principal Component Analysis: Theory and Examples. J. Climate Appl. Meteor. 23, 1660–1673 (1984).\n", + "\n", + "Let's start by importing the necessary packages and loading the data:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xeofs as xe\n", + "import xarray as xr\n", + "\n", + "xr.set_options(display_expand_attrs=False)\n", + "\n", + "sst = xr.tutorial.open_dataset(\"ersstv5\").sst\n", + "sst" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We fit the Complex EOF model directly to the raw data, retaining the seasonal\n", + "cycle for study. The model initialization specifies the desired number of\n", + "modes. The ``use_coslat`` parameter is set to ``True`` to adjust for grid\n", + "convergence at the poles. While the ``ComplexEOF`` class offers padding options\n", + "to mitigate potential edge effects, we'll begin with no padding.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "kwargs = dict(n_modes=4, use_coslat=True, random_state=7)\n", + "model = xe.models.ComplexEOF(padding=\"none\", **kwargs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we fit the model to the data and extract the explained variance.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.fit(sst, dim=\"time\")\n", + "expvar = model.explained_variance()\n", + "expvar_ratio = model.explained_variance_ratio()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's have a look at the explained variance of the first five modes:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expvar.round(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Clearly, the first mode completely dominates and already explains a substantial amount of variance.\n", + "If we look at the fraction of explained variance, we see that the first mode explains about 88.8 %.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(expvar_ratio * 100).round(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In comparison to standard EOF analysis (check the corresponding example,\n", + "S-mode), the first complex mode seems to integrate the first two standard\n", + "modes in terms of explained variance.\n", + "This makes sense as the two modes in standard EOF are both showing parts of\n", + "an annual cycle (which are in quadrature) and thus the complex mode combines both of them.\n", + "Let's confirm our hypothesis by looking at the real part the complex-valued scores:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scores = model.scores()\n", + "scores.real.plot.line(x=\"time\", col=\"mode\", lw=1, ylim=(-0.1, 0.1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And indeed the annual cycle is completed incorporated into the first mode,\n", + "while the second mode shows a semi-annual cycle (mode 3 in standard EOF).\n", + "\n", + "However, mode three and four look unusual. While showing some similarity to\n", + "ENSO (e.g. in mode 3 peaks in 1982, 1998 and 2016), they exhibit a \"running away\"\n", + "behaviour towards the boundaries of the time series.\n", + "This a common issue in complex EOF analysis which is based on the Hilbert transform (a convolution)\n", + "that suffers from the absence of information at the time series boundaries. One way to mitigate this\n", + "is to artificially extend the time series also known as *padding*. In ``xeofs``, you can enable\n", + "such a padding by setting the ``padding`` parameter to ``\"exp\"`` which will extent the boundaries by an exponential\n", + "decaying function. The ``decay_factor`` parameter controls the decay rate of the exponential function measured in\n", + "multiples of the time series length. Let's see how the decay parameter impacts the results:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model_ext = xe.models.ComplexEOF(padding=\"exp\", decay_factor=0.01, **kwargs)\n", + "model_ext.fit(sst, dim=\"time\")\n", + "scores_ext = model_ext.scores().sel(mode=slice(1, 4))\n", + "\n", + "scores_ext.real.plot.line(x=\"time\", col=\"mode\", lw=1, ylim=(-0.1, 0.1))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And indeed, padding the time series effectively reduced the artifacts at the boundaries.\n", + "Lastly, we examine the complex component amplitudes and phases.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "comp_amps = model.components_amplitude()\n", + "comp_amps.plot(col=\"mode\", vmin=0, vmax=0.025)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The component phases of the first mode clearly show the seasonal cycle as\n", + "the northern and southern hemisphere are phase shifted by 180 degrees (white and black).\n", + "Note the blueish regions in the central East Pacific and Indian Ocean which indicate\n", + "a phase shift of 90 degrees compared to the main annual cycle. This is in agreement\n", + "with mode 3 of the standard EOF analysis.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "comp_phases = model.components_phase()\n", + "comp_phases.plot(col=\"mode\", cmap=\"twilight\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_complex_eof.py b/docs/auto_examples/1single/plot_complex_eof.py index d07be820..d72e8132 100644 --- a/docs/auto_examples/1single/plot_complex_eof.py +++ b/docs/auto_examples/1single/plot_complex_eof.py @@ -2,14 +2,14 @@ Complex/Hilbert EOF analysis ============================================ -We demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_. -This method extends traditional EOF analysis into the complex domain, allowing +We demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_. +This method extends traditional EOF analysis into the complex domain, allowing the EOF components to have real and imaginary parts. This capability can reveal -oscillatory patterns in datasets, which are common in Earth observations. +oscillatory patterns in datasets, which are common in Earth observations. For example, beyond typical examples like seasonal cycles, you can think of internal waves in the ocean, or the Quasi-Biennial Oscillation in the atmosphere. -Using monthly sea surface temperature data from 1970 to 2021 as an example, we +Using monthly sea surface temperature data from 1970 to 2021 as an example, we highlight the method's key features and address edge effects as a common challenge. .. [1] Rasmusson, E. M., Arkin, P. A., Chen, W.-Y. & Jalickee, J. B. Biennial variations in surface temperature over the United States as revealed by singular decomposition. Monthly Weather Review 109, 587–598 (1981). diff --git a/docs/auto_examples/1single/plot_complex_eof.py.md5 b/docs/auto_examples/1single/plot_complex_eof.py.md5 index 0938b333..90412219 100644 --- a/docs/auto_examples/1single/plot_complex_eof.py.md5 +++ b/docs/auto_examples/1single/plot_complex_eof.py.md5 @@ -1 +1 @@ -d366ef9012981e7d6b1640f8f697a4e5 \ No newline at end of file +169f32ef68f5635b4a8af2ec5a6be351 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_complex_eof.rst b/docs/auto_examples/1single/plot_complex_eof.rst index db7116d4..b2be8bde 100644 --- a/docs/auto_examples/1single/plot_complex_eof.rst +++ b/docs/auto_examples/1single/plot_complex_eof.rst @@ -21,14 +21,14 @@ Complex/Hilbert EOF analysis ============================================ -We demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_. -This method extends traditional EOF analysis into the complex domain, allowing +We demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_. +This method extends traditional EOF analysis into the complex domain, allowing the EOF components to have real and imaginary parts. This capability can reveal -oscillatory patterns in datasets, which are common in Earth observations. +oscillatory patterns in datasets, which are common in Earth observations. For example, beyond typical examples like seasonal cycles, you can think of internal waves in the ocean, or the Quasi-Biennial Oscillation in the atmosphere. -Using monthly sea surface temperature data from 1970 to 2021 as an example, we +Using monthly sea surface temperature data from 1970 to 2021 as an example, we highlight the method's key features and address edge effects as a common challenge. .. [1] Rasmusson, E. M., Arkin, P. A., Chen, W.-Y. & Jalickee, J. B. Biennial variations in surface temperature over the United States as revealed by singular decomposition. Monthly Weather Review 109, 587–598 (1981). @@ -39,7 +39,7 @@ Let's start by importing the necessary packages and loading the data: .. GENERATED FROM PYTHON SOURCE LINES 23-31 -.. code-block:: default +.. code-block:: Python import xeofs as xe import xarray as xr @@ -420,20 +420,20 @@ Let's start by importing the necessary packages and loading the data: stroke: currentColor; fill: currentColor; } -
<xarray.DataArray 'sst' (time: 624, lat: 89, lon: 180)>
+    
<xarray.DataArray 'sst' (time: 624, lat: 89, lon: 180)> Size: 40MB
     [9996480 values with dtype=float32]
     Coordinates:
-      * lat      (lat) float32 88.0 86.0 84.0 82.0 80.0 ... -82.0 -84.0 -86.0 -88.0
-      * lon      (lon) float32 0.0 2.0 4.0 6.0 8.0 ... 350.0 352.0 354.0 356.0 358.0
-      * time     (time) datetime64[ns] 1970-01-01 1970-02-01 ... 2021-12-01
-    Attributes: (9)
  • long_name :
    Monthly Means of Sea Surface Temperature
    units :
    degC
    var_desc :
    Sea Surface Temperature
    level_desc :
    Surface
    statistic :
    Mean
    dataset :
    NOAA Extended Reconstructed SST V5
    parent_stat :
    Individual Values
    actual_range :
    [-1.8 42.32636]
    valid_range :
    [-1.8 45. ]


  • @@ -485,7 +485,7 @@ to mitigate potential edge effects, we'll begin with no padding. .. GENERATED FROM PYTHON SOURCE LINES 37-41 -.. code-block:: default +.. code-block:: Python kwargs = dict(n_modes=4, use_coslat=True, random_state=7) @@ -504,7 +504,7 @@ Now, we fit the model to the data and extract the explained variance. .. GENERATED FROM PYTHON SOURCE LINES 43-48 -.. code-block:: default +.. code-block:: Python model.fit(sst, dim="time") @@ -524,7 +524,7 @@ Let's have a look at the explained variance of the first five modes: .. GENERATED FROM PYTHON SOURCE LINES 50-54 -.. code-block:: default +.. code-block:: Python expvar.round(0) @@ -901,11 +901,11 @@ Let's have a look at the explained variance of the first five modes: stroke: currentColor; fill: currentColor; } -
    <xarray.DataArray 'explained_variance' (mode: 4)>
    -    array([50686.,  1705.,  1105.,   519.])
    +    
    <xarray.DataArray 'explained_variance' (mode: 4)> Size: 32B
    +    5.069e+04 1.705e+03 1.105e+03 519.0
         Coordinates:
    -      * mode     (mode) int64 1 2 3 4
    -    Attributes: (13)
    + * mode (mode) int64 32B 1 2 3 4 + Attributes: (16)


    @@ -917,7 +917,7 @@ If we look at the fraction of explained variance, we see that the first mode exp .. GENERATED FROM PYTHON SOURCE LINES 57-60 -.. code-block:: default +.. code-block:: Python (expvar_ratio * 100).round(1) @@ -1293,11 +1293,11 @@ If we look at the fraction of explained variance, we see that the first mode exp stroke: currentColor; fill: currentColor; } -
    <xarray.DataArray 'explained_variance_ratio' (mode: 4)>
    -    array([88.8,  3. ,  1.9,  0.9])
    +    
    <xarray.DataArray 'explained_variance_ratio' (mode: 4)> Size: 32B
    +    88.8 3.0 1.9 0.9
         Coordinates:
    -      * mode     (mode) int64 1 2 3 4
    -    Attributes: (13)
    + * mode (mode) int64 32B 1 2 3 4 + Attributes: (16)


    @@ -1313,7 +1313,7 @@ Let's confirm our hypothesis by looking at the real part the complex-valued scor .. GENERATED FROM PYTHON SOURCE LINES 67-72 -.. code-block:: default +.. code-block:: Python scores = model.scores() @@ -1334,7 +1334,7 @@ Let's confirm our hypothesis by looking at the real part the complex-valued scor .. code-block:: none - + @@ -1355,7 +1355,7 @@ multiples of the time series length. Let's see how the decay parameter impacts t .. GENERATED FROM PYTHON SOURCE LINES 85-92 -.. code-block:: default +.. code-block:: Python model_ext = xe.models.ComplexEOF(padding="exp", decay_factor=0.01, **kwargs) @@ -1378,7 +1378,7 @@ multiples of the time series length. Let's see how the decay parameter impacts t .. code-block:: none - + @@ -1389,7 +1389,7 @@ Lastly, we examine the complex component amplitudes and phases. .. GENERATED FROM PYTHON SOURCE LINES 95-99 -.. code-block:: default +.. code-block:: Python comp_amps = model.components_amplitude() @@ -1409,7 +1409,7 @@ Lastly, we examine the complex component amplitudes and phases. .. code-block:: none - + @@ -1423,7 +1423,7 @@ with mode 3 of the standard EOF analysis. .. GENERATED FROM PYTHON SOURCE LINES 105-108 -.. code-block:: default +.. code-block:: Python comp_phases = model.components_phase() @@ -1442,14 +1442,14 @@ with mode 3 of the standard EOF analysis. .. code-block:: none - + .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 15.825 seconds) + **Total running time of the script:** (0 minutes 3.119 seconds) .. _sphx_glr_download_auto_examples_1single_plot_complex_eof.py: @@ -1458,17 +1458,14 @@ with mode 3 of the standard EOF analysis. .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_complex_eof.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_complex_eof.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_complex_eof.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_complex_eof_codeobj.pickle b/docs/auto_examples/1single/plot_complex_eof_codeobj.pickle index a57b6705..8f11151a 100644 Binary files a/docs/auto_examples/1single/plot_complex_eof_codeobj.pickle and b/docs/auto_examples/1single/plot_complex_eof_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_eeof.ipynb b/docs/auto_examples/1single/plot_eeof.ipynb index a3a7b805..93ba4890 100644 --- a/docs/auto_examples/1single/plot_eeof.ipynb +++ b/docs/auto_examples/1single/plot_eeof.ipynb @@ -1,151 +1,191 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Extented EOF analysis\n\nThis example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial \ndata. EEOF analysis, also termed as Multivariate/Multichannel Singular \nSpectrum Analysis, advances traditional EOF analysis to capture propagating \nsignals or oscillations in multivariate datasets. At its core, this \ninvolves the formulation of a lagged covariance matrix that encapsulates \nboth spatial and temporal correlations. Subsequently, this matrix is \ndecomposed to yield its eigenvectors (components) and eigenvalues (explained variance).\n\nLet's begin by setting up the required packages and fetching the data:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import xarray as xr\nimport xeofs as xe\nimport matplotlib.pyplot as plt\n\nxr.set_options(display_expand_data=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Load the tutorial data.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "t2m = xr.tutorial.load_dataset(\"air_temperature\").air" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Prior to conducting the EEOF analysis, it's essential to determine the\nstructure of the lagged covariance matrix. This entails defining the time\ndelay ``tau`` and the ``embedding`` dimension. The former signifies the\ninterval between the original and lagged time series, while the latter\ndictates the number of time-lagged copies in the delay-coordinate space,\nrepresenting the system's dynamics.\nFor illustration, using ``tau=4`` and ``embedding=40``, we generate 40\ndelayed versions of the time series, each offset by 4 time steps, resulting\nin a maximum shift of ``tau x embedding = 160``. Given our dataset's\n6-hour intervals, tau = 4 translates to a 24-hour shift.\nIt's obvious that this way of constructing the lagged covariance matrix\nand subsequently decomposing it can be computationally expensive. For example,\ngiven our dataset's dimensions,\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "t2m.shape" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "the extended dataset would have 40 x 25 x 53 = 53000 features\nwhich is much larger than the original dataset's 1325 features.\nTo mitigate this, we can first preprocess the data using PCA / EOF analysis\nand then perform EEOF analysis on the resulting PCA / EOF scores. Here,\nwe'll use ``n_pca_modes=50`` to retain the first 50 PCA modes, so we end\nup with 40 x 50 = 200 (latent) features.\nWith these parameters set, we proceed to instantiate the ``ExtendedEOF``\nmodel and fit our data.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model = xe.models.ExtendedEOF(\n n_modes=10, tau=4, embedding=40, n_pca_modes=50, use_coslat=True\n)\nmodel.fit(t2m, dim=\"time\")\nscores = model.scores()\ncomponents = model.components()\ncomponents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A notable distinction from standard EOF analysis is the incorporation of an\nextra ``embedding`` dimension in the components. Nonetheless, the\noverarching methodology mirrors traditional EOF practices. The results,\nfor instance, can be assessed by examining the explained variance ratio.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model.explained_variance_ratio().plot()\nplt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Additionally, we can look into the scores; let's spotlight mode 4.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "scores.sel(mode=4).plot()\nplt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In wrapping up, we visualize the corresponding EEOF component of mode 4.\nFor visualization purposes, we'll focus on the component at a specific\nlatitude, in this instance, 60 degrees north.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "components.sel(mode=4, lat=60).plot()\nplt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Extented EOF analysis\n", + "\n", + "This example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial\n", + "data. EEOF analysis, also termed as Multivariate/Multichannel Singular\n", + "Spectrum Analysis, advances traditional EOF analysis to capture propagating\n", + "signals or oscillations in multivariate datasets. At its core, this\n", + "involves the formulation of a lagged covariance matrix that encapsulates\n", + "both spatial and temporal correlations. Subsequently, this matrix is\n", + "decomposed to yield its eigenvectors (components) and eigenvalues (explained variance).\n", + "\n", + "Let's begin by setting up the required packages and fetching the data:\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "import xeofs as xe\n", + "import matplotlib.pyplot as plt\n", + "\n", + "xr.set_options(display_expand_data=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load the tutorial data.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t2m = xr.tutorial.load_dataset(\"air_temperature\").air" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Prior to conducting the EEOF analysis, it's essential to determine the\n", + "structure of the lagged covariance matrix. This entails defining the time\n", + "delay ``tau`` and the ``embedding`` dimension. The former signifies the\n", + "interval between the original and lagged time series, while the latter\n", + "dictates the number of time-lagged copies in the delay-coordinate space,\n", + "representing the system's dynamics.\n", + "For illustration, using ``tau=4`` and ``embedding=40``, we generate 40\n", + "delayed versions of the time series, each offset by 4 time steps, resulting\n", + "in a maximum shift of ``tau x embedding = 160``. Given our dataset's\n", + "6-hour intervals, tau = 4 translates to a 24-hour shift.\n", + "It's obvious that this way of constructing the lagged covariance matrix\n", + "and subsequently decomposing it can be computationally expensive. For example,\n", + "given our dataset's dimensions,\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t2m.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "the extended dataset would have 40 x 25 x 53 = 53000 features\n", + "which is much larger than the original dataset's 1325 features.\n", + "To mitigate this, we can first preprocess the data using PCA / EOF analysis\n", + "and then perform EEOF analysis on the resulting PCA / EOF scores. Here,\n", + "we'll use ``n_pca_modes=50`` to retain the first 50 PCA modes, so we end\n", + "up with 40 x 50 = 200 (latent) features.\n", + "With these parameters set, we proceed to instantiate the ``ExtendedEOF``\n", + "model and fit our data.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = xe.models.ExtendedEOF(\n", + " n_modes=10, tau=4, embedding=40, n_pca_modes=50, use_coslat=True\n", + ")\n", + "model.fit(t2m, dim=\"time\")\n", + "scores = model.scores()\n", + "components = model.components()\n", + "components" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A notable distinction from standard EOF analysis is the incorporation of an\n", + "extra ``embedding`` dimension in the components. Nonetheless, the\n", + "overarching methodology mirrors traditional EOF practices. The results,\n", + "for instance, can be assessed by examining the explained variance ratio.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.explained_variance_ratio().plot()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Additionally, we can look into the scores; let's spotlight mode 4.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scores.sel(mode=4).plot()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In wrapping up, we visualize the corresponding EEOF component of mode 4.\n", + "For visualization purposes, we'll focus on the component at a specific\n", + "latitude, in this instance, 60 degrees north.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "components.sel(mode=4, lat=60).plot()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_eeof.py b/docs/auto_examples/1single/plot_eeof.py index 2a7ab1d1..ab804f5b 100644 --- a/docs/auto_examples/1single/plot_eeof.py +++ b/docs/auto_examples/1single/plot_eeof.py @@ -2,12 +2,12 @@ Extented EOF analysis ===================== -This example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial -data. EEOF analysis, also termed as Multivariate/Multichannel Singular -Spectrum Analysis, advances traditional EOF analysis to capture propagating -signals or oscillations in multivariate datasets. At its core, this -involves the formulation of a lagged covariance matrix that encapsulates -both spatial and temporal correlations. Subsequently, this matrix is +This example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial +data. EEOF analysis, also termed as Multivariate/Multichannel Singular +Spectrum Analysis, advances traditional EOF analysis to capture propagating +signals or oscillations in multivariate datasets. At its core, this +involves the formulation of a lagged covariance matrix that encapsulates +both spatial and temporal correlations. Subsequently, this matrix is decomposed to yield its eigenvectors (components) and eigenvalues (explained variance). Let's begin by setting up the required packages and fetching the data: diff --git a/docs/auto_examples/1single/plot_eeof.py.md5 b/docs/auto_examples/1single/plot_eeof.py.md5 index 48d6006a..c812c58c 100644 --- a/docs/auto_examples/1single/plot_eeof.py.md5 +++ b/docs/auto_examples/1single/plot_eeof.py.md5 @@ -1 +1 @@ -7f3b66c7aec555c78dde9031213be3ad \ No newline at end of file +df94cdd1a2a195a28f08b955bafe0677 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_eeof.rst b/docs/auto_examples/1single/plot_eeof.rst index 10485c76..e5e68399 100644 --- a/docs/auto_examples/1single/plot_eeof.rst +++ b/docs/auto_examples/1single/plot_eeof.rst @@ -21,19 +21,19 @@ Extented EOF analysis ===================== -This example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial -data. EEOF analysis, also termed as Multivariate/Multichannel Singular -Spectrum Analysis, advances traditional EOF analysis to capture propagating -signals or oscillations in multivariate datasets. At its core, this -involves the formulation of a lagged covariance matrix that encapsulates -both spatial and temporal correlations. Subsequently, this matrix is +This example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial +data. EEOF analysis, also termed as Multivariate/Multichannel Singular +Spectrum Analysis, advances traditional EOF analysis to capture propagating +signals or oscillations in multivariate datasets. At its core, this +involves the formulation of a lagged covariance matrix that encapsulates +both spatial and temporal correlations. Subsequently, this matrix is decomposed to yield its eigenvectors (components) and eigenvalues (explained variance). Let's begin by setting up the required packages and fetching the data: .. GENERATED FROM PYTHON SOURCE LINES 15-22 -.. code-block:: default +.. code-block:: Python import xarray as xr @@ -51,7 +51,7 @@ Let's begin by setting up the required packages and fetching the data: .. code-block:: none - + @@ -61,7 +61,7 @@ Load the tutorial data. .. GENERATED FROM PYTHON SOURCE LINES 24-27 -.. code-block:: default +.. code-block:: Python t2m = xr.tutorial.load_dataset("air_temperature").air @@ -91,7 +91,7 @@ given our dataset's dimensions, .. GENERATED FROM PYTHON SOURCE LINES 41-44 -.. code-block:: default +.. code-block:: Python t2m.shape @@ -122,7 +122,7 @@ model and fit our data. .. GENERATED FROM PYTHON SOURCE LINES 53-62 -.. code-block:: default +.. code-block:: Python model = xe.models.ExtendedEOF( @@ -504,88 +504,88 @@ model and fit our data. stroke: currentColor; fill: currentColor; } -
    <xarray.DataArray 'components' (mode: 10, embedding: 40, lat: 25, lon: 53)>
    -    0.0003856 0.0003648 0.0003574 0.0003567 ... -0.001394 -0.000989 -0.0005902
    +    
    <xarray.DataArray 'components' (mode: 10, embedding: 40, lat: 25, lon: 53)> Size: 4MB
    +    0.0003854 0.0003646 0.000357 0.0003562 ... -0.001459 -0.00105 -0.0006424
         Coordinates:
    -      * lat        (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 67.5 70.0 72.5 75.0
    -      * lon        (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0
    -      * embedding  (embedding) int64 0 4 8 12 16 20 24 ... 136 140 144 148 152 156
    -      * mode       (mode) int64 1 2 3 4 5 6 7 8 9 10
    -    Attributes: (12/13)
    -        model:         Extended EOF Analysis
    -        software:      xeofs
    -        version:       1.2.0
    -        date:          2023-10-25 19:13:23
    -        n_modes:       10
    -        center:        True
    -        ...            ...
    -        use_coslat:    True
    -        sample_name:   sample
    -        feature_name:  feature
    -        random_state:  None
    -        compute:       True
    -        solver:        auto
  • model :
    Extended EOF Analysis
    software :
    xeofs
    version :
    2.3.2
    date :
    2024-03-31 20:34:10
    n_modes :
    10
    center :
    True
    standardize :
    False
    use_coslat :
    True
    check_nans :
    True
    sample_name :
    sample
    feature_name :
    feature
    random_state :
    None
    verbose :
    False
    compute :
    True
    solver :
    auto
    solver_kwargs :
    {}


  • @@ -599,7 +599,7 @@ for instance, can be assessed by examining the explained variance ratio. .. GENERATED FROM PYTHON SOURCE LINES 67-71 -.. code-block:: default +.. code-block:: Python model.explained_variance_ratio().plot() @@ -623,7 +623,7 @@ Additionally, we can look into the scores; let's spotlight mode 4. .. GENERATED FROM PYTHON SOURCE LINES 73-77 -.. code-block:: default +.. code-block:: Python scores.sel(mode=4).plot() @@ -649,7 +649,7 @@ latitude, in this instance, 60 degrees north. .. GENERATED FROM PYTHON SOURCE LINES 81-84 -.. code-block:: default +.. code-block:: Python components.sel(mode=4, lat=60).plot() @@ -669,7 +669,7 @@ latitude, in this instance, 60 degrees north. .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 6.061 seconds) + **Total running time of the script:** (0 minutes 0.777 seconds) .. _sphx_glr_download_auto_examples_1single_plot_eeof.py: @@ -678,17 +678,14 @@ latitude, in this instance, 60 degrees north. .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_eeof.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_eeof.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_eeof.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_eeof_codeobj.pickle b/docs/auto_examples/1single/plot_eeof_codeobj.pickle index bf6a1718..02887345 100644 Binary files a/docs/auto_examples/1single/plot_eeof_codeobj.pickle and b/docs/auto_examples/1single/plot_eeof_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_eof-smode.ipynb b/docs/auto_examples/1single/plot_eof-smode.ipynb index 57bd00b6..dbc977c7 100644 --- a/docs/auto_examples/1single/plot_eof-smode.ipynb +++ b/docs/auto_examples/1single/plot_eof-smode.ipynb @@ -1,108 +1,132 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# EOF analysis (S-mode)\n\nEOF analysis in S-mode maximises the temporal variance.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Load packages and data:\nimport xarray as xr\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import EqualEarth, PlateCarree\n\nfrom xeofs.models import EOF" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "sst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform the actual analysis\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model = EOF(n_modes=5, use_coslat=True)\nmodel.fit(sst, dim=\"time\")\nexpvar = model.explained_variance()\nexpvar_ratio = model.explained_variance_ratio()\ncomponents = model.components()\nscores = model.scores()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Explained variance fraction\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "print(\"Explained variance: \", expvar.round(0).values)\nprint(\"Relative: \", (expvar_ratio * 100).round(1).values)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create figure showing the first two modes\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "proj = EqualEarth(central_longitude=180)\nkwargs = {\"cmap\": \"RdBu\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\n\nfig = plt.figure(figsize=(10, 8))\ngs = GridSpec(3, 2, width_ratios=[1, 2])\nax0 = [fig.add_subplot(gs[i, 0]) for i in range(3)]\nax1 = [fig.add_subplot(gs[i, 1], projection=proj) for i in range(3)]\n\nfor i, (a0, a1) in enumerate(zip(ax0, ax1)):\n scores.sel(mode=i + 1).plot(ax=a0)\n a1.coastlines(color=\".5\")\n components.sel(mode=i + 1).plot(ax=a1, **kwargs)\n\n a0.set_xlabel(\"\")\n\nplt.tight_layout()\nplt.savefig(\"eof-smode.jpg\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# EOF analysis (S-mode)\n", + "\n", + "EOF analysis in S-mode maximises the temporal variance.\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load packages and data:\n", + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import EqualEarth, PlateCarree\n", + "\n", + "from xeofs.models import EOF" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform the actual analysis\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = EOF(n_modes=5, use_coslat=True)\n", + "model.fit(sst, dim=\"time\")\n", + "expvar = model.explained_variance()\n", + "expvar_ratio = model.explained_variance_ratio()\n", + "components = model.components()\n", + "scores = model.scores()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Explained variance fraction\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Explained variance: \", expvar.round(0).values)\n", + "print(\"Relative: \", (expvar_ratio * 100).round(1).values)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create figure showing the first two modes\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "proj = EqualEarth(central_longitude=180)\n", + "kwargs = {\"cmap\": \"RdBu\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\n", + "\n", + "fig = plt.figure(figsize=(10, 8))\n", + "gs = GridSpec(3, 2, width_ratios=[1, 2])\n", + "ax0 = [fig.add_subplot(gs[i, 0]) for i in range(3)]\n", + "ax1 = [fig.add_subplot(gs[i, 1], projection=proj) for i in range(3)]\n", + "\n", + "for i, (a0, a1) in enumerate(zip(ax0, ax1)):\n", + " scores.sel(mode=i + 1).plot(ax=a0)\n", + " a1.coastlines(color=\".5\")\n", + " components.sel(mode=i + 1).plot(ax=a1, **kwargs)\n", + "\n", + " a0.set_xlabel(\"\")\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"eof-smode.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_eof-smode.py b/docs/auto_examples/1single/plot_eof-smode.py index 4a947fc8..f9cd5f38 100644 --- a/docs/auto_examples/1single/plot_eof-smode.py +++ b/docs/auto_examples/1single/plot_eof-smode.py @@ -5,7 +5,6 @@ EOF analysis in S-mode maximises the temporal variance. """ - # Load packages and data: import xarray as xr import matplotlib.pyplot as plt diff --git a/docs/auto_examples/1single/plot_eof-smode.py.md5 b/docs/auto_examples/1single/plot_eof-smode.py.md5 index 3ed16822..62a74921 100644 --- a/docs/auto_examples/1single/plot_eof-smode.py.md5 +++ b/docs/auto_examples/1single/plot_eof-smode.py.md5 @@ -1 +1 @@ -5511d8586b6b1c180327232bac9aadea \ No newline at end of file +9dcc843908baf836161fbc9c490b6136 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_eof-smode.rst b/docs/auto_examples/1single/plot_eof-smode.rst index 0acb4ba2..cb87820c 100644 --- a/docs/auto_examples/1single/plot_eof-smode.rst +++ b/docs/auto_examples/1single/plot_eof-smode.rst @@ -23,10 +23,9 @@ EOF analysis (S-mode) EOF analysis in S-mode maximises the temporal variance. -.. GENERATED FROM PYTHON SOURCE LINES 7-17 - -.. code-block:: default +.. GENERATED FROM PYTHON SOURCE LINES 7-16 +.. code-block:: Python # Load packages and data: @@ -44,9 +43,9 @@ EOF analysis in S-mode maximises the temporal variance. -.. GENERATED FROM PYTHON SOURCE LINES 18-21 +.. GENERATED FROM PYTHON SOURCE LINES 17-20 -.. code-block:: default +.. code-block:: Python sst = xr.tutorial.open_dataset("ersstv5")["sst"] @@ -58,13 +57,13 @@ EOF analysis in S-mode maximises the temporal variance. -.. GENERATED FROM PYTHON SOURCE LINES 22-23 +.. GENERATED FROM PYTHON SOURCE LINES 21-22 Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 23-31 +.. GENERATED FROM PYTHON SOURCE LINES 22-30 -.. code-block:: default +.. code-block:: Python model = EOF(n_modes=5, use_coslat=True) @@ -81,13 +80,13 @@ Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 32-33 +.. GENERATED FROM PYTHON SOURCE LINES 31-32 Explained variance fraction -.. GENERATED FROM PYTHON SOURCE LINES 33-37 +.. GENERATED FROM PYTHON SOURCE LINES 32-36 -.. code-block:: default +.. code-block:: Python print("Explained variance: ", expvar.round(0).values) @@ -107,13 +106,13 @@ Explained variance fraction -.. GENERATED FROM PYTHON SOURCE LINES 38-39 +.. GENERATED FROM PYTHON SOURCE LINES 37-38 Create figure showing the first two modes -.. GENERATED FROM PYTHON SOURCE LINES 39-57 +.. GENERATED FROM PYTHON SOURCE LINES 38-56 -.. code-block:: default +.. code-block:: Python proj = EqualEarth(central_longitude=180) @@ -148,7 +147,7 @@ Create figure showing the first two modes .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 4.394 seconds) + **Total running time of the script:** (0 minutes 2.207 seconds) .. _sphx_glr_download_auto_examples_1single_plot_eof-smode.py: @@ -157,17 +156,14 @@ Create figure showing the first two modes .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_eof-smode.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_eof-smode.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_eof-smode.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_eof-smode_codeobj.pickle b/docs/auto_examples/1single/plot_eof-smode_codeobj.pickle index 22a6c83d..bd0de313 100644 Binary files a/docs/auto_examples/1single/plot_eof-smode_codeobj.pickle and b/docs/auto_examples/1single/plot_eof-smode_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_eof-tmode.ipynb b/docs/auto_examples/1single/plot_eof-tmode.ipynb index d69ddf2a..ac26dc99 100644 --- a/docs/auto_examples/1single/plot_eof-tmode.ipynb +++ b/docs/auto_examples/1single/plot_eof-tmode.ipynb @@ -1,79 +1,107 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# EOF analysis (T-mode)\n\nEOF analysis in T-mode maximises the spatial variance.\n\nLoad packages and data:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import xarray as xr\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import EqualEarth, PlateCarree\n\nfrom xeofs.models import EOF\n\nsst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform the actual analysis\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model = EOF(n_modes=5)\nmodel.fit(sst, dim=(\"lat\", \"lon\"))\nexpvar = model.explained_variance_ratio()\ncomponents = model.components()\nscores = model.scores()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create figure showing the first two modes\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "proj = EqualEarth(central_longitude=180)\nkwargs = {\"cmap\": \"RdBu\", \"transform\": PlateCarree()}\n\nfig = plt.figure(figsize=(10, 8))\ngs = GridSpec(3, 2, width_ratios=[2, 1])\nax0 = [fig.add_subplot(gs[i, 0], projection=proj) for i in range(3)]\nax1 = [fig.add_subplot(gs[i, 1]) for i in range(3)]\n\nfor i, (a0, a1) in enumerate(zip(ax0, ax1)):\n scores.sel(mode=i + 1).plot(ax=a0, **kwargs)\n a0.coastlines(color=\".5\")\n components.sel(mode=i + 1).plot(ax=a1)\n\n a0.set_xlabel(\"\")\n\nplt.tight_layout()\nplt.savefig(\"eof-tmode.jpg\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# EOF analysis (T-mode)\n", + "\n", + "EOF analysis in T-mode maximises the spatial variance.\n", + "\n", + "Load packages and data:\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import EqualEarth, PlateCarree\n", + "\n", + "from xeofs.models import EOF\n", + "\n", + "sst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform the actual analysis\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = EOF(n_modes=5)\n", + "model.fit(sst, dim=(\"lat\", \"lon\"))\n", + "expvar = model.explained_variance_ratio()\n", + "components = model.components()\n", + "scores = model.scores()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create figure showing the first two modes\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "proj = EqualEarth(central_longitude=180)\n", + "kwargs = {\"cmap\": \"RdBu\", \"transform\": PlateCarree()}\n", + "\n", + "fig = plt.figure(figsize=(10, 8))\n", + "gs = GridSpec(3, 2, width_ratios=[2, 1])\n", + "ax0 = [fig.add_subplot(gs[i, 0], projection=proj) for i in range(3)]\n", + "ax1 = [fig.add_subplot(gs[i, 1]) for i in range(3)]\n", + "\n", + "for i, (a0, a1) in enumerate(zip(ax0, ax1)):\n", + " scores.sel(mode=i + 1).plot(ax=a0, **kwargs)\n", + " a0.coastlines(color=\".5\")\n", + " components.sel(mode=i + 1).plot(ax=a1)\n", + "\n", + " a0.set_xlabel(\"\")\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"eof-tmode.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_eof-tmode.py b/docs/auto_examples/1single/plot_eof-tmode.py index 2afe0fdc..6a618e3e 100644 --- a/docs/auto_examples/1single/plot_eof-tmode.py +++ b/docs/auto_examples/1single/plot_eof-tmode.py @@ -6,6 +6,7 @@ Load packages and data: """ + import xarray as xr import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec diff --git a/docs/auto_examples/1single/plot_eof-tmode.py.md5 b/docs/auto_examples/1single/plot_eof-tmode.py.md5 index 20b785e8..0e6e4115 100644 --- a/docs/auto_examples/1single/plot_eof-tmode.py.md5 +++ b/docs/auto_examples/1single/plot_eof-tmode.py.md5 @@ -1 +1 @@ -79fe6be84ad4148428f14cf9f7754ca3 \ No newline at end of file +cb4eb5e93d5365bebbbecc2581f70358 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_eof-tmode.rst b/docs/auto_examples/1single/plot_eof-tmode.rst index f5f0083d..04053bb4 100644 --- a/docs/auto_examples/1single/plot_eof-tmode.rst +++ b/docs/auto_examples/1single/plot_eof-tmode.rst @@ -25,9 +25,10 @@ EOF analysis in T-mode maximises the spatial variance. Load packages and data: -.. GENERATED FROM PYTHON SOURCE LINES 9-18 +.. GENERATED FROM PYTHON SOURCE LINES 9-19 + +.. code-block:: Python -.. code-block:: default import xarray as xr import matplotlib.pyplot as plt @@ -45,13 +46,13 @@ Load packages and data: -.. GENERATED FROM PYTHON SOURCE LINES 19-20 +.. GENERATED FROM PYTHON SOURCE LINES 20-21 Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 20-27 +.. GENERATED FROM PYTHON SOURCE LINES 21-28 -.. code-block:: default +.. code-block:: Python model = EOF(n_modes=5) @@ -67,13 +68,13 @@ Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 28-29 +.. GENERATED FROM PYTHON SOURCE LINES 29-30 Create figure showing the first two modes -.. GENERATED FROM PYTHON SOURCE LINES 29-47 +.. GENERATED FROM PYTHON SOURCE LINES 30-48 -.. code-block:: default +.. code-block:: Python proj = EqualEarth(central_longitude=180) @@ -108,7 +109,7 @@ Create figure showing the first two modes .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 5.067 seconds) + **Total running time of the script:** (0 minutes 2.323 seconds) .. _sphx_glr_download_auto_examples_1single_plot_eof-tmode.py: @@ -117,17 +118,14 @@ Create figure showing the first two modes .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_eof-tmode.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_eof-tmode.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_eof-tmode.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_eof-tmode_codeobj.pickle b/docs/auto_examples/1single/plot_eof-tmode_codeobj.pickle index c73b089f..de37415c 100644 Binary files a/docs/auto_examples/1single/plot_eof-tmode_codeobj.pickle and b/docs/auto_examples/1single/plot_eof-tmode_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_gwpca.ipynb b/docs/auto_examples/1single/plot_gwpca.ipynb index de4c22ac..2d12398f 100644 --- a/docs/auto_examples/1single/plot_gwpca.ipynb +++ b/docs/auto_examples/1single/plot_gwpca.ipynb @@ -1,169 +1,293 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Geographically weighted PCA\nGeographically Weighted Principal Component Analysis (GWPCA) is a spatial analysis method that identifies and visualizes local spatial patterns and relationships in multivariate datasets across various geographic areas. It operates by applying PCA within a moving window over a geographical region, which enables the extraction of local principal components that can differ across locations.\n\nTIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_. \nThe dataset comprises 10 variables (chemical elements) and spans 768 samples. \nHere, each sample refers to a pair of latitude and longitude coordinates, representing specific sampling stations.\n\n.. [1] Reimann, C. et al. Baltic soil survey: total concentrations of major and selected trace elements in arable soils from 10 countries around the Baltic Sea. Science of The Total Environment 257, 155\u2013170 (2000).\n.. [2] https://rpubs.com/chrisbrunsdon/99675\n\n\n\n

    Note

    The dataset we're using is found in the R package \n [mvoutlier](https://cran.r-project.org/web/packages/mvoutlier/mvoutlier.pdf). \n To access it, we'll employ the Python package \n [rpy2](https://rpy2.github.io/doc/latest/html/index.html) which facilitates \n interaction with R packages from within Python.

    \n\n

    Note

    Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension. \n As a workaround, ``xarray.DataArray.to_array`` can be used to convert the ``Dataset`` to an ``DataArray``.

    \n\n

    Warning

    Bear in mind that GWPCA requires significant computational power.\n The ``xeofs`` implementation is optimized for CPU efficiency and is best suited \n for smaller to medium data sets. For more extensive datasets where parallel processing becomes essential,\n it's advisable to turn to the R package [GWmodel](https://cran.r-project.org/web/packages/GWmodel/GWmodel.pdf).\n This package harnesses CUDA to enable GPU-accelerated GWPCA for optimized performance.

    \n\n\nLet's import the necessary packages.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# For the analysis\nimport numpy as np\nimport xarray as xr\nimport xeofs as xe\n\n# For visualization\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# For accessing R packages\nimport rpy2.robjects as ro\nfrom rpy2.robjects.packages import importr\nfrom rpy2.robjects import pandas2ri" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we'll install the R package [mvoutlier](https://cran.r-project.org/web/packages/mvoutlier/mvoutlier.pdf)\nusing the [rpy2](https://rpy2.github.io/doc/latest/html/index.html) package.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "xr.set_options(display_expand_data=False)\nutils = importr(\"utils\")\nutils.chooseCRANmirror(ind=1)\nutils.install_packages(\"mvoutlier\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's load the dataset and convert it into a ``pandas.DataFrame``.\nAlongside, we'll also load the background data that outlines the borders of countries\nin the Baltic Sea region. This will help us visually represent the GWPCA results.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "ro.r(\n \"\"\"\n require(\"mvoutlier\")\n data(bsstop)\n Data <- bsstop[,1:14]\n background <- bss.background\n \"\"\"\n)\nwith (ro.default_converter + pandas2ri.converter).context():\n data_df = ro.conversion.get_conversion().rpy2py(ro.r[\"Data\"])\n background_df = ro.conversion.get_conversion().rpy2py(ro.r[\"background\"])\ndata_df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since ``xeofs`` uses ``xarray``, we convert the data into an ``xarray.DataArray``.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "data_df = data_df.rename(columns={\"ID\": \"station\"}).set_index(\"station\")\ndata = data_df.to_xarray()\ndata = data.rename({\"XCOO\": \"x\", \"YCOO\": \"y\"})\ndata = data.set_index(station=(\"x\", \"y\"))\ndata = data.drop_vars(\"CNo\")\nda = data.to_array(dim=\"element\")\nda" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's dive into the GWPCA. First, initialize a ``GWPCA`` instance and fit it to the data.\nThe ``station`` dimension serves as our sample dimension, along which the local PCAs will be applied.\nSince these PCAs need to gauge distances to adjacent stations, we must specify\na distance metric. Our station data includes coordinates in meters, so we'll\nchoose the ``euclidean`` metric. If you have coordinates in degrees (like\nlatitude and longitude), choose the ``haversine`` metric instead.\nWe're also using a ``bisquare`` kernel with a bandwidth of 1000 km. Note that the\nbandwidth unit always follows input data (which is in meters here),\nexcept when using the ``haversine`` metric, which always gives distances in\nkilometers. Lastly, we'll standardize the input to ensure consistent scales\nfor the chemical elements.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "gwpca = xe.models.GWPCA(\n n_modes=5,\n standardize=True,\n metric=\"euclidean\",\n kernel=\"bisquare\",\n bandwidth=1000000.0,\n)\ngwpca.fit(da, \"station\")\ngwpca.components()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The ``components`` method returns the local principal components for each station. Note that the\ndimensionality of the returned array is ``[station, element, mode]``, so in practice we don't really have\nreduced the dimensionality of the data set. However, we can\nextract the largest locally weighted components for each station which tells us which chemical elements\ndominate the local PCAs.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "llwc = gwpca.largest_locally_weighted_components()\nllwc" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's visualize the spatial patterns of the chemical elements.\nAs the stations are positioned on a irregular grid, we'll transform the\n``llwc`` ``DataArray`` into a ``pandas.DataFrame``. After that, we can easily visualize\nit using the ``scatter`` method.\nFor demonstation, we'll concentrate on the first mode:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "llwc1_df = llwc.sel(mode=1).to_dataframe()\n\nelements = da.element.values\nn_elements = len(elements)\ncolors = np.arange(n_elements)\ncol_dict = {el: col for el, col in zip(elements, colors)}\n\nllwc1_df[\"colors\"] = llwc1_df[\"largest_locally_weighted_components\"].map(col_dict)\ncmap = sns.color_palette(\"tab10\", n_colors=n_elements, as_cmap=True)\n\n\nfig = plt.figure(figsize=(10, 10))\nax = fig.add_subplot(111)\nbackground_df.plot.scatter(ax=ax, x=\"V1\", y=\"V2\", color=\".3\", marker=\".\", s=1)\ns = ax.scatter(\n x=llwc1_df[\"x\"],\n y=llwc1_df[\"y\"],\n c=llwc1_df[\"colors\"],\n ec=\"w\",\n s=40,\n cmap=cmap,\n vmin=-0.5,\n vmax=n_elements - 0.5,\n)\ncbar = fig.colorbar(mappable=s, ax=ax, label=\"Largest locally weighted component\")\ncbar.set_ticks(colors)\ncbar.set_ticklabels(elements)\nax.set_title(\"Largest locally weighted element\", loc=\"left\", weight=800)\nplt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the final step, let's examine the explained variance. Like standard PCA,\nthis gives us insight into the variance explained by each mode. But with a\nlocal PCA for every station, the explained variance varies spatially. Notably,\nthe first mode's explained variance differs across countries, ranging from\nroughly 40% to 70%.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "exp_var_ratio = gwpca.explained_variance_ratio()\nevr1_df = exp_var_ratio.sel(mode=1).to_dataframe()\n\nfig = plt.figure(figsize=(10, 10))\nax = fig.add_subplot(111)\nbackground_df.plot.scatter(ax=ax, x=\"V1\", y=\"V2\", color=\".3\", marker=\".\", s=1)\nevr1_df.plot.scatter(\n ax=ax, x=\"x\", y=\"y\", c=\"explained_variance_ratio\", vmin=0.4, vmax=0.7\n)\nax.set_title(\"Fraction of locally explained variance\", loc=\"left\", weight=800)\nplt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Geographically weighted PCA\n", + "Geographically Weighted Principal Component Analysis (GWPCA) is a spatial analysis method that identifies and visualizes local spatial patterns and relationships in multivariate datasets across various geographic areas. It operates by applying PCA within a moving window over a geographical region, which enables the extraction of local principal components that can differ across locations.\n", + "\n", + "TIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_.\n", + "The dataset comprises 10 variables (chemical elements) and spans 768 samples.\n", + "Here, each sample refers to a pair of latitude and longitude coordinates, representing specific sampling stations.\n", + "\n", + ".. [1] Reimann, C. et al. Baltic soil survey: total concentrations of major and selected trace elements in arable soils from 10 countries around the Baltic Sea. Science of The Total Environment 257, 155–170 (2000).\n", + ".. [2] https://rpubs.com/chrisbrunsdon/99675\n", + "\n", + "\n", + "\n", + "

    Note

    The dataset we're using is found in the R package\n", + " [mvoutlier](https://cran.r-project.org/web/packages/mvoutlier/mvoutlier.pdf).\n", + " To access it, we'll employ the Python package\n", + " [rpy2](https://rpy2.github.io/doc/latest/html/index.html) which facilitates\n", + " interaction with R packages from within Python.

    \n", + "\n", + "

    Note

    Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension.\n", + " As a workaround, ``xarray.DataArray.to_array`` can be used to convert the ``Dataset`` to an ``DataArray``.

    \n", + "\n", + "

    Warning

    Bear in mind that GWPCA requires significant computational power.\n", + " The ``xeofs`` implementation is optimized for CPU efficiency and is best suited\n", + " for smaller to medium data sets. For more extensive datasets where parallel processing becomes essential,\n", + " it's advisable to turn to the R package [GWmodel](https://cran.r-project.org/web/packages/GWmodel/GWmodel.pdf).\n", + " This package harnesses CUDA to enable GPU-accelerated GWPCA for optimized performance.

    \n", + "\n", + "\n", + "Let's import the necessary packages.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# For the analysis\n", + "import numpy as np\n", + "import xarray as xr\n", + "import xeofs as xe\n", + "\n", + "# For visualization\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "# For accessing R packages\n", + "import rpy2.robjects as ro\n", + "from rpy2.robjects.packages import importr\n", + "from rpy2.robjects import pandas2ri" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we'll install the R package [mvoutlier](https://cran.r-project.org/web/packages/mvoutlier/mvoutlier.pdf)\n", + "using the [rpy2](https://rpy2.github.io/doc/latest/html/index.html) package.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xr.set_options(display_expand_data=False)\n", + "utils = importr(\"utils\")\n", + "utils.chooseCRANmirror(ind=1)\n", + "utils.install_packages(\"mvoutlier\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's load the dataset and convert it into a ``pandas.DataFrame``.\n", + "Alongside, we'll also load the background data that outlines the borders of countries\n", + "in the Baltic Sea region. This will help us visually represent the GWPCA results.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ro.r(\n", + " \"\"\"\n", + " require(\"mvoutlier\")\n", + " data(bsstop)\n", + " Data <- bsstop[,1:14]\n", + " background <- bss.background\n", + " \"\"\"\n", + ")\n", + "with (ro.default_converter + pandas2ri.converter).context():\n", + " data_df = ro.conversion.get_conversion().rpy2py(ro.r[\"Data\"])\n", + " background_df = ro.conversion.get_conversion().rpy2py(ro.r[\"background\"])\n", + "data_df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since ``xeofs`` uses ``xarray``, we convert the data into an ``xarray.DataArray``.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data_df = data_df.rename(columns={\"ID\": \"station\"}).set_index(\"station\")\n", + "data = data_df.to_xarray()\n", + "data = data.rename({\"XCOO\": \"x\", \"YCOO\": \"y\"})\n", + "data = data.set_index(station=(\"x\", \"y\"))\n", + "data = data.drop_vars(\"CNo\")\n", + "da = data.to_array(dim=\"element\")\n", + "da" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's dive into the GWPCA. First, initialize a ``GWPCA`` instance and fit it to the data.\n", + "The ``station`` dimension serves as our sample dimension, along which the local PCAs will be applied.\n", + "Since these PCAs need to gauge distances to adjacent stations, we must specify\n", + "a distance metric. Our station data includes coordinates in meters, so we'll\n", + "choose the ``euclidean`` metric. If you have coordinates in degrees (like\n", + "latitude and longitude), choose the ``haversine`` metric instead.\n", + "We're also using a ``bisquare`` kernel with a bandwidth of 1000 km. Note that the\n", + "bandwidth unit always follows input data (which is in meters here),\n", + "except when using the ``haversine`` metric, which always gives distances in\n", + "kilometers. Lastly, we'll standardize the input to ensure consistent scales\n", + "for the chemical elements.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gwpca = xe.models.GWPCA(\n", + " n_modes=5,\n", + " standardize=True,\n", + " metric=\"euclidean\",\n", + " kernel=\"bisquare\",\n", + " bandwidth=1000000.0,\n", + ")\n", + "gwpca.fit(da, \"station\")\n", + "gwpca.components()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The ``components`` method returns the local principal components for each station. Note that the\n", + "dimensionality of the returned array is ``[station, element, mode]``, so in practice we don't really have\n", + "reduced the dimensionality of the data set. However, we can\n", + "extract the largest locally weighted components for each station which tells us which chemical elements\n", + "dominate the local PCAs.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "llwc = gwpca.largest_locally_weighted_components()\n", + "llwc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's visualize the spatial patterns of the chemical elements.\n", + "As the stations are positioned on a irregular grid, we'll transform the\n", + "``llwc`` ``DataArray`` into a ``pandas.DataFrame``. After that, we can easily visualize\n", + "it using the ``scatter`` method.\n", + "For demonstation, we'll concentrate on the first mode:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "llwc1_df = llwc.sel(mode=1).to_dataframe()\n", + "\n", + "elements = da.element.values\n", + "n_elements = len(elements)\n", + "colors = np.arange(n_elements)\n", + "col_dict = {el: col for el, col in zip(elements, colors)}\n", + "\n", + "llwc1_df[\"colors\"] = llwc1_df[\"largest_locally_weighted_components\"].map(col_dict)\n", + "cmap = sns.color_palette(\"tab10\", n_colors=n_elements, as_cmap=True)\n", + "\n", + "\n", + "fig = plt.figure(figsize=(10, 10))\n", + "ax = fig.add_subplot(111)\n", + "background_df.plot.scatter(ax=ax, x=\"V1\", y=\"V2\", color=\".3\", marker=\".\", s=1)\n", + "s = ax.scatter(\n", + " x=llwc1_df[\"x\"],\n", + " y=llwc1_df[\"y\"],\n", + " c=llwc1_df[\"colors\"],\n", + " ec=\"w\",\n", + " s=40,\n", + " cmap=cmap,\n", + " vmin=-0.5,\n", + " vmax=n_elements - 0.5,\n", + ")\n", + "cbar = fig.colorbar(mappable=s, ax=ax, label=\"Largest locally weighted component\")\n", + "cbar.set_ticks(colors)\n", + "cbar.set_ticklabels(elements)\n", + "ax.set_title(\"Largest locally weighted element\", loc=\"left\", weight=800)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the final step, let's examine the explained variance. Like standard PCA,\n", + "this gives us insight into the variance explained by each mode. But with a\n", + "local PCA for every station, the explained variance varies spatially. Notably,\n", + "the first mode's explained variance differs across countries, ranging from\n", + "roughly 40% to 70%.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "exp_var_ratio = gwpca.explained_variance_ratio()\n", + "evr1_df = exp_var_ratio.sel(mode=1).to_dataframe()\n", + "\n", + "fig = plt.figure(figsize=(10, 10))\n", + "ax = fig.add_subplot(111)\n", + "background_df.plot.scatter(ax=ax, x=\"V1\", y=\"V2\", color=\".3\", marker=\".\", s=1)\n", + "evr1_df.plot.scatter(\n", + " ax=ax, x=\"x\", y=\"y\", c=\"explained_variance_ratio\", vmin=0.4, vmax=0.7\n", + ")\n", + "ax.set_title(\"Fraction of locally explained variance\", loc=\"left\", weight=800)\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_gwpca.py b/docs/auto_examples/1single/plot_gwpca.py index a0842832..f1542228 100644 --- a/docs/auto_examples/1single/plot_gwpca.py +++ b/docs/auto_examples/1single/plot_gwpca.py @@ -3,8 +3,8 @@ =========================== Geographically Weighted Principal Component Analysis (GWPCA) is a spatial analysis method that identifies and visualizes local spatial patterns and relationships in multivariate datasets across various geographic areas. It operates by applying PCA within a moving window over a geographical region, which enables the extraction of local principal components that can differ across locations. -TIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_. -The dataset comprises 10 variables (chemical elements) and spans 768 samples. +TIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_. +The dataset comprises 10 variables (chemical elements) and spans 768 samples. Here, each sample refers to a pair of latitude and longitude coordinates, representing specific sampling stations. .. [1] Reimann, C. et al. Baltic soil survey: total concentrations of major and selected trace elements in arable soils from 10 countries around the Baltic Sea. Science of The Total Environment 257, 155–170 (2000). @@ -12,17 +12,17 @@ -.. note:: The dataset we're using is found in the R package - `mvoutlier `_. - To access it, we'll employ the Python package - `rpy2 `_ which facilitates - interaction with R packages from within Python. +.. note:: The dataset we're using is found in the R package + `mvoutlier `_. + To access it, we'll employ the Python package + `rpy2 `_ which facilitates + interaction with R packages from within Python. -.. note:: Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension. +.. note:: Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension. As a workaround, ``xarray.DataArray.to_array`` can be used to convert the ``Dataset`` to an ``DataArray``. .. warning:: Bear in mind that GWPCA requires significant computational power. - The ``xeofs`` implementation is optimized for CPU efficiency and is best suited + The ``xeofs`` implementation is optimized for CPU efficiency and is best suited for smaller to medium data sets. For more extensive datasets where parallel processing becomes essential, it's advisable to turn to the R package `GWmodel `_. This package harnesses CUDA to enable GPU-accelerated GWPCA for optimized performance. @@ -30,6 +30,7 @@ Let's import the necessary packages. """ + # For the analysis import numpy as np import xarray as xr diff --git a/docs/auto_examples/1single/plot_gwpca.py.md5 b/docs/auto_examples/1single/plot_gwpca.py.md5 index 6e37a983..638f2378 100644 --- a/docs/auto_examples/1single/plot_gwpca.py.md5 +++ b/docs/auto_examples/1single/plot_gwpca.py.md5 @@ -1 +1 @@ -958e12c0ca3bfc03fe27e2e22362e165 \ No newline at end of file +77b9f112f4bc958b9490200a1e64d954 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_gwpca.rst b/docs/auto_examples/1single/plot_gwpca.rst index 5dfbd851..11fe5aa3 100644 --- a/docs/auto_examples/1single/plot_gwpca.rst +++ b/docs/auto_examples/1single/plot_gwpca.rst @@ -22,8 +22,8 @@ Geographically weighted PCA =========================== Geographically Weighted Principal Component Analysis (GWPCA) is a spatial analysis method that identifies and visualizes local spatial patterns and relationships in multivariate datasets across various geographic areas. It operates by applying PCA within a moving window over a geographical region, which enables the extraction of local principal components that can differ across locations. -TIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_. -The dataset comprises 10 variables (chemical elements) and spans 768 samples. +TIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_. +The dataset comprises 10 variables (chemical elements) and spans 768 samples. Here, each sample refers to a pair of latitude and longitude coordinates, representing specific sampling stations. .. [1] Reimann, C. et al. Baltic soil survey: total concentrations of major and selected trace elements in arable soils from 10 countries around the Baltic Sea. Science of The Total Environment 257, 155–170 (2000). @@ -31,17 +31,17 @@ Here, each sample refers to a pair of latitude and longitude coordinates, repres -.. note:: The dataset we're using is found in the R package - `mvoutlier `_. - To access it, we'll employ the Python package - `rpy2 `_ which facilitates - interaction with R packages from within Python. +.. note:: The dataset we're using is found in the R package + `mvoutlier `_. + To access it, we'll employ the Python package + `rpy2 `_ which facilitates + interaction with R packages from within Python. -.. note:: Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension. +.. note:: Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension. As a workaround, ``xarray.DataArray.to_array`` can be used to convert the ``Dataset`` to an ``DataArray``. .. warning:: Bear in mind that GWPCA requires significant computational power. - The ``xeofs`` implementation is optimized for CPU efficiency and is best suited + The ``xeofs`` implementation is optimized for CPU efficiency and is best suited for smaller to medium data sets. For more extensive datasets where parallel processing becomes essential, it's advisable to turn to the R package `GWmodel `_. This package harnesses CUDA to enable GPU-accelerated GWPCA for optimized performance. @@ -49,9 +49,10 @@ Here, each sample refers to a pair of latitude and longitude coordinates, repres Let's import the necessary packages. -.. GENERATED FROM PYTHON SOURCE LINES 33-47 +.. GENERATED FROM PYTHON SOURCE LINES 33-48 + +.. code-block:: Python -.. code-block:: default # For the analysis import numpy as np @@ -74,14 +75,14 @@ Let's import the necessary packages. -.. GENERATED FROM PYTHON SOURCE LINES 48-50 +.. GENERATED FROM PYTHON SOURCE LINES 49-51 Next, we'll install the R package `mvoutlier `_ using the `rpy2 `_ package. -.. GENERATED FROM PYTHON SOURCE LINES 50-56 +.. GENERATED FROM PYTHON SOURCE LINES 51-57 -.. code-block:: default +.. code-block:: Python xr.set_options(display_expand_data=False) @@ -97,6 +98,189 @@ using the `rpy2 `_ package. .. code-block:: none + R[write to console]: also installing the dependencies ‘DEoptimR’, ‘sgeostat’, ‘robustbase’ + + + R[write to console]: trying URL 'https://cloud.r-project.org/src/contrib/DEoptimR_1.1-3.tar.gz' + + R[write to console]: Content type 'application/x-gzip' + R[write to console]: length 19222 bytes (18 KB) + + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: + + R[write to console]: downloaded 18 KB + + + R[write to console]: trying URL 'https://cloud.r-project.org/src/contrib/sgeostat_1.0-27.tar.gz' + + R[write to console]: Content type 'application/x-gzip' + R[write to console]: length 35685 bytes (34 KB) + + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: + + R[write to console]: downloaded 34 KB + + + R[write to console]: trying URL 'https://cloud.r-project.org/src/contrib/robustbase_0.99-2.tar.gz' + + R[write to console]: Content type 'application/x-gzip' + R[write to console]: length 2292086 bytes (2.2 MB) + + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: = + R[write to console]: + + R[write to console]: downloaded 2.2 MB + + R[write to console]: trying URL 'https://cloud.r-project.org/src/contrib/mvoutlier_2.1.1.tar.gz' R[write to console]: Content type 'application/x-gzip' @@ -161,7 +345,7 @@ using the `rpy2 `_ package. R[write to console]: R[write to console]: The downloaded source packages are in - ‘/tmp/RtmpzcnwC4/downloaded_packages’ + ‘/tmp/Rtmpr8iXHn/downloaded_packages’ R[write to console]: R[write to console]: @@ -171,19 +355,19 @@ using the `rpy2 `_ package. R[write to console]: done - [0] + [0] -.. GENERATED FROM PYTHON SOURCE LINES 57-60 +.. GENERATED FROM PYTHON SOURCE LINES 58-61 Let's load the dataset and convert it into a ``pandas.DataFrame``. Alongside, we'll also load the background data that outlines the borders of countries in the Baltic Sea region. This will help us visually represent the GWPCA results. -.. GENERATED FROM PYTHON SOURCE LINES 60-74 +.. GENERATED FROM PYTHON SOURCE LINES 61-75 -.. code-block:: default +.. code-block:: Python ro.r( @@ -343,13 +527,13 @@ in the Baltic Sea region. This will help us visually represent the GWPCA results

    -.. GENERATED FROM PYTHON SOURCE LINES 75-76 +.. GENERATED FROM PYTHON SOURCE LINES 76-77 Since ``xeofs`` uses ``xarray``, we convert the data into an ``xarray.DataArray``. -.. GENERATED FROM PYTHON SOURCE LINES 76-85 +.. GENERATED FROM PYTHON SOURCE LINES 77-86 -.. code-block:: default +.. code-block:: Python data_df = data_df.rename(columns={"ID": "station"}).set_index("station") @@ -731,22 +915,22 @@ Since ``xeofs`` uses ``xarray``, we convert the data into an ``xarray.DataArray` stroke: currentColor; fill: currentColor; } -
    <xarray.DataArray (element: 10, station: 768)>
    +    
    <xarray.DataArray (element: 10, station: 768)> Size: 61kB
         43.61 58.73 58.14 43.98 60.9 54.0 82.72 ... 0.196 0.202 0.207 0.109 0.141 0.185
         Coordinates:
    -      * station  (station) object MultiIndex
    -      * x        (station) float64 -6.197e+05 2.147e+05 ... -2.82e+05 -1.273e+05
    -      * y        (station) float64 6.805e+06 7.746e+06 ... 5.796e+06 6.523e+06
    -      * element  (element) object 'SiO2_T' 'TiO2_T' 'Al2O3_T' ... 'K2O_T' 'P2O5_T'


  • -.. GENERATED FROM PYTHON SOURCE LINES 86-97 +.. GENERATED FROM PYTHON SOURCE LINES 87-98 Let's dive into the GWPCA. First, initialize a ``GWPCA`` instance and fit it to the data. The ``station`` dimension serves as our sample dimension, along which the local PCAs will be applied. @@ -788,9 +972,9 @@ except when using the ``haversine`` metric, which always gives distances in kilometers. Lastly, we'll standardize the input to ensure consistent scales for the chemical elements. -.. GENERATED FROM PYTHON SOURCE LINES 97-109 +.. GENERATED FROM PYTHON SOURCE LINES 98-110 -.. code-block:: default +.. code-block:: Python gwpca = xe.models.GWPCA( @@ -1175,28 +1359,28 @@ for the chemical elements. stroke: currentColor; fill: currentColor; } -
    <xarray.DataArray 'components' (mode: 5, element: 10, station: 768)>
    +    
    <xarray.DataArray 'components' (mode: 5, element: 10, station: 768)> Size: 307kB
         0.1813 -0.3584 0.1243 0.2 -0.3812 ... 0.1229 -0.2865 0.4732 0.4197 -0.4249
         Coordinates:
    -      * mode     (mode) int64 1 2 3 4 5
    -      * element  (element) object 'SiO2_T' 'TiO2_T' 'Al2O3_T' ... 'K2O_T' 'P2O5_T'
    -      * station  (station) object MultiIndex
    -      * x        (station) float64 -6.197e+05 2.147e+05 ... -2.82e+05 -1.273e+05
    -      * y        (station) float64 6.805e+06 7.746e+06 ... 5.796e+06 6.523e+06
    -    Attributes: (12/13)
    -        model:         GWPCA
    -        software:      xeofs
    -        version:       1.2.0
    -        date:          2023-10-25 19:16:03
    -        n_modes:       5
    -        center:        True
    -        ...            ...
    -        use_coslat:    False
    -        sample_name:   sample
    -        feature_name:  feature
    -        random_state:  None
    -        compute:       True
    -        solver:        auto
  • model :
    GWPCA
    software :
    xeofs
    version :
    2.3.2
    date :
    2024-03-31 21:13:03
    n_modes :
    5
    center :
    True
    standardize :
    True
    use_coslat :
    False
    check_nans :
    True
    sample_name :
    sample
    feature_name :
    feature
    random_state :
    None
    verbose :
    False
    compute :
    True
    solver :
    auto
    solver_kwargs :
    {}


  • -.. GENERATED FROM PYTHON SOURCE LINES 110-115 +.. GENERATED FROM PYTHON SOURCE LINES 111-116 The ``components`` method returns the local principal components for each station. Note that the dimensionality of the returned array is ``[station, element, mode]``, so in practice we don't really have @@ -1275,9 +1459,9 @@ reduced the dimensionality of the data set. However, we can extract the largest locally weighted components for each station which tells us which chemical elements dominate the local PCAs. -.. GENERATED FROM PYTHON SOURCE LINES 115-119 +.. GENERATED FROM PYTHON SOURCE LINES 116-120 -.. code-block:: default +.. code-block:: Python llwc = gwpca.largest_locally_weighted_components() @@ -1654,20 +1838,20 @@ dominate the local PCAs. stroke: currentColor; fill: currentColor; } -
    <xarray.DataArray 'largest_locally_weighted_components' (mode: 5, station: 768)>
    +    
    <xarray.DataArray 'largest_locally_weighted_components' (mode: 5, station: 768)> Size: 31kB
         'MgO_T' 'Al2O3_T' 'MgO_T' 'TiO2_T' ... 'K2O_T' 'Fe2O3_T' 'Fe2O3_T' 'CaO_T'
         Coordinates:
    -      * mode     (mode) int64 1 2 3 4 5
    -      * station  (station) object MultiIndex
    -      * x        (station) float64 -6.197e+05 2.147e+05 ... -2.82e+05 -1.273e+05
    -      * y        (station) float64 6.805e+06 7.746e+06 ... 5.796e+06 6.523e+06


  • -.. GENERATED FROM PYTHON SOURCE LINES 120-125 +.. GENERATED FROM PYTHON SOURCE LINES 121-126 Let's visualize the spatial patterns of the chemical elements. As the stations are positioned on a irregular grid, we'll transform the @@ -1701,9 +1885,9 @@ As the stations are positioned on a irregular grid, we'll transform the it using the ``scatter`` method. For demonstation, we'll concentrate on the first mode: -.. GENERATED FROM PYTHON SOURCE LINES 125-156 +.. GENERATED FROM PYTHON SOURCE LINES 126-157 -.. code-block:: default +.. code-block:: Python llwc1_df = llwc.sel(mode=1).to_dataframe() @@ -1748,7 +1932,7 @@ For demonstation, we'll concentrate on the first mode: -.. GENERATED FROM PYTHON SOURCE LINES 157-162 +.. GENERATED FROM PYTHON SOURCE LINES 158-163 In the final step, let's examine the explained variance. Like standard PCA, this gives us insight into the variance explained by each mode. But with a @@ -1756,9 +1940,9 @@ local PCA for every station, the explained variance varies spatially. Notably, the first mode's explained variance differs across countries, ranging from roughly 40% to 70%. -.. GENERATED FROM PYTHON SOURCE LINES 162-175 +.. GENERATED FROM PYTHON SOURCE LINES 163-176 -.. code-block:: default +.. code-block:: Python @@ -1788,7 +1972,7 @@ roughly 40% to 70%. .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 28.277 seconds) + **Total running time of the script:** (0 minutes 34.593 seconds) .. _sphx_glr_download_auto_examples_1single_plot_gwpca.py: @@ -1797,17 +1981,14 @@ roughly 40% to 70%. .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_gwpca.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_gwpca.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_gwpca.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_gwpca_codeobj.pickle b/docs/auto_examples/1single/plot_gwpca_codeobj.pickle index 7bd75139..508520c6 100644 Binary files a/docs/auto_examples/1single/plot_gwpca_codeobj.pickle and b/docs/auto_examples/1single/plot_gwpca_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_mreof.ipynb b/docs/auto_examples/1single/plot_mreof.ipynb index 03fa86ff..9eceb7e9 100644 --- a/docs/auto_examples/1single/plot_mreof.ipynb +++ b/docs/auto_examples/1single/plot_mreof.ipynb @@ -1,97 +1,143 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Varimax-rotated Multivariate EOF analysis\n\nMultivariate EOF analysis with additional Varimax rotation.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Load packages and data:\nimport xarray as xr\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import PlateCarree\n\nfrom xeofs.models import EOF, EOFRotator" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create four different dataarrayss\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "sst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]\nsubset1 = sst.isel(lon=slice(0, 45))\nsubset2 = sst.isel(lon=slice(46, 90))\nsubset3 = sst.isel(lon=slice(91, 135))\nsubset4 = sst.isel(lon=slice(136, None))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform the actual analysis\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "multivariate_data = [subset1, subset2, subset3, subset4]\nmpca = EOF(n_modes=100, standardize=False, use_coslat=True)\nmpca.fit(multivariate_data, dim=\"time\")\nrotator = EOFRotator(n_modes=20)\nrotator.fit(mpca)\nrcomponents = rotator.components()\nrscores = rotator.scores()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Plot mode 1\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "mode = 5\nproj = PlateCarree()\nkwargs = {\n \"cmap\": \"RdBu\",\n \"vmin\": -0.05,\n \"vmax\": 0.05,\n \"transform\": proj,\n \"add_colorbar\": False,\n}\n\nfig = plt.figure(figsize=(7.3, 6))\nfig.subplots_adjust(wspace=0)\ngs = GridSpec(2, 4, figure=fig, width_ratios=[1, 1, 1, 1])\nax = [fig.add_subplot(gs[0, i], projection=proj) for i in range(4)]\nax_pc = fig.add_subplot(gs[1, :])\n\n# PC\nrscores.sel(mode=mode).plot(ax=ax_pc)\nax_pc.set_xlabel(\"\")\nax_pc.set_title(\"\")\n\n# EOFs\nfor i, (a, comps) in enumerate(zip(ax, rcomponents)):\n a.coastlines(color=\".5\")\n comps.sel(mode=mode).plot(ax=a, **kwargs)\n a.set_xticks([])\n a.set_yticks([])\n a.set_xlabel(\"\")\n a.set_ylabel(\"\")\n a.set_title(\"Subset {:}\".format(i + 1))\nax[0].set_ylabel(\"EOFs\")\nfig.suptitle(\"Mode {:}\".format(mode))\nplt.savefig(\"mreof-analysis.jpg\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Varimax-rotated Multivariate EOF analysis\n", + "\n", + "Multivariate EOF analysis with additional Varimax rotation.\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load packages and data:\n", + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import PlateCarree\n", + "\n", + "from xeofs.models import EOF, EOFRotator" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create four different dataarrayss\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]\n", + "subset1 = sst.isel(lon=slice(0, 45))\n", + "subset2 = sst.isel(lon=slice(46, 90))\n", + "subset3 = sst.isel(lon=slice(91, 135))\n", + "subset4 = sst.isel(lon=slice(136, None))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform the actual analysis\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "multivariate_data = [subset1, subset2, subset3, subset4]\n", + "mpca = EOF(n_modes=100, standardize=False, use_coslat=True)\n", + "mpca.fit(multivariate_data, dim=\"time\")\n", + "rotator = EOFRotator(n_modes=20)\n", + "rotator.fit(mpca)\n", + "rcomponents = rotator.components()\n", + "rscores = rotator.scores()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot mode 1\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mode = 5\n", + "proj = PlateCarree()\n", + "kwargs = {\n", + " \"cmap\": \"RdBu\",\n", + " \"vmin\": -0.05,\n", + " \"vmax\": 0.05,\n", + " \"transform\": proj,\n", + " \"add_colorbar\": False,\n", + "}\n", + "\n", + "fig = plt.figure(figsize=(7.3, 6))\n", + "fig.subplots_adjust(wspace=0)\n", + "gs = GridSpec(2, 4, figure=fig, width_ratios=[1, 1, 1, 1])\n", + "ax = [fig.add_subplot(gs[0, i], projection=proj) for i in range(4)]\n", + "ax_pc = fig.add_subplot(gs[1, :])\n", + "\n", + "# PC\n", + "rscores.sel(mode=mode).plot(ax=ax_pc)\n", + "ax_pc.set_xlabel(\"\")\n", + "ax_pc.set_title(\"\")\n", + "\n", + "# EOFs\n", + "for i, (a, comps) in enumerate(zip(ax, rcomponents)):\n", + " a.coastlines(color=\".5\")\n", + " comps.sel(mode=mode).plot(ax=a, **kwargs)\n", + " a.set_xticks([], [])\n", + " a.set_yticks([], [])\n", + " a.set_xlabel(\"\")\n", + " a.set_ylabel(\"\")\n", + " a.set_title(\"Subset {:}\".format(i + 1))\n", + "ax[0].set_ylabel(\"EOFs\")\n", + "fig.suptitle(\"Mode {:}\".format(mode))\n", + "plt.savefig(\"mreof-analysis.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_mreof.py b/docs/auto_examples/1single/plot_mreof.py index cafbe67e..5bbc6a0f 100644 --- a/docs/auto_examples/1single/plot_mreof.py +++ b/docs/auto_examples/1single/plot_mreof.py @@ -5,7 +5,6 @@ Multivariate EOF analysis with additional Varimax rotation. """ - # Load packages and data: import xarray as xr import matplotlib.pyplot as plt @@ -61,8 +60,8 @@ for i, (a, comps) in enumerate(zip(ax, rcomponents)): a.coastlines(color=".5") comps.sel(mode=mode).plot(ax=a, **kwargs) - a.set_xticks([]) - a.set_yticks([]) + a.set_xticks([], []) + a.set_yticks([], []) a.set_xlabel("") a.set_ylabel("") a.set_title("Subset {:}".format(i + 1)) diff --git a/docs/auto_examples/1single/plot_mreof.py.md5 b/docs/auto_examples/1single/plot_mreof.py.md5 index 5ab19f35..57db41e3 100644 --- a/docs/auto_examples/1single/plot_mreof.py.md5 +++ b/docs/auto_examples/1single/plot_mreof.py.md5 @@ -1 +1 @@ -410e1d6510453237ba075f29352a1b1c \ No newline at end of file +26962c4661f0e87127e3ebcadae33bb7 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_mreof.rst b/docs/auto_examples/1single/plot_mreof.rst index e8a560af..105ef3cc 100644 --- a/docs/auto_examples/1single/plot_mreof.rst +++ b/docs/auto_examples/1single/plot_mreof.rst @@ -23,10 +23,9 @@ Varimax-rotated Multivariate EOF analysis Multivariate EOF analysis with additional Varimax rotation. -.. GENERATED FROM PYTHON SOURCE LINES 7-17 - -.. code-block:: default +.. GENERATED FROM PYTHON SOURCE LINES 7-16 +.. code-block:: Python # Load packages and data: @@ -44,13 +43,13 @@ Multivariate EOF analysis with additional Varimax rotation. -.. GENERATED FROM PYTHON SOURCE LINES 18-19 +.. GENERATED FROM PYTHON SOURCE LINES 17-18 Create four different dataarrayss -.. GENERATED FROM PYTHON SOURCE LINES 19-25 +.. GENERATED FROM PYTHON SOURCE LINES 18-24 -.. code-block:: default +.. code-block:: Python sst = xr.tutorial.open_dataset("ersstv5")["sst"] subset1 = sst.isel(lon=slice(0, 45)) @@ -65,13 +64,13 @@ Create four different dataarrayss -.. GENERATED FROM PYTHON SOURCE LINES 26-27 +.. GENERATED FROM PYTHON SOURCE LINES 25-26 Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 27-36 +.. GENERATED FROM PYTHON SOURCE LINES 26-35 -.. code-block:: default +.. code-block:: Python multivariate_data = [subset1, subset2, subset3, subset4] @@ -89,13 +88,13 @@ Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 37-38 +.. GENERATED FROM PYTHON SOURCE LINES 36-37 Plot mode 1 -.. GENERATED FROM PYTHON SOURCE LINES 38-72 +.. GENERATED FROM PYTHON SOURCE LINES 37-71 -.. code-block:: default +.. code-block:: Python mode = 5 @@ -123,8 +122,8 @@ Plot mode 1 for i, (a, comps) in enumerate(zip(ax, rcomponents)): a.coastlines(color=".5") comps.sel(mode=mode).plot(ax=a, **kwargs) - a.set_xticks([]) - a.set_yticks([]) + a.set_xticks([], []) + a.set_yticks([], []) a.set_xlabel("") a.set_ylabel("") a.set_title("Subset {:}".format(i + 1)) @@ -146,7 +145,7 @@ Plot mode 1 .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 6.486 seconds) + **Total running time of the script:** (0 minutes 1.727 seconds) .. _sphx_glr_download_auto_examples_1single_plot_mreof.py: @@ -155,17 +154,14 @@ Plot mode 1 .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_mreof.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_mreof.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_mreof.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_mreof_codeobj.pickle b/docs/auto_examples/1single/plot_mreof_codeobj.pickle index 49965c5e..bd2093e1 100644 Binary files a/docs/auto_examples/1single/plot_mreof_codeobj.pickle and b/docs/auto_examples/1single/plot_mreof_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_multivariate-eof.ipynb b/docs/auto_examples/1single/plot_multivariate-eof.ipynb index 0ae61a98..6983769d 100644 --- a/docs/auto_examples/1single/plot_multivariate-eof.ipynb +++ b/docs/auto_examples/1single/plot_multivariate-eof.ipynb @@ -1,79 +1,127 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Multivariate EOF analysis\n\nMultivariate EOF analysis.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Load packages and data:\nimport xarray as xr\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import PlateCarree\n\nfrom xeofs.models import EOF\n\n# Create four different dataarrayss\nsst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]\nsubset1 = sst.isel(lon=slice(0, 45))\nsubset2 = sst.isel(lon=slice(46, 90))\nsubset3 = sst.isel(lon=slice(91, 135))\nsubset4 = sst.isel(lon=slice(136, None))\nmultivariate_data = [subset1, subset2, subset3, subset4]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform the actual analysis\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "pca = EOF(n_modes=10, standardize=False, use_coslat=True)\npca.fit(multivariate_data, dim=\"time\")\ncomponents = pca.components()\nscores = pca.scores()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Plot mode 1\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "mode = 5\nproj = PlateCarree()\nkwargs = {\n \"cmap\": \"RdBu\",\n \"vmin\": -0.05,\n \"vmax\": 0.05,\n \"transform\": proj,\n \"add_colorbar\": False,\n}\n\nfig = plt.figure(figsize=(7.3, 6))\nfig.subplots_adjust(wspace=0)\ngs = GridSpec(2, 4, figure=fig, width_ratios=[1, 1, 1, 1])\nax = [fig.add_subplot(gs[0, i], projection=proj) for i in range(4)]\nax_pc = fig.add_subplot(gs[1, :])\n\n# PC\nscores.sel(mode=mode).plot(ax=ax_pc)\nax_pc.set_xlabel(\"\")\nax_pc.set_title(\"\")\n\n# EOFs\nfor i, (a, comps) in enumerate(zip(ax, components)):\n a.coastlines(color=\".5\")\n comps.sel(mode=mode).plot(ax=a, **kwargs)\n a.set_xticks([])\n a.set_yticks([])\n a.set_xlabel(\"\")\n a.set_ylabel(\"\")\n a.set_title(\"Subset {:}\".format(i + 1))\nax[0].set_ylabel(\"EOFs\")\nfig.suptitle(\"Mode {:}\".format(mode))\nplt.savefig(\"multivariate-eof-analysis.jpg\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Multivariate EOF analysis\n", + "\n", + "Multivariate EOF analysis.\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load packages and data:\n", + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import PlateCarree\n", + "\n", + "from xeofs.models import EOF\n", + "\n", + "# Create four different dataarrayss\n", + "sst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]\n", + "subset1 = sst.isel(lon=slice(0, 45))\n", + "subset2 = sst.isel(lon=slice(46, 90))\n", + "subset3 = sst.isel(lon=slice(91, 135))\n", + "subset4 = sst.isel(lon=slice(136, None))\n", + "multivariate_data = [subset1, subset2, subset3, subset4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform the actual analysis\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pca = EOF(n_modes=10, standardize=False, use_coslat=True)\n", + "pca.fit(multivariate_data, dim=\"time\")\n", + "components = pca.components()\n", + "scores = pca.scores()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot mode 1\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mode = 5\n", + "proj = PlateCarree()\n", + "kwargs = {\n", + " \"cmap\": \"RdBu\",\n", + " \"vmin\": -0.05,\n", + " \"vmax\": 0.05,\n", + " \"transform\": proj,\n", + " \"add_colorbar\": False,\n", + "}\n", + "\n", + "fig = plt.figure(figsize=(7.3, 6))\n", + "fig.subplots_adjust(wspace=0)\n", + "gs = GridSpec(2, 4, figure=fig, width_ratios=[1, 1, 1, 1])\n", + "ax = [fig.add_subplot(gs[0, i], projection=proj) for i in range(4)]\n", + "ax_pc = fig.add_subplot(gs[1, :])\n", + "\n", + "# PC\n", + "scores.sel(mode=mode).plot(ax=ax_pc)\n", + "ax_pc.set_xlabel(\"\")\n", + "ax_pc.set_title(\"\")\n", + "\n", + "# EOFs\n", + "for i, (a, comps) in enumerate(zip(ax, components)):\n", + " a.coastlines(color=\".5\")\n", + " comps.sel(mode=mode).plot(ax=a, **kwargs)\n", + " a.set_xticks([], [])\n", + " a.set_yticks([], [])\n", + " a.set_xlabel(\"\")\n", + " a.set_ylabel(\"\")\n", + " a.set_title(\"Subset {:}\".format(i + 1))\n", + "ax[0].set_ylabel(\"EOFs\")\n", + "fig.suptitle(\"Mode {:}\".format(mode))\n", + "plt.savefig(\"multivariate-eof-analysis.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_multivariate-eof.py b/docs/auto_examples/1single/plot_multivariate-eof.py index 85331795..31c6f623 100644 --- a/docs/auto_examples/1single/plot_multivariate-eof.py +++ b/docs/auto_examples/1single/plot_multivariate-eof.py @@ -5,7 +5,6 @@ Multivariate EOF analysis. """ - # Load packages and data: import xarray as xr import matplotlib.pyplot as plt @@ -58,8 +57,8 @@ for i, (a, comps) in enumerate(zip(ax, components)): a.coastlines(color=".5") comps.sel(mode=mode).plot(ax=a, **kwargs) - a.set_xticks([]) - a.set_yticks([]) + a.set_xticks([], []) + a.set_yticks([], []) a.set_xlabel("") a.set_ylabel("") a.set_title("Subset {:}".format(i + 1)) diff --git a/docs/auto_examples/1single/plot_multivariate-eof.py.md5 b/docs/auto_examples/1single/plot_multivariate-eof.py.md5 index 17547cfd..d14cd21e 100644 --- a/docs/auto_examples/1single/plot_multivariate-eof.py.md5 +++ b/docs/auto_examples/1single/plot_multivariate-eof.py.md5 @@ -1 +1 @@ -5b802ea42e5a2e0309a67468761e34cc \ No newline at end of file +d76ccd30400590a4e6d49d598bbdb423 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_multivariate-eof.rst b/docs/auto_examples/1single/plot_multivariate-eof.rst index b41154f1..f0ef5c22 100644 --- a/docs/auto_examples/1single/plot_multivariate-eof.rst +++ b/docs/auto_examples/1single/plot_multivariate-eof.rst @@ -23,10 +23,9 @@ Multivariate EOF analysis Multivariate EOF analysis. -.. GENERATED FROM PYTHON SOURCE LINES 7-25 - -.. code-block:: default +.. GENERATED FROM PYTHON SOURCE LINES 7-24 +.. code-block:: Python # Load packages and data: @@ -52,13 +51,13 @@ Multivariate EOF analysis. -.. GENERATED FROM PYTHON SOURCE LINES 26-27 +.. GENERATED FROM PYTHON SOURCE LINES 25-26 Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 27-33 +.. GENERATED FROM PYTHON SOURCE LINES 26-32 -.. code-block:: default +.. code-block:: Python pca = EOF(n_modes=10, standardize=False, use_coslat=True) @@ -73,13 +72,13 @@ Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 34-35 +.. GENERATED FROM PYTHON SOURCE LINES 33-34 Plot mode 1 -.. GENERATED FROM PYTHON SOURCE LINES 35-69 +.. GENERATED FROM PYTHON SOURCE LINES 34-68 -.. code-block:: default +.. code-block:: Python mode = 5 @@ -107,8 +106,8 @@ Plot mode 1 for i, (a, comps) in enumerate(zip(ax, components)): a.coastlines(color=".5") comps.sel(mode=mode).plot(ax=a, **kwargs) - a.set_xticks([]) - a.set_yticks([]) + a.set_xticks([], []) + a.set_yticks([], []) a.set_xlabel("") a.set_ylabel("") a.set_title("Subset {:}".format(i + 1)) @@ -130,7 +129,7 @@ Plot mode 1 .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 2.932 seconds) + **Total running time of the script:** (0 minutes 1.211 seconds) .. _sphx_glr_download_auto_examples_1single_plot_multivariate-eof.py: @@ -139,17 +138,14 @@ Plot mode 1 .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_multivariate-eof.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_multivariate-eof.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_multivariate-eof.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_multivariate-eof_codeobj.pickle b/docs/auto_examples/1single/plot_multivariate-eof_codeobj.pickle index 05337597..96521a56 100644 Binary files a/docs/auto_examples/1single/plot_multivariate-eof_codeobj.pickle and b/docs/auto_examples/1single/plot_multivariate-eof_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_rotated_eof.ipynb b/docs/auto_examples/1single/plot_rotated_eof.ipynb index 57a58b8a..b92799d3 100644 --- a/docs/auto_examples/1single/plot_rotated_eof.ipynb +++ b/docs/auto_examples/1single/plot_rotated_eof.ipynb @@ -1,79 +1,156 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Rotated EOF analysis\n\nEOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting \nthe derived eigenvectors (EOFs) as climatic variability patterns. However, due to \nthe inherent orthogonality constraint in EOF analysis, the interpretation of all \nbut the first EOF can be problematic. Rotated EOF analysis, using optimization criteria \nlike Varimax and Promax, offers a solution by releasing this orthogonality constraint, \nthus enabling a more accurate interpretation of variability patterns.\n\nBoth Varimax (orthogonal) and Promax (oblique) rotations result in \"sparse\" solutions, \nmeaning the EOFs become more interpretable by limiting the number of variables that \ncontribute to each EOF. This rotation effectively serves as a regularization method \nfor the EOF solution, with the strength of regularization determined by the power parameter; \nthe higher the value, the sparser the EOFs.\n\nPromax rotation, with a small regularization value (i.e., power=1), reverts to Varimax \nrotation. In this context, we compare the first three modes of EOF analysis: (1) \nwithout regularization, (2) with Varimax rotation, and (3) with Promax rotation.\n\nWe'll start by loading the necessary packages and data:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import xarray as xr\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import Robinson, PlateCarree\n\nfrom xeofs.models import EOF, EOFRotator\n\n\nsns.set_context(\"paper\")\n\nsst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform the actual analysis\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "components = []\nscores = []\n# (1) Standard EOF without regularization\nmodel = EOF(n_modes=100, standardize=True, use_coslat=True)\nmodel.fit(sst, dim=\"time\")\ncomponents.append(model.components())\nscores.append(model.scores())\n# (2) Varimax-rotated EOF analysis\nrot_var = EOFRotator(n_modes=50, power=1)\nrot_var.fit(model)\ncomponents.append(rot_var.components())\nscores.append(rot_var.scores())\n# (3) Promax-rotated EOF analysis\nrot_pro = EOFRotator(n_modes=50, power=4)\nrot_pro.fit(model)\ncomponents.append(rot_pro.components())\nscores.append(rot_pro.scores())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create figure showing the first 6 modes for all 3 cases. While the first mode\nis very similar in all three cases the subsequent modes of the standard\nsolution exhibit dipole and tripole-like patterns. Under Varimax and Promax\nrotation, these structures completely disappear suggesting that these patterns\nwere mere artifacts due to the orthogonality.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "proj = Robinson(central_longitude=180)\nkwargs = {\n \"cmap\": \"RdBu\",\n \"transform\": PlateCarree(),\n \"vmin\": -0.03,\n \"vmax\": +0.03,\n \"add_colorbar\": False,\n}\n\nfig = plt.figure(figsize=(10, 5))\ngs = GridSpec(3, 4)\nax_std = [fig.add_subplot(gs[0, i], projection=proj) for i in range(4)]\nax_var = [fig.add_subplot(gs[1, i], projection=proj) for i in range(4)]\nax_pro = [fig.add_subplot(gs[2, i], projection=proj) for i in range(4)]\n\nfor i, (a0, a1, a2) in enumerate(zip(ax_std, ax_var, ax_pro)):\n mode = i + 1\n a0.coastlines(color=\".5\")\n a1.coastlines(color=\".5\")\n a2.coastlines(color=\".5\")\n components[0].sel(mode=mode).plot(ax=a0, **kwargs)\n components[1].sel(mode=mode).plot(ax=a1, **kwargs)\n components[2].sel(mode=mode).plot(ax=a2, **kwargs)\n\ntitle_kwargs = dict(rotation=90, va=\"center\", weight=\"bold\")\nax_std[0].text(-0.1, 0.5, \"Standard\", transform=ax_std[0].transAxes, **title_kwargs)\nax_var[0].text(-0.1, 0.5, \"Varimax\", transform=ax_var[0].transAxes, **title_kwargs)\nax_pro[0].text(-0.1, 0.5, \"Promax\", transform=ax_pro[0].transAxes, **title_kwargs)\n\nplt.tight_layout()\nplt.savefig(\"rotated_eof.jpg\", dpi=200)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Rotated EOF analysis\n", + "\n", + "EOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting\n", + "the derived eigenvectors (EOFs) as climatic variability patterns. However, due to\n", + "the inherent orthogonality constraint in EOF analysis, the interpretation of all\n", + "but the first EOF can be problematic. Rotated EOF analysis, using optimization criteria\n", + "like Varimax and Promax, offers a solution by releasing this orthogonality constraint,\n", + "thus enabling a more accurate interpretation of variability patterns.\n", + "\n", + "Both Varimax (orthogonal) and Promax (oblique) rotations result in \"sparse\" solutions,\n", + "meaning the EOFs become more interpretable by limiting the number of variables that\n", + "contribute to each EOF. This rotation effectively serves as a regularization method\n", + "for the EOF solution, with the strength of regularization determined by the power parameter;\n", + "the higher the value, the sparser the EOFs.\n", + "\n", + "Promax rotation, with a small regularization value (i.e., power=1), reverts to Varimax\n", + "rotation. In this context, we compare the first three modes of EOF analysis: (1)\n", + "without regularization, (2) with Varimax rotation, and (3) with Promax rotation.\n", + "\n", + "We'll start by loading the necessary packages and data:\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import Robinson, PlateCarree\n", + "\n", + "from xeofs.models import EOF, EOFRotator\n", + "\n", + "\n", + "sns.set_context(\"paper\")\n", + "\n", + "sst = xr.tutorial.open_dataset(\"ersstv5\")[\"sst\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform the actual analysis\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "components = []\n", + "scores = []\n", + "# (1) Standard EOF without regularization\n", + "model = EOF(n_modes=100, standardize=True, use_coslat=True)\n", + "model.fit(sst, dim=\"time\")\n", + "components.append(model.components())\n", + "scores.append(model.scores())\n", + "# (2) Varimax-rotated EOF analysis\n", + "rot_var = EOFRotator(n_modes=50, power=1)\n", + "rot_var.fit(model)\n", + "components.append(rot_var.components())\n", + "scores.append(rot_var.scores())\n", + "# (3) Promax-rotated EOF analysis\n", + "rot_pro = EOFRotator(n_modes=50, power=4)\n", + "rot_pro.fit(model)\n", + "components.append(rot_pro.components())\n", + "scores.append(rot_pro.scores())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create figure showing the first 6 modes for all 3 cases. While the first mode\n", + "is very similar in all three cases the subsequent modes of the standard\n", + "solution exhibit dipole and tripole-like patterns. Under Varimax and Promax\n", + "rotation, these structures completely disappear suggesting that these patterns\n", + "were mere artifacts due to the orthogonality.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "proj = Robinson(central_longitude=180)\n", + "kwargs = {\n", + " \"cmap\": \"RdBu\",\n", + " \"transform\": PlateCarree(),\n", + " \"vmin\": -0.03,\n", + " \"vmax\": +0.03,\n", + " \"add_colorbar\": False,\n", + "}\n", + "\n", + "fig = plt.figure(figsize=(10, 5))\n", + "gs = GridSpec(3, 4)\n", + "ax_std = [fig.add_subplot(gs[0, i], projection=proj) for i in range(4)]\n", + "ax_var = [fig.add_subplot(gs[1, i], projection=proj) for i in range(4)]\n", + "ax_pro = [fig.add_subplot(gs[2, i], projection=proj) for i in range(4)]\n", + "\n", + "for i, (a0, a1, a2) in enumerate(zip(ax_std, ax_var, ax_pro)):\n", + " mode = i + 1\n", + " a0.coastlines(color=\".5\")\n", + " a1.coastlines(color=\".5\")\n", + " a2.coastlines(color=\".5\")\n", + " components[0].sel(mode=mode).plot(ax=a0, **kwargs)\n", + " components[1].sel(mode=mode).plot(ax=a1, **kwargs)\n", + " components[2].sel(mode=mode).plot(ax=a2, **kwargs)\n", + "\n", + "title_kwargs = dict(rotation=90, va=\"center\", weight=\"bold\")\n", + "ax_std[0].text(-0.1, 0.5, \"Standard\", transform=ax_std[0].transAxes, **title_kwargs)\n", + "ax_var[0].text(-0.1, 0.5, \"Varimax\", transform=ax_var[0].transAxes, **title_kwargs)\n", + "ax_pro[0].text(-0.1, 0.5, \"Promax\", transform=ax_pro[0].transAxes, **title_kwargs)\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"rotated_eof.jpg\", dpi=200)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_rotated_eof.py b/docs/auto_examples/1single/plot_rotated_eof.py index f28a2446..0f8b296b 100644 --- a/docs/auto_examples/1single/plot_rotated_eof.py +++ b/docs/auto_examples/1single/plot_rotated_eof.py @@ -2,25 +2,26 @@ Rotated EOF analysis ======================== -EOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting -the derived eigenvectors (EOFs) as climatic variability patterns. However, due to -the inherent orthogonality constraint in EOF analysis, the interpretation of all -but the first EOF can be problematic. Rotated EOF analysis, using optimization criteria -like Varimax and Promax, offers a solution by releasing this orthogonality constraint, +EOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting +the derived eigenvectors (EOFs) as climatic variability patterns. However, due to +the inherent orthogonality constraint in EOF analysis, the interpretation of all +but the first EOF can be problematic. Rotated EOF analysis, using optimization criteria +like Varimax and Promax, offers a solution by releasing this orthogonality constraint, thus enabling a more accurate interpretation of variability patterns. -Both Varimax (orthogonal) and Promax (oblique) rotations result in "sparse" solutions, -meaning the EOFs become more interpretable by limiting the number of variables that -contribute to each EOF. This rotation effectively serves as a regularization method -for the EOF solution, with the strength of regularization determined by the power parameter; +Both Varimax (orthogonal) and Promax (oblique) rotations result in "sparse" solutions, +meaning the EOFs become more interpretable by limiting the number of variables that +contribute to each EOF. This rotation effectively serves as a regularization method +for the EOF solution, with the strength of regularization determined by the power parameter; the higher the value, the sparser the EOFs. -Promax rotation, with a small regularization value (i.e., power=1), reverts to Varimax -rotation. In this context, we compare the first three modes of EOF analysis: (1) +Promax rotation, with a small regularization value (i.e., power=1), reverts to Varimax +rotation. In this context, we compare the first three modes of EOF analysis: (1) without regularization, (2) with Varimax rotation, and (3) with Promax rotation. We'll start by loading the necessary packages and data: """ + import xarray as xr import matplotlib.pyplot as plt import seaborn as sns diff --git a/docs/auto_examples/1single/plot_rotated_eof.py.md5 b/docs/auto_examples/1single/plot_rotated_eof.py.md5 index aec50bde..46e91846 100644 --- a/docs/auto_examples/1single/plot_rotated_eof.py.md5 +++ b/docs/auto_examples/1single/plot_rotated_eof.py.md5 @@ -1 +1 @@ -7d3990fe91608b6585b1085c1a8a323f \ No newline at end of file +88116a4a1f79c81f89706b7345a6ba70 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_rotated_eof.rst b/docs/auto_examples/1single/plot_rotated_eof.rst index e7f3fd33..410b573f 100644 --- a/docs/auto_examples/1single/plot_rotated_eof.rst +++ b/docs/auto_examples/1single/plot_rotated_eof.rst @@ -21,28 +21,29 @@ Rotated EOF analysis ======================== -EOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting -the derived eigenvectors (EOFs) as climatic variability patterns. However, due to -the inherent orthogonality constraint in EOF analysis, the interpretation of all -but the first EOF can be problematic. Rotated EOF analysis, using optimization criteria -like Varimax and Promax, offers a solution by releasing this orthogonality constraint, +EOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting +the derived eigenvectors (EOFs) as climatic variability patterns. However, due to +the inherent orthogonality constraint in EOF analysis, the interpretation of all +but the first EOF can be problematic. Rotated EOF analysis, using optimization criteria +like Varimax and Promax, offers a solution by releasing this orthogonality constraint, thus enabling a more accurate interpretation of variability patterns. -Both Varimax (orthogonal) and Promax (oblique) rotations result in "sparse" solutions, -meaning the EOFs become more interpretable by limiting the number of variables that -contribute to each EOF. This rotation effectively serves as a regularization method -for the EOF solution, with the strength of regularization determined by the power parameter; +Both Varimax (orthogonal) and Promax (oblique) rotations result in "sparse" solutions, +meaning the EOFs become more interpretable by limiting the number of variables that +contribute to each EOF. This rotation effectively serves as a regularization method +for the EOF solution, with the strength of regularization determined by the power parameter; the higher the value, the sparser the EOFs. -Promax rotation, with a small regularization value (i.e., power=1), reverts to Varimax -rotation. In this context, we compare the first three modes of EOF analysis: (1) +Promax rotation, with a small regularization value (i.e., power=1), reverts to Varimax +rotation. In this context, we compare the first three modes of EOF analysis: (1) without regularization, (2) with Varimax rotation, and (3) with Promax rotation. We'll start by loading the necessary packages and data: -.. GENERATED FROM PYTHON SOURCE LINES 24-38 +.. GENERATED FROM PYTHON SOURCE LINES 24-39 + +.. code-block:: Python -.. code-block:: default import xarray as xr import matplotlib.pyplot as plt @@ -65,13 +66,13 @@ We'll start by loading the necessary packages and data: -.. GENERATED FROM PYTHON SOURCE LINES 39-40 +.. GENERATED FROM PYTHON SOURCE LINES 40-41 Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 40-60 +.. GENERATED FROM PYTHON SOURCE LINES 41-61 -.. code-block:: default +.. code-block:: Python components = [] @@ -97,10 +98,17 @@ Perform the actual analysis +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + /home/slevang/miniconda3/envs/xeofs-docs/lib/python3.11/site-packages/numpy/lib/nanfunctions.py:1879: RuntimeWarning: Degrees of freedom <= 0 for slice. + var = nanvar(a, axis=axis, dtype=dtype, out=out, ddof=ddof, -.. GENERATED FROM PYTHON SOURCE LINES 61-66 + +.. GENERATED FROM PYTHON SOURCE LINES 62-67 Create figure showing the first 6 modes for all 3 cases. While the first mode is very similar in all three cases the subsequent modes of the standard @@ -108,9 +116,9 @@ solution exhibit dipole and tripole-like patterns. Under Varimax and Promax rotation, these structures completely disappear suggesting that these patterns were mere artifacts due to the orthogonality. -.. GENERATED FROM PYTHON SOURCE LINES 66-98 +.. GENERATED FROM PYTHON SOURCE LINES 67-99 -.. code-block:: default +.. code-block:: Python proj = Robinson(central_longitude=180) @@ -159,7 +167,7 @@ were mere artifacts due to the orthogonality. .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 18.587 seconds) + **Total running time of the script:** (0 minutes 6.472 seconds) .. _sphx_glr_download_auto_examples_1single_plot_rotated_eof.py: @@ -168,17 +176,14 @@ were mere artifacts due to the orthogonality. .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_rotated_eof.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_rotated_eof.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_rotated_eof.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_rotated_eof_codeobj.pickle b/docs/auto_examples/1single/plot_rotated_eof_codeobj.pickle index 5d2d3b73..63217752 100644 Binary files a/docs/auto_examples/1single/plot_rotated_eof_codeobj.pickle and b/docs/auto_examples/1single/plot_rotated_eof_codeobj.pickle differ diff --git a/docs/auto_examples/1single/plot_weighted-eof.ipynb b/docs/auto_examples/1single/plot_weighted-eof.ipynb index e44e53a3..d9aef5e2 100644 --- a/docs/auto_examples/1single/plot_weighted-eof.ipynb +++ b/docs/auto_examples/1single/plot_weighted-eof.ipynb @@ -1,79 +1,147 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Weighted EOF analysis\n\nWeighted EOF analysis (in S-mode) maximises the temporal variance\nconsidering each gridpoint with a different weight. We compare the\nresults for an EOF analysis based on (1) the covariance matrix, (2) area\nweighting based on latitude (coslat weighting), (3) the correlation matrix\nand finally (4) correlation matrix + coslat weighting.\n\nLoad packages and data:\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import xarray as xr\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import Orthographic, PlateCarree\n\nfrom xeofs.models import EOF\n\nsns.set_context(\"paper\")\n\nt2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform the actual analysis\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "components = []\nscores = []\n# (1) Based on covariance matrix\nmodel_cov = EOF(n_modes=5, standardize=False, use_coslat=False)\nmodel_cov.fit(t2m, \"time\")\ncomponents.append(model_cov.components())\nscores.append(model_cov.scores())\n# (2) Based on coslat weighted covariance matrix\nmodel_lat = EOF(n_modes=5, standardize=False, use_coslat=True)\nmodel_lat.fit(t2m, \"time\")\ncomponents.append(model_lat.components())\nscores.append(model_lat.scores())\n# (3) Based on correlation matrix\nmodel_cor = EOF(n_modes=5, standardize=True, use_coslat=False)\nmodel_cor.fit(t2m, \"time\")\ncomponents.append(model_cor.components())\nscores.append(model_cor.scores())\n# (4) Based on coslat weighted correlation matrix\nmodel_cor_lat = EOF(n_modes=5, standardize=True, use_coslat=True)\nmodel_cor_lat.fit(t2m, \"time\")\ncomponents.append(model_cor_lat.components())\nscores.append(model_cor_lat.scores())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create figure showing the first mode for all 4 cases\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "proj = Orthographic(central_latitude=30, central_longitude=-80)\nkwargs = {\n \"cmap\": \"mako\",\n \"transform\": PlateCarree(),\n \"vmin\": 0,\n}\ntitles = [\n \"(1) Covariances\",\n \"(2) Covariances + coslat\",\n \"(3) Correlation\",\n \"(4) Correlation + coslat\",\n]\nfig = plt.figure(figsize=(10, 12))\ngs = GridSpec(4, 2)\nax_pcs = [fig.add_subplot(gs[i, 0]) for i in range(4)]\nax_eofs = [fig.add_subplot(gs[i, 1], projection=proj) for i in range(4)]\n\nfor i, (a1, a2) in enumerate(zip(ax_eofs, ax_pcs)):\n a1.coastlines(color=\".5\")\n components[i].sel(mode=1).plot(ax=a1, **kwargs)\n scores[i].sel(mode=1).plot(ax=a2, color=\"darkred\")\n a2.set_xlabel(\"\")\n a1.set_title(\"\", loc=\"center\")\n a2.set_title(\"\", loc=\"center\")\n a2.set_title(titles[i], loc=\"left\", weight=\"bold\")\n if i < 3:\n a2.set_xticks([])\n sns.despine(ax=a2, trim=True, bottom=True)\n else:\n sns.despine(ax=a2, trim=True, bottom=False)\n\nplt.tight_layout()\nplt.savefig(\"weighted_eof.jpg\", dpi=200)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Weighted EOF analysis\n", + "\n", + "Weighted EOF analysis (in S-mode) maximises the temporal variance\n", + "considering each gridpoint with a different weight. We compare the\n", + "results for an EOF analysis based on (1) the covariance matrix, (2) area\n", + "weighting based on latitude (coslat weighting), (3) the correlation matrix\n", + "and finally (4) correlation matrix + coslat weighting.\n", + "\n", + "Load packages and data:\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import Orthographic, PlateCarree\n", + "\n", + "from xeofs.models import EOF\n", + "\n", + "sns.set_context(\"paper\")\n", + "\n", + "t2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform the actual analysis\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "components = []\n", + "scores = []\n", + "# (1) Based on covariance matrix\n", + "model_cov = EOF(n_modes=5, standardize=False, use_coslat=False)\n", + "model_cov.fit(t2m, \"time\")\n", + "components.append(model_cov.components())\n", + "scores.append(model_cov.scores())\n", + "# (2) Based on coslat weighted covariance matrix\n", + "model_lat = EOF(n_modes=5, standardize=False, use_coslat=True)\n", + "model_lat.fit(t2m, \"time\")\n", + "components.append(model_lat.components())\n", + "scores.append(model_lat.scores())\n", + "# (3) Based on correlation matrix\n", + "model_cor = EOF(n_modes=5, standardize=True, use_coslat=False)\n", + "model_cor.fit(t2m, \"time\")\n", + "components.append(model_cor.components())\n", + "scores.append(model_cor.scores())\n", + "# (4) Based on coslat weighted correlation matrix\n", + "model_cor_lat = EOF(n_modes=5, standardize=True, use_coslat=True)\n", + "model_cor_lat.fit(t2m, \"time\")\n", + "components.append(model_cor_lat.components())\n", + "scores.append(model_cor_lat.scores())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create figure showing the first mode for all 4 cases\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "proj = Orthographic(central_latitude=30, central_longitude=-80)\n", + "kwargs = {\n", + " \"cmap\": \"mako\",\n", + " \"transform\": PlateCarree(),\n", + " \"vmin\": 0,\n", + "}\n", + "titles = [\n", + " \"(1) Covariances\",\n", + " \"(2) Covariances + coslat\",\n", + " \"(3) Correlation\",\n", + " \"(4) Correlation + coslat\",\n", + "]\n", + "fig = plt.figure(figsize=(10, 12))\n", + "gs = GridSpec(4, 2)\n", + "ax_pcs = [fig.add_subplot(gs[i, 0]) for i in range(4)]\n", + "ax_eofs = [fig.add_subplot(gs[i, 1], projection=proj) for i in range(4)]\n", + "\n", + "for i, (a1, a2) in enumerate(zip(ax_eofs, ax_pcs)):\n", + " a1.coastlines(color=\".5\")\n", + " components[i].sel(mode=1).plot(ax=a1, **kwargs)\n", + " scores[i].sel(mode=1).plot(ax=a2, color=\"darkred\")\n", + " a2.set_xlabel(\"\")\n", + " a1.set_title(\"\", loc=\"center\")\n", + " a2.set_title(\"\", loc=\"center\")\n", + " a2.set_title(titles[i], loc=\"left\", weight=\"bold\")\n", + " if i < 3:\n", + " a2.set_xticks([], [])\n", + " sns.despine(ax=a2, trim=True, bottom=True)\n", + " else:\n", + " sns.despine(ax=a2, trim=True, bottom=False)\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"weighted_eof.jpg\", dpi=200)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/1single/plot_weighted-eof.py b/docs/auto_examples/1single/plot_weighted-eof.py index 23721267..26a88473 100644 --- a/docs/auto_examples/1single/plot_weighted-eof.py +++ b/docs/auto_examples/1single/plot_weighted-eof.py @@ -10,6 +10,7 @@ Load packages and data: """ + import xarray as xr import matplotlib.pyplot as plt import seaborn as sns @@ -78,7 +79,7 @@ a2.set_title("", loc="center") a2.set_title(titles[i], loc="left", weight="bold") if i < 3: - a2.set_xticks([]) + a2.set_xticks([], []) sns.despine(ax=a2, trim=True, bottom=True) else: sns.despine(ax=a2, trim=True, bottom=False) diff --git a/docs/auto_examples/1single/plot_weighted-eof.py.md5 b/docs/auto_examples/1single/plot_weighted-eof.py.md5 index bd701fd2..b015a5cf 100644 --- a/docs/auto_examples/1single/plot_weighted-eof.py.md5 +++ b/docs/auto_examples/1single/plot_weighted-eof.py.md5 @@ -1 +1 @@ -0ecd8e72b1a6232f732dd5a1e50706ad \ No newline at end of file +8ca089ebc9dfca92e49dbd81d4047695 \ No newline at end of file diff --git a/docs/auto_examples/1single/plot_weighted-eof.rst b/docs/auto_examples/1single/plot_weighted-eof.rst index 894d0dc6..90769f45 100644 --- a/docs/auto_examples/1single/plot_weighted-eof.rst +++ b/docs/auto_examples/1single/plot_weighted-eof.rst @@ -29,9 +29,10 @@ and finally (4) correlation matrix + coslat weighting. Load packages and data: -.. GENERATED FROM PYTHON SOURCE LINES 13-25 +.. GENERATED FROM PYTHON SOURCE LINES 13-26 + +.. code-block:: Python -.. code-block:: default import xarray as xr import matplotlib.pyplot as plt @@ -52,13 +53,13 @@ Load packages and data: -.. GENERATED FROM PYTHON SOURCE LINES 26-27 +.. GENERATED FROM PYTHON SOURCE LINES 27-28 Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 27-52 +.. GENERATED FROM PYTHON SOURCE LINES 28-53 -.. code-block:: default +.. code-block:: Python components = [] @@ -92,13 +93,13 @@ Perform the actual analysis -.. GENERATED FROM PYTHON SOURCE LINES 53-54 +.. GENERATED FROM PYTHON SOURCE LINES 54-55 Create figure showing the first mode for all 4 cases -.. GENERATED FROM PYTHON SOURCE LINES 54-88 +.. GENERATED FROM PYTHON SOURCE LINES 55-89 -.. code-block:: default +.. code-block:: Python proj = Orthographic(central_latitude=30, central_longitude=-80) @@ -127,7 +128,7 @@ Create figure showing the first mode for all 4 cases a2.set_title("", loc="center") a2.set_title(titles[i], loc="left", weight="bold") if i < 3: - a2.set_xticks([]) + a2.set_xticks([], []) sns.despine(ax=a2, trim=True, bottom=True) else: sns.despine(ax=a2, trim=True, bottom=False) @@ -149,7 +150,7 @@ Create figure showing the first mode for all 4 cases .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 5.606 seconds) + **Total running time of the script:** (0 minutes 1.928 seconds) .. _sphx_glr_download_auto_examples_1single_plot_weighted-eof.py: @@ -158,17 +159,14 @@ Create figure showing the first mode for all 4 cases .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_weighted-eof.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_weighted-eof.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_weighted-eof.ipynb ` - .. only:: html diff --git a/docs/auto_examples/1single/plot_weighted-eof_codeobj.pickle b/docs/auto_examples/1single/plot_weighted-eof_codeobj.pickle index a937230f..be19075a 100644 Binary files a/docs/auto_examples/1single/plot_weighted-eof_codeobj.pickle and b/docs/auto_examples/1single/plot_weighted-eof_codeobj.pickle differ diff --git a/docs/auto_examples/1single/sg_execution_times.rst b/docs/auto_examples/1single/sg_execution_times.rst index b53b496b..757bb304 100644 --- a/docs/auto_examples/1single/sg_execution_times.rst +++ b/docs/auto_examples/1single/sg_execution_times.rst @@ -6,26 +6,59 @@ Computation times ================= -**00:28.072** total execution time for **auto_examples_1single** files: - -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_eeof_trend.py` (``plot_eeof_trend.py``) | 00:28.072 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_complex_eof.py` (``plot_complex_eof.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_eeof.py` (``plot_eeof.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_eof-smode.py` (``plot_eof-smode.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_eof-tmode.py` (``plot_eof-tmode.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_gwpca.py` (``plot_gwpca.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_mreof.py` (``plot_mreof.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_multivariate-eof.py` (``plot_multivariate-eof.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_rotated_eof.py` (``plot_rotated_eof.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_1single_plot_weighted-eof.py` (``plot_weighted-eof.py``) | 00:00.000 | 0.0 MB | -+-----------------------------------------------------------------------------------------------+-----------+--------+ +**00:39.458** total execution time for 10 files **from auto_examples/1single**: + +.. container:: + + .. raw:: html + + + + + + + + .. list-table:: + :header-rows: 1 + :class: table table-striped sg-datatable + + * - Example + - Time + - Mem (MB) + * - :ref:`sphx_glr_auto_examples_1single_plot_gwpca.py` (``plot_gwpca.py``) + - 00:34.593 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_weighted-eof.py` (``plot_weighted-eof.py``) + - 00:01.928 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_mreof.py` (``plot_mreof.py``) + - 00:01.727 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_multivariate-eof.py` (``plot_multivariate-eof.py``) + - 00:01.211 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_complex_eof.py` (``plot_complex_eof.py``) + - 00:00.000 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_eeof.py` (``plot_eeof.py``) + - 00:00.000 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_eeof_trend.py` (``plot_eeof_trend.py``) + - 00:00.000 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_eof-smode.py` (``plot_eof-smode.py``) + - 00:00.000 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_eof-tmode.py` (``plot_eof-tmode.py``) + - 00:00.000 + - 0.0 + * - :ref:`sphx_glr_auto_examples_1single_plot_rotated_eof.py` (``plot_rotated_eof.py``) + - 00:00.000 + - 0.0 diff --git a/docs/auto_examples/2multi/images/sphx_glr_plot_cca_001.png b/docs/auto_examples/2multi/images/sphx_glr_plot_cca_001.png index 36047fff..5a4c2a6e 100644 Binary files a/docs/auto_examples/2multi/images/sphx_glr_plot_cca_001.png and b/docs/auto_examples/2multi/images/sphx_glr_plot_cca_001.png differ diff --git a/docs/auto_examples/2multi/images/sphx_glr_plot_cca_002.png b/docs/auto_examples/2multi/images/sphx_glr_plot_cca_002.png index 09cad2a5..a02a021f 100644 Binary files a/docs/auto_examples/2multi/images/sphx_glr_plot_cca_002.png and b/docs/auto_examples/2multi/images/sphx_glr_plot_cca_002.png differ diff --git a/docs/auto_examples/2multi/images/sphx_glr_plot_mca_001.png b/docs/auto_examples/2multi/images/sphx_glr_plot_mca_001.png index bb527a08..1755ad7c 100644 Binary files a/docs/auto_examples/2multi/images/sphx_glr_plot_mca_001.png and b/docs/auto_examples/2multi/images/sphx_glr_plot_mca_001.png differ diff --git a/docs/auto_examples/2multi/images/sphx_glr_plot_rotated_mca_001.png b/docs/auto_examples/2multi/images/sphx_glr_plot_rotated_mca_001.png index 66635d58..de211f10 100644 Binary files a/docs/auto_examples/2multi/images/sphx_glr_plot_rotated_mca_001.png and b/docs/auto_examples/2multi/images/sphx_glr_plot_rotated_mca_001.png differ diff --git a/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_cca_thumb.png b/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_cca_thumb.png index 8266068a..9c16f7d5 100644 Binary files a/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_cca_thumb.png and b/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_cca_thumb.png differ diff --git a/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_mca_thumb.png b/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_mca_thumb.png index 937da7e1..b4771316 100644 Binary files a/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_mca_thumb.png and b/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_mca_thumb.png differ diff --git a/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_rotated_mca_thumb.png b/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_rotated_mca_thumb.png index 156939c0..292b6200 100644 Binary files a/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_rotated_mca_thumb.png and b/docs/auto_examples/2multi/images/thumb/sphx_glr_plot_rotated_mca_thumb.png differ diff --git a/docs/auto_examples/2multi/index.rst b/docs/auto_examples/2multi/index.rst index ea2b7228..bd745d1e 100644 --- a/docs/auto_examples/2multi/index.rst +++ b/docs/auto_examples/2multi/index.rst @@ -14,7 +14,7 @@ .. raw:: html -
    +
    .. only:: html diff --git a/docs/auto_examples/2multi/plot_cca.ipynb b/docs/auto_examples/2multi/plot_cca.ipynb index 056f191b..be266233 100644 --- a/docs/auto_examples/2multi/plot_cca.ipynb +++ b/docs/auto_examples/2multi/plot_cca.ipynb @@ -1,133 +1,197 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Canonical Correlation Analysis\n\nIn this example, we're going to perform a Canonical Correlation Analysis (CCA) \non three datasets using the ERSSTv5 monthly sea surface temperature (SST) data \nfrom 1970 to 2022. We divide this data into three areas: the Indian Ocean, \nthe Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these \nregions.\n\nFirst, we'll import the necessary modules.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import xarray as xr\nimport xeofs as xe\n\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nimport cartopy.crs as ccrs" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we load the data and compute the SST anomalies. This removes the\nmonthly climatologies, so the seasonal cycle doesn't impact our CCA.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "sst = xr.tutorial.load_dataset(\"ersstv5\").sst\nsst = sst.groupby(\"time.month\") - sst.groupby(\"time.month\").mean(\"time\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we define the three regions of interest and store them in a list.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "indian = sst.sel(lon=slice(35, 115), lat=slice(30, -30))\npacific = sst.sel(lon=slice(130, 290), lat=slice(30, -30))\natlantic = sst.sel(lon=slice(320, 360), lat=slice(70, 10))\n\ndata_list = [indian, pacific, atlantic]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now perform CCA. Since we are dealing with a high-dimensional feature space, we first\nperform PCA to reduce the dimensionality (this is kind of a regularized CCA) by setting\n``pca=True``. By setting the ``variance_fraction`` keyword argument, we specify that we\nwant to keep the number of PCA modes that explain 90% of the variance in each of the\nthree data sets.\n\nAn important parameter is ``init_pca_modes``. It specifies the number\nof PCA modes that are initially compute before truncating them to account for 90 %. If this\nnumber is small enough, randomized PCAs will be performed instead of the full SVD decomposition\nwhich is much faster. We can also specify ``init_pca_modes`` as a float (0 < x <= 1),\nin which case the number of PCA modes is given by the fraction of the data matrix's rank\nThe default is set to 0.75 which will ensure that randomized PCAs are performed.\n\nGiven the nature of SST data, we might lower it to something like 0.3, since\nwe expect that most of the variance in the data will be explained by a small\nnumber of PC modes.\n\nNote that if our initial PCA modes don't hit the 90% variance target, ``xeofs``\nwill give a warning.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model = xe.models.CCA(\n n_modes=2,\n use_coslat=True,\n pca=True,\n variance_fraction=0.9,\n init_pca_modes=0.30,\n)\nmodel.fit(data_list, dim=\"time\")\ncomponents = model.components()\nscores = model.scores()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's look at the canonical loadings (components) of the first mode.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "mode = 1\n\ncentral_longitudes = [\n indian.lon.median().item(),\n pacific.lon.median().item(),\n pacific.lon.median().item(),\n]\nprojections = [ccrs.PlateCarree(central_longitude=lon) for lon in central_longitudes]\n\nfig = plt.figure(figsize=(12, 2.5))\ngs = GridSpec(1, 4, figure=fig, width_ratios=[2, 4, 1, 0.2])\naxes = [fig.add_subplot(gs[0, i], projection=projections[i]) for i in range(3)]\ncax = fig.add_subplot(1, 4, 4)\nkwargs = dict(transform=ccrs.PlateCarree(), vmin=-1, vmax=1, cmap=\"RdBu_r\", cbar_ax=cax)\ncomponents[0].sel(mode=mode).plot(ax=axes[0], **kwargs)\ncomponents[1].sel(mode=mode).plot(ax=axes[1], **kwargs)\nim = components[2].sel(mode=mode).plot(ax=axes[2], **kwargs)\nfig.colorbar(im, cax=cax, orientation=\"vertical\")\nfor ax in axes:\n ax.coastlines()\n ax.set_title(\"\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And lastly, we'll check out the canonical variates (scores) of the first mode.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "fig, ax = plt.subplots(figsize=(12, 4))\nscores[0].sel(mode=mode).plot(ax=ax, label=\"Indian Ocean\")\nscores[1].sel(mode=mode).plot(ax=ax, label=\"Central Pacific\")\nscores[2].sel(mode=mode).plot(ax=ax, label=\"North Atlantic\")\nax.legend()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Canonical Correlation Analysis\n", + "\n", + "In this example, we're going to perform a Canonical Correlation Analysis (CCA)\n", + "on three datasets using the ERSSTv5 monthly sea surface temperature (SST) data\n", + "from 1970 to 2022. We divide this data into three areas: the Indian Ocean,\n", + "the Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these\n", + "regions.\n", + "\n", + "First, we'll import the necessary modules.\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "import xeofs as xe\n", + "\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "import cartopy.crs as ccrs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we load the data and compute the SST anomalies. This removes the\n", + "monthly climatologies, so the seasonal cycle doesn't impact our CCA.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sst = xr.tutorial.load_dataset(\"ersstv5\").sst\n", + "sst = sst.groupby(\"time.month\") - sst.groupby(\"time.month\").mean(\"time\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we define the three regions of interest and store them in a list.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "indian = sst.sel(lon=slice(35, 115), lat=slice(30, -30))\n", + "pacific = sst.sel(lon=slice(130, 290), lat=slice(30, -30))\n", + "atlantic = sst.sel(lon=slice(320, 360), lat=slice(70, 10))\n", + "\n", + "data_list = [indian, pacific, atlantic]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now perform CCA. Since we are dealing with a high-dimensional feature space, we first\n", + "perform PCA to reduce the dimensionality (this is kind of a regularized CCA) by setting\n", + "``pca=True``. By setting the ``variance_fraction`` keyword argument, we specify that we\n", + "want to keep the number of PCA modes that explain 90% of the variance in each of the\n", + "three data sets.\n", + "\n", + "An important parameter is ``init_pca_modes``. It specifies the number\n", + "of PCA modes that are initially compute before truncating them to account for 90 %. If this\n", + "number is small enough, randomized PCAs will be performed instead of the full SVD decomposition\n", + "which is much faster. We can also specify ``init_pca_modes`` as a float (0 < x <= 1),\n", + "in which case the number of PCA modes is given by the fraction of the data matrix's rank\n", + "The default is set to 0.75 which will ensure that randomized PCAs are performed.\n", + "\n", + "Given the nature of SST data, we might lower it to something like 0.3, since\n", + "we expect that most of the variance in the data will be explained by a small\n", + "number of PC modes.\n", + "\n", + "Note that if our initial PCA modes don't hit the 90% variance target, ``xeofs``\n", + "will give a warning.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = xe.models.CCA(\n", + " n_modes=2,\n", + " use_coslat=True,\n", + " pca=True,\n", + " variance_fraction=0.9,\n", + " init_pca_modes=0.30,\n", + ")\n", + "model.fit(data_list, dim=\"time\")\n", + "components = model.components()\n", + "scores = model.scores()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's look at the canonical loadings (components) of the first mode.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mode = 1\n", + "\n", + "central_longitudes = [\n", + " indian.lon.median().item(),\n", + " pacific.lon.median().item(),\n", + " pacific.lon.median().item(),\n", + "]\n", + "projections = [ccrs.PlateCarree(central_longitude=lon) for lon in central_longitudes]\n", + "\n", + "fig = plt.figure(figsize=(12, 2.5))\n", + "gs = GridSpec(1, 4, figure=fig, width_ratios=[2, 4, 1, 0.2])\n", + "axes = [fig.add_subplot(gs[0, i], projection=projections[i]) for i in range(3)]\n", + "cax = fig.add_subplot(1, 4, 4)\n", + "kwargs = dict(transform=ccrs.PlateCarree(), vmin=-1, vmax=1, cmap=\"RdBu_r\", cbar_ax=cax)\n", + "components[0].sel(mode=mode).plot(ax=axes[0], **kwargs)\n", + "components[1].sel(mode=mode).plot(ax=axes[1], **kwargs)\n", + "im = components[2].sel(mode=mode).plot(ax=axes[2], **kwargs)\n", + "fig.colorbar(im, cax=cax, orientation=\"vertical\")\n", + "for ax in axes:\n", + " ax.coastlines()\n", + " ax.set_title(\"\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And lastly, we'll check out the canonical variates (scores) of the first mode.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(12, 4))\n", + "scores[0].sel(mode=mode).plot(ax=ax, label=\"Indian Ocean\")\n", + "scores[1].sel(mode=mode).plot(ax=ax, label=\"Central Pacific\")\n", + "scores[2].sel(mode=mode).plot(ax=ax, label=\"North Atlantic\")\n", + "ax.legend()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/2multi/plot_cca.py b/docs/auto_examples/2multi/plot_cca.py index b84cf0dc..e57af825 100644 --- a/docs/auto_examples/2multi/plot_cca.py +++ b/docs/auto_examples/2multi/plot_cca.py @@ -2,10 +2,10 @@ Canonical Correlation Analysis ============================== -In this example, we're going to perform a Canonical Correlation Analysis (CCA) -on three datasets using the ERSSTv5 monthly sea surface temperature (SST) data -from 1970 to 2022. We divide this data into three areas: the Indian Ocean, -the Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these +In this example, we're going to perform a Canonical Correlation Analysis (CCA) +on three datasets using the ERSSTv5 monthly sea surface temperature (SST) data +from 1970 to 2022. We divide this data into three areas: the Indian Ocean, +the Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these regions. First, we'll import the necessary modules. diff --git a/docs/auto_examples/2multi/plot_cca.py.md5 b/docs/auto_examples/2multi/plot_cca.py.md5 index 009b5fb0..d0fdf998 100644 --- a/docs/auto_examples/2multi/plot_cca.py.md5 +++ b/docs/auto_examples/2multi/plot_cca.py.md5 @@ -1 +1 @@ -ae159e7d6eb88d368d77effb49f30a2e \ No newline at end of file +89f56b4ed3606f9c5a94189c1c497250 \ No newline at end of file diff --git a/docs/auto_examples/2multi/plot_cca.rst b/docs/auto_examples/2multi/plot_cca.rst index 50c078d1..51cbe8dc 100644 --- a/docs/auto_examples/2multi/plot_cca.rst +++ b/docs/auto_examples/2multi/plot_cca.rst @@ -21,17 +21,17 @@ Canonical Correlation Analysis ============================== -In this example, we're going to perform a Canonical Correlation Analysis (CCA) -on three datasets using the ERSSTv5 monthly sea surface temperature (SST) data -from 1970 to 2022. We divide this data into three areas: the Indian Ocean, -the Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these +In this example, we're going to perform a Canonical Correlation Analysis (CCA) +on three datasets using the ERSSTv5 monthly sea surface temperature (SST) data +from 1970 to 2022. We divide this data into three areas: the Indian Ocean, +the Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these regions. First, we'll import the necessary modules. .. GENERATED FROM PYTHON SOURCE LINES 13-21 -.. code-block:: default +.. code-block:: Python import xarray as xr @@ -55,7 +55,7 @@ monthly climatologies, so the seasonal cycle doesn't impact our CCA. .. GENERATED FROM PYTHON SOURCE LINES 24-29 -.. code-block:: default +.. code-block:: Python sst = xr.tutorial.load_dataset("ersstv5").sst @@ -75,7 +75,7 @@ Now, we define the three regions of interest and store them in a list. .. GENERATED FROM PYTHON SOURCE LINES 31-38 -.. code-block:: default +.. code-block:: Python indian = sst.sel(lon=slice(35, 115), lat=slice(30, -30)) @@ -115,7 +115,7 @@ will give a warning. .. GENERATED FROM PYTHON SOURCE LINES 58-70 -.. code-block:: default +.. code-block:: Python model = xe.models.CCA( @@ -142,7 +142,7 @@ Let's look at the canonical loadings (components) of the first mode. .. GENERATED FROM PYTHON SOURCE LINES 72-95 -.. code-block:: default +.. code-block:: Python mode = 1 @@ -185,7 +185,7 @@ And lastly, we'll check out the canonical variates (scores) of the first mode. .. GENERATED FROM PYTHON SOURCE LINES 97-103 -.. code-block:: default +.. code-block:: Python fig, ax = plt.subplots(figsize=(12, 4)) @@ -207,14 +207,14 @@ And lastly, we'll check out the canonical variates (scores) of the first mode. .. code-block:: none - + .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 13.071 seconds) + **Total running time of the script:** (0 minutes 1.632 seconds) .. _sphx_glr_download_auto_examples_2multi_plot_cca.py: @@ -223,17 +223,14 @@ And lastly, we'll check out the canonical variates (scores) of the first mode. .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_cca.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_cca.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_cca.ipynb ` - .. only:: html diff --git a/docs/auto_examples/2multi/plot_cca_codeobj.pickle b/docs/auto_examples/2multi/plot_cca_codeobj.pickle index 7d21e7e9..e9a23cf3 100644 Binary files a/docs/auto_examples/2multi/plot_cca_codeobj.pickle and b/docs/auto_examples/2multi/plot_cca_codeobj.pickle differ diff --git a/docs/auto_examples/2multi/plot_mca.ipynb b/docs/auto_examples/2multi/plot_mca.ipynb index 108ae3c6..0cdfe016 100644 --- a/docs/auto_examples/2multi/plot_mca.ipynb +++ b/docs/auto_examples/2multi/plot_mca.ipynb @@ -1,151 +1,219 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Maximum Covariance Analysis\n\nMaximum Covariance Analysis (MCA) between two data sets.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Load packages and data:\nimport numpy as np\nimport xarray as xr\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import Orthographic, PlateCarree\nfrom cartopy.feature import LAND\n\nfrom xeofs.models import MCA" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create 2 different DataArrays\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "t2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]\nda1 = t2m.isel(lon=slice(0, 26))\nda2 = t2m.isel(lon=slice(27, None))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform MCA\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "mca = MCA(n_modes=20, standardize=False, use_coslat=True)\nmca.fit(da1, da2, dim=\"time\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get singular vectors, projections (PCs), homogeneous and heterogeneous\npatterns:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "singular_vectors = mca.components()\nscores = mca.scores()\nhom_pats, pvals_hom = mca.homogeneous_patterns()\nhet_pats, pvals_het = mca.heterogeneous_patterns()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When two fields are expected, the output of the above methods is a list of\nlength 2, with the first and second entry containing the relevant object for\n``X`` and ``Y``. For example, the p-values obtained from the two-sided t-test\nfor the homogeneous patterns of ``X`` are:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "pvals_hom[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a mask to identifiy where p-values are below 0.05\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "hom_mask = [values < 0.05 for values in pvals_hom]\nhet_mask = [values < 0.05 for values in pvals_het]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Plot some relevant quantities of mode 2.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "lonlats = [\n np.meshgrid(pvals_hom[0].lon.values, pvals_hom[0].lat.values),\n np.meshgrid(pvals_hom[1].lon.values, pvals_hom[1].lat.values),\n]\nproj = [\n Orthographic(central_latitude=30, central_longitude=-120),\n Orthographic(central_latitude=30, central_longitude=-60),\n]\nkwargs1 = {\"cmap\": \"BrBG\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\nkwargs2 = {\"cmap\": \"RdBu\", \"vmin\": -1, \"vmax\": 1, \"transform\": PlateCarree()}\n\nmode = 2\n\nfig = plt.figure(figsize=(7, 14))\ngs = GridSpec(5, 2)\nax1 = [fig.add_subplot(gs[0, i], projection=proj[i]) for i in range(2)]\nax2 = [fig.add_subplot(gs[1, i], projection=proj[i]) for i in range(2)]\nax3 = [fig.add_subplot(gs[2, i], projection=proj[i]) for i in range(2)]\nax4 = [fig.add_subplot(gs[3, i]) for i in range(2)]\n\nfor i, a in enumerate(ax1):\n singular_vectors[i].sel(mode=mode).plot(ax=a, **kwargs1)\n\nfor i, a in enumerate(ax2):\n hom_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n a.scatter(\n lonlats[i][0],\n lonlats[i][1],\n hom_mask[i].sel(mode=mode).values * 0.5,\n color=\"k\",\n alpha=0.5,\n transform=PlateCarree(),\n )\nfor i, a in enumerate(ax3):\n het_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n a.scatter(\n lonlats[i][0],\n lonlats[i][1],\n het_mask[i].sel(mode=mode).values * 0.5,\n color=\"k\",\n alpha=0.5,\n transform=PlateCarree(),\n )\n\nfor i, a in enumerate(ax4):\n scores[i].sel(mode=mode).plot(ax=a)\n a.set_xlabel(\"\")\n\n\nfor a in np.ravel([ax1, ax2, ax3]):\n a.coastlines(color=\".5\")\n a.add_feature(LAND)\n\nplt.tight_layout()\nplt.savefig(\"mca.jpg\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Maximum Covariance Analysis\n", + "\n", + "Maximum Covariance Analysis (MCA) between two data sets.\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load packages and data:\n", + "import numpy as np\n", + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import Orthographic, PlateCarree\n", + "from cartopy.feature import LAND\n", + "\n", + "from xeofs.models import MCA" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create 2 different DataArrays\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]\n", + "da1 = t2m.isel(lon=slice(0, 26))\n", + "da2 = t2m.isel(lon=slice(27, None))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform MCA\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mca = MCA(n_modes=20, standardize=False, use_coslat=True)\n", + "mca.fit(da1, da2, dim=\"time\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get singular vectors, projections (PCs), homogeneous and heterogeneous\n", + "patterns:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "singular_vectors = mca.components()\n", + "scores = mca.scores()\n", + "hom_pats, pvals_hom = mca.homogeneous_patterns()\n", + "het_pats, pvals_het = mca.heterogeneous_patterns()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When two fields are expected, the output of the above methods is a list of\n", + "length 2, with the first and second entry containing the relevant object for\n", + "``X`` and ``Y``. For example, the p-values obtained from the two-sided t-test\n", + "for the homogeneous patterns of ``X`` are:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pvals_hom[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a mask to identifiy where p-values are below 0.05\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hom_mask = [values < 0.05 for values in pvals_hom]\n", + "het_mask = [values < 0.05 for values in pvals_het]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot some relevant quantities of mode 2.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lonlats = [\n", + " np.meshgrid(pvals_hom[0].lon.values, pvals_hom[0].lat.values),\n", + " np.meshgrid(pvals_hom[1].lon.values, pvals_hom[1].lat.values),\n", + "]\n", + "proj = [\n", + " Orthographic(central_latitude=30, central_longitude=-120),\n", + " Orthographic(central_latitude=30, central_longitude=-60),\n", + "]\n", + "kwargs1 = {\"cmap\": \"BrBG\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\n", + "kwargs2 = {\"cmap\": \"RdBu\", \"vmin\": -1, \"vmax\": 1, \"transform\": PlateCarree()}\n", + "\n", + "mode = 2\n", + "\n", + "fig = plt.figure(figsize=(7, 14))\n", + "gs = GridSpec(5, 2)\n", + "ax1 = [fig.add_subplot(gs[0, i], projection=proj[i]) for i in range(2)]\n", + "ax2 = [fig.add_subplot(gs[1, i], projection=proj[i]) for i in range(2)]\n", + "ax3 = [fig.add_subplot(gs[2, i], projection=proj[i]) for i in range(2)]\n", + "ax4 = [fig.add_subplot(gs[3, i]) for i in range(2)]\n", + "\n", + "for i, a in enumerate(ax1):\n", + " singular_vectors[i].sel(mode=mode).plot(ax=a, **kwargs1)\n", + "\n", + "for i, a in enumerate(ax2):\n", + " hom_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n", + " a.scatter(\n", + " lonlats[i][0],\n", + " lonlats[i][1],\n", + " hom_mask[i].sel(mode=mode).values * 0.5,\n", + " color=\"k\",\n", + " alpha=0.5,\n", + " transform=PlateCarree(),\n", + " )\n", + "for i, a in enumerate(ax3):\n", + " het_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n", + " a.scatter(\n", + " lonlats[i][0],\n", + " lonlats[i][1],\n", + " het_mask[i].sel(mode=mode).values * 0.5,\n", + " color=\"k\",\n", + " alpha=0.5,\n", + " transform=PlateCarree(),\n", + " )\n", + "\n", + "for i, a in enumerate(ax4):\n", + " scores[i].sel(mode=mode).plot(ax=a)\n", + " a.set_xlabel(\"\")\n", + "\n", + "\n", + "for a in np.ravel([ax1, ax2, ax3]):\n", + " a.coastlines(color=\".5\")\n", + " a.add_feature(LAND)\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"mca.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/2multi/plot_mca.py b/docs/auto_examples/2multi/plot_mca.py index 9b804644..d3b48de7 100644 --- a/docs/auto_examples/2multi/plot_mca.py +++ b/docs/auto_examples/2multi/plot_mca.py @@ -5,7 +5,6 @@ Maximum Covariance Analysis (MCA) between two data sets. """ - # Load packages and data: import numpy as np import xarray as xr diff --git a/docs/auto_examples/2multi/plot_mca.py.md5 b/docs/auto_examples/2multi/plot_mca.py.md5 index 8a390e95..99600e23 100644 --- a/docs/auto_examples/2multi/plot_mca.py.md5 +++ b/docs/auto_examples/2multi/plot_mca.py.md5 @@ -1 +1 @@ -b2503a0f6fe8980f1cee9be38f31c73e \ No newline at end of file +76e68784ad5c6cb6f7eb0924c3019da9 \ No newline at end of file diff --git a/docs/auto_examples/2multi/plot_mca.rst b/docs/auto_examples/2multi/plot_mca.rst index e2c381c6..06fa7336 100644 --- a/docs/auto_examples/2multi/plot_mca.rst +++ b/docs/auto_examples/2multi/plot_mca.rst @@ -23,10 +23,9 @@ Maximum Covariance Analysis Maximum Covariance Analysis (MCA) between two data sets. -.. GENERATED FROM PYTHON SOURCE LINES 7-19 - -.. code-block:: default +.. GENERATED FROM PYTHON SOURCE LINES 7-18 +.. code-block:: Python # Load packages and data: @@ -46,13 +45,13 @@ Maximum Covariance Analysis (MCA) between two data sets. -.. GENERATED FROM PYTHON SOURCE LINES 20-21 +.. GENERATED FROM PYTHON SOURCE LINES 19-20 Create 2 different DataArrays -.. GENERATED FROM PYTHON SOURCE LINES 21-26 +.. GENERATED FROM PYTHON SOURCE LINES 20-25 -.. code-block:: default +.. code-block:: Python t2m = xr.tutorial.load_dataset("air_temperature")["air"] @@ -66,13 +65,13 @@ Create 2 different DataArrays -.. GENERATED FROM PYTHON SOURCE LINES 27-28 +.. GENERATED FROM PYTHON SOURCE LINES 26-27 Perform MCA -.. GENERATED FROM PYTHON SOURCE LINES 28-32 +.. GENERATED FROM PYTHON SOURCE LINES 27-31 -.. code-block:: default +.. code-block:: Python mca = MCA(n_modes=20, standardize=False, use_coslat=True) @@ -87,18 +86,18 @@ Perform MCA .. code-block:: none - + -.. GENERATED FROM PYTHON SOURCE LINES 33-35 +.. GENERATED FROM PYTHON SOURCE LINES 32-34 Get singular vectors, projections (PCs), homogeneous and heterogeneous patterns: -.. GENERATED FROM PYTHON SOURCE LINES 35-41 +.. GENERATED FROM PYTHON SOURCE LINES 34-40 -.. code-block:: default +.. code-block:: Python singular_vectors = mca.components() @@ -113,16 +112,16 @@ patterns: -.. GENERATED FROM PYTHON SOURCE LINES 42-46 +.. GENERATED FROM PYTHON SOURCE LINES 41-45 When two fields are expected, the output of the above methods is a list of length 2, with the first and second entry containing the relevant object for ``X`` and ``Y``. For example, the p-values obtained from the two-sided t-test for the homogeneous patterns of ``X`` are: -.. GENERATED FROM PYTHON SOURCE LINES 46-49 +.. GENERATED FROM PYTHON SOURCE LINES 45-48 -.. code-block:: default +.. code-block:: Python pvals_hom[0] @@ -499,71 +498,31 @@ for the homogeneous patterns of ``X`` are: fill: currentColor; }
    <xarray.DataArray 'pvalues_of_left_homogeneous_patterns' (mode: 20, lat: 25,
    -                                                              lon: 26)>
    -    array([[[7.29374897e-298, 4.92157472e-268, 8.32382290e-265, ...,
    -             1.08681083e-108, 1.03639765e-164, 0.00000000e+000],
    -            [0.00000000e+000, 1.10991037e-316, 1.20740718e-261, ...,
    -             4.10518390e-131, 1.44361817e-128, 2.12644639e-154],
    -            [0.00000000e+000, 0.00000000e+000, 3.62777187e-317, ...,
    -             7.98234852e-039, 2.30423459e-094, 2.21447015e-303],
    -            ...,
    -            [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             0.00000000e+000, 0.00000000e+000, 0.00000000e+000],
    -            [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             0.00000000e+000, 0.00000000e+000, 0.00000000e+000],
    -            [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             0.00000000e+000, 0.00000000e+000, 0.00000000e+000]],
    -
    -           [[3.53356464e-053, 2.16458187e-064, 1.82082352e-072, ...,
    -             2.73963215e-061, 1.91557069e-001, 1.78821911e-051],
    -            [1.09082456e-048, 9.63033598e-054, 5.03588837e-061, ...,
    -             5.32308100e-062, 3.17748175e-139, 4.93155255e-125],
    -            [2.28500864e-026, 6.67730087e-023, 1.31657526e-042, ...,
    -             3.45643640e-301, 5.93676048e-211, 6.80890371e-056],
    -    ...
    -            [6.68028323e-015, 6.36799636e-016, 1.40424635e-015, ...,
    -             7.79519418e-001, 5.47948179e-001, 3.94369444e-001],
    -            [1.60502590e-010, 2.56625354e-010, 1.28102262e-009, ...,
    -             2.29172525e-001, 1.46246437e-001, 1.06877108e-001],
    -            [1.32442878e-009, 3.66374656e-009, 1.85914222e-008, ...,
    -             1.67860641e-001, 1.50368398e-001, 1.54500266e-001]],
    -
    -           [[3.52336556e-001, 1.68719893e-002, 1.89032329e-002, ...,
    -             7.85325588e-001, 2.77656062e-004, 2.09278514e-009],
    -            [3.51835129e-001, 2.03858184e-001, 1.77920685e-001, ...,
    -             1.67769352e-003, 1.75517410e-004, 3.62760486e-006],
    -            [4.94662972e-001, 3.67637823e-001, 1.12698398e-001, ...,
    -             1.02161213e-007, 7.09256483e-005, 3.77172316e-004],
    -            ...,
    -            [4.02700721e-019, 1.70640543e-018, 2.01380734e-017, ...,
    -             6.53881051e-001, 6.06515118e-001, 5.74031976e-001],
    -            [7.98658654e-007, 2.85676775e-006, 1.07423123e-005, ...,
    -             8.18013734e-001, 9.27700927e-001, 9.60593627e-001],
    -            [3.43962237e-002, 6.48273766e-002, 1.22432687e-001, ...,
    -             8.68261063e-002, 1.68867366e-001, 2.89714726e-001]]])
    +                                                              lon: 26)> Size: 104kB
    +    7.302e-298 4.926e-268 8.327e-265 3.64e-251 ... 0.04256 0.08683 0.1689 0.2897
         Coordinates:
    -      * lat      (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 65.0 67.5 70.0 72.5 75.0
    -      * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 255.0 257.5 260.0 262.5
    -      * mode     (mode) int64 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    -    Attributes: (12/14)
    -        model:         MCA
    -        software:      xeofs
    -        version:       1.2.0
    -        date:          2023-10-29 13:29:43
    -        n_modes:       20
    -        center:        True
    -        ...            ...
    -        n_pca_modes:   None
    -        compute:       True
    -        sample_name:   sample
    -        feature_name:  feature
    -        solver:        auto
    -        random_state:  None
  • model :
    MCA
    software :
    xeofs
    version :
    2.3.2
    date :
    2024-03-31 21:13:25
    n_modes :
    20
    center :
    True
    standardize :
    False
    use_coslat :
    True
    check_nans :
    True
    n_pca_modes :
    None
    compute :
    True
    sample_name :
    sample
    feature_name :
    feature
    solver :
    auto
    random_state :
    None
    solver_kwargs :
    {}


  • -.. GENERATED FROM PYTHON SOURCE LINES 50-51 +.. GENERATED FROM PYTHON SOURCE LINES 49-50 Create a mask to identifiy where p-values are below 0.05 -.. GENERATED FROM PYTHON SOURCE LINES 51-56 +.. GENERATED FROM PYTHON SOURCE LINES 50-55 -.. code-block:: default +.. code-block:: Python hom_mask = [values < 0.05 for values in pvals_hom] @@ -634,13 +593,13 @@ Create a mask to identifiy where p-values are below 0.05 -.. GENERATED FROM PYTHON SOURCE LINES 57-58 +.. GENERATED FROM PYTHON SOURCE LINES 56-57 Plot some relevant quantities of mode 2. -.. GENERATED FROM PYTHON SOURCE LINES 58-114 +.. GENERATED FROM PYTHON SOURCE LINES 57-113 -.. code-block:: default +.. code-block:: Python lonlats = [ @@ -707,13 +666,20 @@ Plot some relevant quantities of mode 2. :class: sphx-glr-single-img +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + /home/slevang/miniconda3/envs/xeofs-docs/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_land.zip + warnings.warn(f'Downloading: {url}', DownloadWarning) + .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 4.349 seconds) + **Total running time of the script:** (0 minutes 3.519 seconds) .. _sphx_glr_download_auto_examples_2multi_plot_mca.py: @@ -722,17 +688,14 @@ Plot some relevant quantities of mode 2. .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_mca.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_mca.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_mca.ipynb ` - .. only:: html diff --git a/docs/auto_examples/2multi/plot_mca_codeobj.pickle b/docs/auto_examples/2multi/plot_mca_codeobj.pickle index 7c5d36e8..8279095a 100644 Binary files a/docs/auto_examples/2multi/plot_mca_codeobj.pickle and b/docs/auto_examples/2multi/plot_mca_codeobj.pickle differ diff --git a/docs/auto_examples/2multi/plot_rotated_mca.ipynb b/docs/auto_examples/2multi/plot_rotated_mca.ipynb index ff8cbd3d..8bc915f4 100644 --- a/docs/auto_examples/2multi/plot_rotated_mca.ipynb +++ b/docs/auto_examples/2multi/plot_rotated_mca.ipynb @@ -1,169 +1,237 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Rotated Maximum Covariance Analysis\n\nRotated Maximum Covariance Analysis (MCA) between two data sets.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Load packages and data:\nimport numpy as np\nimport xarray as xr\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import Orthographic, PlateCarree\nfrom cartopy.feature import LAND\n\nfrom xeofs.models import MCA, MCARotator" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create 2 different DataArrays\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "t2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]\nda1 = t2m.isel(lon=slice(0, 26))\nda2 = t2m.isel(lon=slice(27, None))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform MCA\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "mca = MCA(n_modes=20, standardize=False, use_coslat=True)\nmca.fit(da1, da2, dim=\"time\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Apply Varimax-rotation to MCA solution\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "rot = MCARotator(n_modes=10)\nrot.fit(mca)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get rotated singular vectors, projections (PCs), homogeneous and heterogeneous\npatterns:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "singular_vectors = rot.components()\nscores = rot.scores()\nhom_pats, pvals_hom = rot.homogeneous_patterns()\nhet_pats, pvals_het = rot.heterogeneous_patterns()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When two fields are expected, the output of the above methods is a list of\nlength 2, with the first and second entry containing the relevant object for\n``X`` and ``Y``. For example, the p-values obtained from the two-sided t-test\nfor the homogeneous patterns of ``X`` are:\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "pvals_hom[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a mask to identifiy where p-values are below 0.05\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "hom_mask = [values < 0.05 for values in pvals_hom]\nhet_mask = [values < 0.05 for values in pvals_het]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Plot some relevant quantities of mode 2.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "lonlats = [\n np.meshgrid(pvals_hom[0].lon.values, pvals_hom[0].lat.values),\n np.meshgrid(pvals_hom[1].lon.values, pvals_hom[1].lat.values),\n]\nproj = [\n Orthographic(central_latitude=30, central_longitude=-120),\n Orthographic(central_latitude=30, central_longitude=-60),\n]\nkwargs1 = {\"cmap\": \"BrBG\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\nkwargs2 = {\"cmap\": \"RdBu\", \"vmin\": -1, \"vmax\": 1, \"transform\": PlateCarree()}\n\nmode = 2\n\nfig = plt.figure(figsize=(7, 14))\ngs = GridSpec(5, 2)\nax1 = [fig.add_subplot(gs[0, i], projection=proj[i]) for i in range(2)]\nax2 = [fig.add_subplot(gs[1, i], projection=proj[i]) for i in range(2)]\nax3 = [fig.add_subplot(gs[2, i], projection=proj[i]) for i in range(2)]\nax4 = [fig.add_subplot(gs[3, i]) for i in range(2)]\n\nfor i, a in enumerate(ax1):\n singular_vectors[i].sel(mode=mode).plot(ax=a, **kwargs1)\n\nfor i, a in enumerate(ax2):\n hom_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n a.scatter(\n lonlats[i][0],\n lonlats[i][1],\n hom_mask[i].sel(mode=mode).values * 0.5,\n color=\"k\",\n alpha=0.5,\n transform=PlateCarree(),\n )\nfor i, a in enumerate(ax3):\n het_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n a.scatter(\n lonlats[i][0],\n lonlats[i][1],\n het_mask[i].sel(mode=mode).values * 0.5,\n color=\"k\",\n alpha=0.5,\n transform=PlateCarree(),\n )\n\nfor i, a in enumerate(ax4):\n scores[i].sel(mode=mode).plot(ax=a)\n a.set_xlabel(\"\")\n\n\nfor a in np.ravel([ax1, ax2, ax3]):\n a.coastlines(color=\".5\")\n a.add_feature(LAND)\n\nplt.tight_layout()\nplt.savefig(\"rotated_mca.jpg\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Rotated Maximum Covariance Analysis\n", + "\n", + "Rotated Maximum Covariance Analysis (MCA) between two data sets.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load packages and data:\n", + "import numpy as np\n", + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import Orthographic, PlateCarree\n", + "from cartopy.feature import LAND\n", + "\n", + "from xeofs.models import MCA, MCARotator" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create 2 different DataArrays\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]\n", + "da1 = t2m.isel(lon=slice(0, 26))\n", + "da2 = t2m.isel(lon=slice(27, None))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform MCA\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mca = MCA(n_modes=20, standardize=False, use_coslat=True)\n", + "mca.fit(da1, da2, dim=\"time\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Apply Varimax-rotation to MCA solution\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "rot = MCARotator(n_modes=10)\n", + "rot.fit(mca)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get rotated singular vectors, projections (PCs), homogeneous and heterogeneous\n", + "patterns:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "singular_vectors = rot.components()\n", + "scores = rot.scores()\n", + "hom_pats, pvals_hom = rot.homogeneous_patterns()\n", + "het_pats, pvals_het = rot.heterogeneous_patterns()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When two fields are expected, the output of the above methods is a list of\n", + "length 2, with the first and second entry containing the relevant object for\n", + "``X`` and ``Y``. For example, the p-values obtained from the two-sided t-test\n", + "for the homogeneous patterns of ``X`` are:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pvals_hom[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a mask to identifiy where p-values are below 0.05\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hom_mask = [values < 0.05 for values in pvals_hom]\n", + "het_mask = [values < 0.05 for values in pvals_het]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot some relevant quantities of mode 2.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lonlats = [\n", + " np.meshgrid(pvals_hom[0].lon.values, pvals_hom[0].lat.values),\n", + " np.meshgrid(pvals_hom[1].lon.values, pvals_hom[1].lat.values),\n", + "]\n", + "proj = [\n", + " Orthographic(central_latitude=30, central_longitude=-120),\n", + " Orthographic(central_latitude=30, central_longitude=-60),\n", + "]\n", + "kwargs1 = {\"cmap\": \"BrBG\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\n", + "kwargs2 = {\"cmap\": \"RdBu\", \"vmin\": -1, \"vmax\": 1, \"transform\": PlateCarree()}\n", + "\n", + "mode = 2\n", + "\n", + "fig = plt.figure(figsize=(7, 14))\n", + "gs = GridSpec(5, 2)\n", + "ax1 = [fig.add_subplot(gs[0, i], projection=proj[i]) for i in range(2)]\n", + "ax2 = [fig.add_subplot(gs[1, i], projection=proj[i]) for i in range(2)]\n", + "ax3 = [fig.add_subplot(gs[2, i], projection=proj[i]) for i in range(2)]\n", + "ax4 = [fig.add_subplot(gs[3, i]) for i in range(2)]\n", + "\n", + "for i, a in enumerate(ax1):\n", + " singular_vectors[i].sel(mode=mode).plot(ax=a, **kwargs1)\n", + "\n", + "for i, a in enumerate(ax2):\n", + " hom_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n", + " a.scatter(\n", + " lonlats[i][0],\n", + " lonlats[i][1],\n", + " hom_mask[i].sel(mode=mode).values * 0.5,\n", + " color=\"k\",\n", + " alpha=0.5,\n", + " transform=PlateCarree(),\n", + " )\n", + "for i, a in enumerate(ax3):\n", + " het_pats[i].sel(mode=mode).plot(ax=a, **kwargs2)\n", + " a.scatter(\n", + " lonlats[i][0],\n", + " lonlats[i][1],\n", + " het_mask[i].sel(mode=mode).values * 0.5,\n", + " color=\"k\",\n", + " alpha=0.5,\n", + " transform=PlateCarree(),\n", + " )\n", + "\n", + "for i, a in enumerate(ax4):\n", + " scores[i].sel(mode=mode).plot(ax=a)\n", + " a.set_xlabel(\"\")\n", + "\n", + "\n", + "for a in np.ravel([ax1, ax2, ax3]):\n", + " a.coastlines(color=\".5\")\n", + " a.add_feature(LAND)\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"rotated_mca.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/2multi/plot_rotated_mca.py b/docs/auto_examples/2multi/plot_rotated_mca.py index 59d337bc..a7ec89fe 100644 --- a/docs/auto_examples/2multi/plot_rotated_mca.py +++ b/docs/auto_examples/2multi/plot_rotated_mca.py @@ -5,7 +5,6 @@ Rotated Maximum Covariance Analysis (MCA) between two data sets. """ - # Load packages and data: import numpy as np import xarray as xr diff --git a/docs/auto_examples/2multi/plot_rotated_mca.py.md5 b/docs/auto_examples/2multi/plot_rotated_mca.py.md5 index ead7bc43..c25ed037 100644 --- a/docs/auto_examples/2multi/plot_rotated_mca.py.md5 +++ b/docs/auto_examples/2multi/plot_rotated_mca.py.md5 @@ -1 +1 @@ -03131f27bffceae9db1f188ff8f11a23 \ No newline at end of file +2a8fc6d56ead0b05f3f5c909c0e07bbb \ No newline at end of file diff --git a/docs/auto_examples/2multi/plot_rotated_mca.rst b/docs/auto_examples/2multi/plot_rotated_mca.rst index f283e8c5..902df371 100644 --- a/docs/auto_examples/2multi/plot_rotated_mca.rst +++ b/docs/auto_examples/2multi/plot_rotated_mca.rst @@ -23,10 +23,9 @@ Rotated Maximum Covariance Analysis Rotated Maximum Covariance Analysis (MCA) between two data sets. -.. GENERATED FROM PYTHON SOURCE LINES 7-19 - -.. code-block:: default +.. GENERATED FROM PYTHON SOURCE LINES 7-18 +.. code-block:: Python # Load packages and data: @@ -46,13 +45,13 @@ Rotated Maximum Covariance Analysis (MCA) between two data sets. -.. GENERATED FROM PYTHON SOURCE LINES 20-21 +.. GENERATED FROM PYTHON SOURCE LINES 19-20 Create 2 different DataArrays -.. GENERATED FROM PYTHON SOURCE LINES 21-26 +.. GENERATED FROM PYTHON SOURCE LINES 20-25 -.. code-block:: default +.. code-block:: Python t2m = xr.tutorial.load_dataset("air_temperature")["air"] @@ -66,13 +65,13 @@ Create 2 different DataArrays -.. GENERATED FROM PYTHON SOURCE LINES 27-28 +.. GENERATED FROM PYTHON SOURCE LINES 26-27 Perform MCA -.. GENERATED FROM PYTHON SOURCE LINES 28-32 +.. GENERATED FROM PYTHON SOURCE LINES 27-31 -.. code-block:: default +.. code-block:: Python mca = MCA(n_modes=20, standardize=False, use_coslat=True) @@ -87,17 +86,17 @@ Perform MCA .. code-block:: none - + -.. GENERATED FROM PYTHON SOURCE LINES 33-34 +.. GENERATED FROM PYTHON SOURCE LINES 32-33 Apply Varimax-rotation to MCA solution -.. GENERATED FROM PYTHON SOURCE LINES 34-38 +.. GENERATED FROM PYTHON SOURCE LINES 33-37 -.. code-block:: default +.. code-block:: Python rot = MCARotator(n_modes=10) @@ -107,17 +106,23 @@ Apply Varimax-rotation to MCA solution +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + -.. GENERATED FROM PYTHON SOURCE LINES 39-41 + + +.. GENERATED FROM PYTHON SOURCE LINES 38-40 Get rotated singular vectors, projections (PCs), homogeneous and heterogeneous patterns: -.. GENERATED FROM PYTHON SOURCE LINES 41-47 +.. GENERATED FROM PYTHON SOURCE LINES 40-46 -.. code-block:: default +.. code-block:: Python singular_vectors = rot.components() @@ -132,16 +137,16 @@ patterns: -.. GENERATED FROM PYTHON SOURCE LINES 48-52 +.. GENERATED FROM PYTHON SOURCE LINES 47-51 When two fields are expected, the output of the above methods is a list of length 2, with the first and second entry containing the relevant object for ``X`` and ``Y``. For example, the p-values obtained from the two-sided t-test for the homogeneous patterns of ``X`` are: -.. GENERATED FROM PYTHON SOURCE LINES 52-55 +.. GENERATED FROM PYTHON SOURCE LINES 51-54 -.. code-block:: default +.. code-block:: Python pvals_hom[0] @@ -518,52 +523,12 @@ for the homogeneous patterns of ``X`` are: fill: currentColor; }
    <xarray.DataArray 'pvalues_of_left_homogeneous_patterns' (mode: 10, lat: 25,
    -                                                              lon: 26)>
    -    array([[[5.91798633e-081, 4.09037030e-064, 6.23425561e-058, ...,
    -             4.45216591e-046, 7.99246088e-107, 6.95533368e-234],
    -            [9.61231974e-109, 4.30909052e-079, 2.41956104e-054, ...,
    -             1.13316213e-079, 1.17033263e-086, 1.58776474e-105],
    -            [3.65945612e-169, 1.03636735e-150, 5.85938600e-088, ...,
    -             2.66091078e-037, 1.39445455e-071, 1.89947470e-183],
    -            ...,
    -            [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             0.00000000e+000, 0.00000000e+000, 0.00000000e+000],
    -            [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             0.00000000e+000, 0.00000000e+000, 0.00000000e+000],
    -            [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             0.00000000e+000, 0.00000000e+000, 0.00000000e+000]],
    -
    -           [[0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             2.15049395e-115, 1.25690777e-037, 3.79422747e-010],
    -            [0.00000000e+000, 0.00000000e+000, 0.00000000e+000, ...,
    -             3.68434950e-006, 4.54442588e-001, 7.47361402e-001],
    -            [5.82970051e-304, 1.04446785e-286, 1.67982320e-322, ...,
    -             3.12415723e-031, 2.97910617e-009, 3.83983102e-013],
    -    ...
    -            [3.81951811e-033, 1.24766309e-035, 9.83759118e-037, ...,
    -             1.08208863e-007, 2.09241618e-007, 9.75026228e-007],
    -            [7.63507975e-018, 1.84998265e-018, 1.85005250e-018, ...,
    -             1.47665784e-002, 2.23166837e-002, 3.74986857e-002],
    -            [5.23820545e-013, 5.59326448e-014, 1.46539526e-014, ...,
    -             7.79688798e-001, 7.97072146e-001, 8.38057312e-001]],
    -
    -           [[1.33009336e-001, 3.88106643e-002, 2.39386496e-003, ...,
    -             9.33561796e-001, 6.41357062e-001, 5.12874473e-001],
    -            [2.47971905e-002, 1.49401803e-002, 1.01803200e-003, ...,
    -             9.48611093e-001, 3.16366009e-001, 6.29374852e-002],
    -            [1.00284803e-002, 8.50825810e-002, 1.51720312e-001, ...,
    -             2.62222025e-001, 1.27842313e-002, 1.43419078e-004],
    -            ...,
    -            [6.95159651e-010, 1.10849674e-010, 2.79734189e-011, ...,
    -             2.20338645e-004, 2.58483821e-003, 2.44608586e-002],
    -            [2.08872724e-002, 1.93770600e-002, 2.08168263e-002, ...,
    -             3.74564462e-004, 2.56337651e-003, 1.63483691e-002],
    -            [9.06082861e-001, 8.64987130e-001, 8.39176635e-001, ...,
    -             5.47872690e-003, 1.49439193e-002, 3.60352909e-002]]])
    +                                                              lon: 26)> Size: 52kB
    +    5.921e-81 4.092e-64 6.235e-58 5.975e-49 ... 0.001974 0.005479 0.01494 0.03604
         Coordinates:
    -      * lat      (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 65.0 67.5 70.0 72.5 75.0
    -      * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 255.0 257.5 260.0 262.5
    -      * mode     (mode) int64 1 2 3 4 5 6 7 8 9 10
    +      * lat      (lat) float32 100B 15.0 17.5 20.0 22.5 25.0 ... 67.5 70.0 72.5 75.0
    +      * lon      (lon) float32 104B 200.0 202.5 205.0 207.5 ... 257.5 260.0 262.5
    +      * mode     (mode) int64 80B 1 2 3 4 5 6 7 8 9 10
         Attributes:
             model:             Rotated MCA
             n_modes:           10
    @@ -571,14 +536,15 @@ for the homogeneous patterns of ``X`` are:
             max_iter:          1000
             rtol:              1e-08
             squared_loadings:  False
    +        compute:           True
             software:          xeofs
    -        version:           1.2.0
    -        date:              2023-10-29 13:29:48
  • model :
    Rotated MCA
    n_modes :
    10
    power :
    1
    max_iter :
    1000
    rtol :
    1e-08
    squared_loadings :
    False
    compute :
    True
    software :
    xeofs
    version :
    2.3.2
    date :
    2024-03-31 21:13:29


  • -.. GENERATED FROM PYTHON SOURCE LINES 56-57 +.. GENERATED FROM PYTHON SOURCE LINES 55-56 Create a mask to identifiy where p-values are below 0.05 -.. GENERATED FROM PYTHON SOURCE LINES 57-62 +.. GENERATED FROM PYTHON SOURCE LINES 56-61 -.. code-block:: default +.. code-block:: Python hom_mask = [values < 0.05 for values in pvals_hom] @@ -648,13 +614,13 @@ Create a mask to identifiy where p-values are below 0.05 -.. GENERATED FROM PYTHON SOURCE LINES 63-64 +.. GENERATED FROM PYTHON SOURCE LINES 62-63 Plot some relevant quantities of mode 2. -.. GENERATED FROM PYTHON SOURCE LINES 64-120 +.. GENERATED FROM PYTHON SOURCE LINES 63-119 -.. code-block:: default +.. code-block:: Python lonlats = [ @@ -727,7 +693,7 @@ Plot some relevant quantities of mode 2. .. rst-class:: sphx-glr-timing - **Total running time of the script:** (0 minutes 3.714 seconds) + **Total running time of the script:** (0 minutes 2.207 seconds) .. _sphx_glr_download_auto_examples_2multi_plot_rotated_mca.py: @@ -736,17 +702,14 @@ Plot some relevant quantities of mode 2. .. container:: sphx-glr-footer sphx-glr-footer-example + .. container:: sphx-glr-download sphx-glr-download-jupyter - + :download:`Download Jupyter notebook: plot_rotated_mca.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_rotated_mca.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_rotated_mca.ipynb ` - .. only:: html diff --git a/docs/auto_examples/2multi/plot_rotated_mca_codeobj.pickle b/docs/auto_examples/2multi/plot_rotated_mca_codeobj.pickle index 6b946dbb..ea3553d3 100644 Binary files a/docs/auto_examples/2multi/plot_rotated_mca_codeobj.pickle and b/docs/auto_examples/2multi/plot_rotated_mca_codeobj.pickle differ diff --git a/docs/auto_examples/2multi/sg_execution_times.rst b/docs/auto_examples/2multi/sg_execution_times.rst index 726e6a3c..815af82c 100644 --- a/docs/auto_examples/2multi/sg_execution_times.rst +++ b/docs/auto_examples/2multi/sg_execution_times.rst @@ -6,12 +6,38 @@ Computation times ================= -**00:08.063** total execution time for **auto_examples_2multi** files: - -+------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_2multi_plot_mca.py` (``plot_mca.py``) | 00:04.349 | 0.0 MB | -+------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_2multi_plot_rotated_mca.py` (``plot_rotated_mca.py``) | 00:03.714 | 0.0 MB | -+------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_2multi_plot_cca.py` (``plot_cca.py``) | 00:00.000 | 0.0 MB | -+------------------------------------------------------------------------------------+-----------+--------+ +**00:07.357** total execution time for 3 files **from auto_examples/2multi**: + +.. container:: + + .. raw:: html + + + + + + + + .. list-table:: + :header-rows: 1 + :class: table table-striped sg-datatable + + * - Example + - Time + - Mem (MB) + * - :ref:`sphx_glr_auto_examples_2multi_plot_mca.py` (``plot_mca.py``) + - 00:03.519 + - 0.0 + * - :ref:`sphx_glr_auto_examples_2multi_plot_rotated_mca.py` (``plot_rotated_mca.py``) + - 00:02.207 + - 0.0 + * - :ref:`sphx_glr_auto_examples_2multi_plot_cca.py` (``plot_cca.py``) + - 00:01.632 + - 0.0 diff --git a/docs/auto_examples/3validation/images/sphx_glr_plot_bootstrap_001.png b/docs/auto_examples/3validation/images/sphx_glr_plot_bootstrap_001.png index ecfbacf6..6baca248 100644 Binary files a/docs/auto_examples/3validation/images/sphx_glr_plot_bootstrap_001.png and b/docs/auto_examples/3validation/images/sphx_glr_plot_bootstrap_001.png differ diff --git a/docs/auto_examples/3validation/images/thumb/sphx_glr_plot_bootstrap_thumb.png b/docs/auto_examples/3validation/images/thumb/sphx_glr_plot_bootstrap_thumb.png index 988a6fcd..6081e99f 100644 Binary files a/docs/auto_examples/3validation/images/thumb/sphx_glr_plot_bootstrap_thumb.png and b/docs/auto_examples/3validation/images/thumb/sphx_glr_plot_bootstrap_thumb.png differ diff --git a/docs/auto_examples/3validation/plot_bootstrap.ipynb b/docs/auto_examples/3validation/plot_bootstrap.ipynb index 994e7b62..a9b7b574 100644 --- a/docs/auto_examples/3validation/plot_bootstrap.ipynb +++ b/docs/auto_examples/3validation/plot_bootstrap.ipynb @@ -1,126 +1,182 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Significance testing of EOF analysis via bootstrap\n\nTest the significance of individual modes and obtain confidence intervals\nfor both EOFs and PCs.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# Load packages and data:\nimport numpy as np\nimport xarray as xr\nimport matplotlib.pyplot as plt\nfrom matplotlib.gridspec import GridSpec\nfrom cartopy.crs import Orthographic, PlateCarree\n\nfrom xeofs.models import EOF\nfrom xeofs.validation import EOFBootstrapper" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "t2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform EOF analysis\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "model = EOF(n_modes=5, standardize=False)\nmodel.fit(t2m, dim=\"time\")\nexpvar = model.explained_variance_ratio()\ncomponents = model.components()\nscores = model.scores()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Perform bootstrapping of the model to identy the number of significant modes.\nWe perform 50 bootstraps.\nNote - if computationallly feasible - you typically want to choose higher\nnumbers of bootstraps e.g. 1000.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "n_boot = 50\n\nbs = EOFBootstrapper(n_bootstraps=n_boot)\nbs.fit(model)\nbs_expvar = bs.explained_variance()\nci_expvar = bs_expvar.quantile([0.025, 0.975], \"n\") # 95% confidence intervals\n\nq025 = ci_expvar.sel(quantile=0.025)\nq975 = ci_expvar.sel(quantile=0.975)\n\nis_significant = q025 - q975.shift({\"mode\": -1}) > 0\nn_significant_modes = (\n is_significant.where(is_significant == True).cumsum(skipna=False).max().fillna(0)\n)\nprint(\"{:} modes are significant at alpha=0.05\".format(n_significant_modes.values))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The bootstrapping procedure identifies 3 significant modes. We can also\ncompute the 95 % confidence intervals of the EOFs/PCs and mask out\ninsignificant elements of the obtained EOFs.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "ci_components = bs.components().quantile([0.025, 0.975], \"n\")\nci_scores = bs.scores().quantile([0.025, 0.975], \"n\")\n\nis_sig_comps = np.sign(ci_components).prod(\"quantile\") > 0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Summarize the results in a figure.\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "lons, lats = np.meshgrid(is_sig_comps.lon.values, is_sig_comps.lat.values)\nproj = Orthographic(central_latitude=30, central_longitude=-80)\nkwargs = {\"cmap\": \"RdBu\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\n\nfig = plt.figure(figsize=(10, 16))\ngs = GridSpec(5, 2)\nax1 = [fig.add_subplot(gs[i, 0], projection=proj) for i in range(5)]\nax2 = [fig.add_subplot(gs[i, 1]) for i in range(5)]\n\nfor i, (a1, a2) in enumerate(zip(ax1, ax2)):\n a1.coastlines(color=\".5\")\n components.isel(mode=i).plot(ax=a1, **kwargs)\n a1.scatter(\n lons,\n lats,\n is_sig_comps.isel(mode=i).values * 0.5,\n color=\"k\",\n alpha=0.5,\n transform=PlateCarree(),\n )\n ci_scores.isel(mode=i, quantile=0).plot(ax=a2, color=\".3\", lw=\".5\", label=\"2.5%\")\n ci_scores.isel(mode=i, quantile=1).plot(ax=a2, color=\".3\", lw=\".5\", label=\"97.5%\")\n scores.isel(mode=i).plot(ax=a2, lw=\".5\", alpha=0.5, label=\"PC\")\n a2.legend(loc=2)\n\nplt.tight_layout()\nplt.savefig(\"bootstrap.jpg\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.11.4" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Significance testing of EOF analysis via bootstrap\n", + "\n", + "Test the significance of individual modes and obtain confidence intervals\n", + "for both EOFs and PCs.\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load packages and data:\n", + "import numpy as np\n", + "import xarray as xr\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from cartopy.crs import Orthographic, PlateCarree\n", + "\n", + "from xeofs.models import EOF\n", + "from xeofs.validation import EOFBootstrapper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "t2m = xr.tutorial.load_dataset(\"air_temperature\")[\"air\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform EOF analysis\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = EOF(n_modes=5, standardize=False)\n", + "model.fit(t2m, dim=\"time\")\n", + "expvar = model.explained_variance_ratio()\n", + "components = model.components()\n", + "scores = model.scores()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perform bootstrapping of the model to identy the number of significant modes.\n", + "We perform 50 bootstraps.\n", + "Note - if computationallly feasible - you typically want to choose higher\n", + "numbers of bootstraps e.g. 1000.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "n_boot = 50\n", + "\n", + "bs = EOFBootstrapper(n_bootstraps=n_boot)\n", + "bs.fit(model)\n", + "bs_expvar = bs.explained_variance()\n", + "ci_expvar = bs_expvar.quantile([0.025, 0.975], \"n\") # 95% confidence intervals\n", + "\n", + "q025 = ci_expvar.sel(quantile=0.025)\n", + "q975 = ci_expvar.sel(quantile=0.975)\n", + "\n", + "is_significant = q025 - q975.shift({\"mode\": -1}) > 0\n", + "n_significant_modes = (\n", + " is_significant.where(is_significant is True).cumsum(skipna=False).max().fillna(0)\n", + ")\n", + "print(\"{:} modes are significant at alpha=0.05\".format(n_significant_modes.values))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The bootstrapping procedure identifies 3 significant modes. We can also\n", + "compute the 95 % confidence intervals of the EOFs/PCs and mask out\n", + "insignificant elements of the obtained EOFs.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ci_components = bs.components().quantile([0.025, 0.975], \"n\")\n", + "ci_scores = bs.scores().quantile([0.025, 0.975], \"n\")\n", + "\n", + "is_sig_comps = np.sign(ci_components).prod(\"quantile\") > 0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Summarize the results in a figure.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lons, lats = np.meshgrid(is_sig_comps.lon.values, is_sig_comps.lat.values)\n", + "proj = Orthographic(central_latitude=30, central_longitude=-80)\n", + "kwargs = {\"cmap\": \"RdBu\", \"vmin\": -0.05, \"vmax\": 0.05, \"transform\": PlateCarree()}\n", + "\n", + "fig = plt.figure(figsize=(10, 16))\n", + "gs = GridSpec(5, 2)\n", + "ax1 = [fig.add_subplot(gs[i, 0], projection=proj) for i in range(5)]\n", + "ax2 = [fig.add_subplot(gs[i, 1]) for i in range(5)]\n", + "\n", + "for i, (a1, a2) in enumerate(zip(ax1, ax2)):\n", + " a1.coastlines(color=\".5\")\n", + " components.isel(mode=i).plot(ax=a1, **kwargs)\n", + " a1.scatter(\n", + " lons,\n", + " lats,\n", + " is_sig_comps.isel(mode=i).values * 0.5,\n", + " color=\"k\",\n", + " alpha=0.5,\n", + " transform=PlateCarree(),\n", + " )\n", + " ci_scores.isel(mode=i, quantile=0).plot(ax=a2, color=\".3\", lw=\".5\", label=\"2.5%\")\n", + " ci_scores.isel(mode=i, quantile=1).plot(ax=a2, color=\".3\", lw=\".5\", label=\"97.5%\")\n", + " scores.isel(mode=i).plot(ax=a2, lw=\".5\", alpha=0.5, label=\"PC\")\n", + " a2.legend(loc=2)\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"bootstrap.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/auto_examples/3validation/plot_bootstrap.py b/docs/auto_examples/3validation/plot_bootstrap.py index 5a53af99..02cec5dc 100644 --- a/docs/auto_examples/3validation/plot_bootstrap.py +++ b/docs/auto_examples/3validation/plot_bootstrap.py @@ -6,7 +6,6 @@ for both EOFs and PCs. """ - # Load packages and data: import numpy as np import xarray as xr @@ -49,7 +48,7 @@ is_significant = q025 - q975.shift({"mode": -1}) > 0 n_significant_modes = ( - is_significant.where(is_significant == True).cumsum(skipna=False).max().fillna(0) + is_significant.where(is_significant is True).cumsum(skipna=False).max().fillna(0) ) print("{:} modes are significant at alpha=0.05".format(n_significant_modes.values)) diff --git a/docs/auto_examples/3validation/plot_bootstrap.py.md5 b/docs/auto_examples/3validation/plot_bootstrap.py.md5 index fa4f3e89..8f63d45c 100644 --- a/docs/auto_examples/3validation/plot_bootstrap.py.md5 +++ b/docs/auto_examples/3validation/plot_bootstrap.py.md5 @@ -1 +1 @@ -3ab68b97210891b1db8335ada89b8563 \ No newline at end of file +e9826d4566fc7f2d94555e72a94c50c8 \ No newline at end of file diff --git a/docs/auto_examples/3validation/plot_bootstrap.rst b/docs/auto_examples/3validation/plot_bootstrap.rst index c2c90420..e77e8f63 100644 --- a/docs/auto_examples/3validation/plot_bootstrap.rst +++ b/docs/auto_examples/3validation/plot_bootstrap.rst @@ -24,10 +24,9 @@ Significance testing of EOF analysis via bootstrap Test the significance of individual modes and obtain confidence intervals for both EOFs and PCs. -.. GENERATED FROM PYTHON SOURCE LINES 8-20 - -.. code-block:: default +.. GENERATED FROM PYTHON SOURCE LINES 8-19 +.. code-block:: Python # Load packages and data: @@ -47,9 +46,9 @@ for both EOFs and PCs. -.. GENERATED FROM PYTHON SOURCE LINES 21-24 +.. GENERATED FROM PYTHON SOURCE LINES 20-23 -.. code-block:: default +.. code-block:: Python t2m = xr.tutorial.load_dataset("air_temperature")["air"] @@ -61,13 +60,13 @@ for both EOFs and PCs. -.. GENERATED FROM PYTHON SOURCE LINES 25-26 +.. GENERATED FROM PYTHON SOURCE LINES 24-25 Perform EOF analysis -.. GENERATED FROM PYTHON SOURCE LINES 26-34 +.. GENERATED FROM PYTHON SOURCE LINES 25-33 -.. code-block:: default +.. code-block:: Python model = EOF(n_modes=5, standardize=False) @@ -84,16 +83,16 @@ Perform EOF analysis -.. GENERATED FROM PYTHON SOURCE LINES 35-39 +.. GENERATED FROM PYTHON SOURCE LINES 34-38 Perform bootstrapping of the model to identy the number of significant modes. We perform 50 bootstraps. Note - if computationallly feasible - you typically want to choose higher numbers of bootstraps e.g. 1000. -.. GENERATED FROM PYTHON SOURCE LINES 39-56 +.. GENERATED FROM PYTHON SOURCE LINES 38-55 -.. code-block:: default +.. code-block:: Python n_boot = 50 @@ -108,7 +107,7 @@ numbers of bootstraps e.g. 1000. is_significant = q025 - q975.shift({"mode": -1}) > 0 n_significant_modes = ( - is_significant.where(is_significant == True).cumsum(skipna=False).max().fillna(0) + is_significant.where(is_significant is True).cumsum(skipna=False).max().fillna(0) ) print("{:} modes are significant at alpha=0.05".format(n_significant_modes.values)) @@ -120,21 +119,21 @@ numbers of bootstraps e.g. 1000. .. code-block:: none - 0%| | 0/50 [00:00` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_bootstrap.py ` - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: plot_bootstrap.ipynb ` - .. only:: html diff --git a/docs/auto_examples/3validation/plot_bootstrap_codeobj.pickle b/docs/auto_examples/3validation/plot_bootstrap_codeobj.pickle index eaa38f04..1285dc7e 100644 Binary files a/docs/auto_examples/3validation/plot_bootstrap_codeobj.pickle and b/docs/auto_examples/3validation/plot_bootstrap_codeobj.pickle differ diff --git a/docs/auto_examples/3validation/sg_execution_times.rst b/docs/auto_examples/3validation/sg_execution_times.rst index 1e19def0..fafa61f1 100644 --- a/docs/auto_examples/3validation/sg_execution_times.rst +++ b/docs/auto_examples/3validation/sg_execution_times.rst @@ -6,8 +6,32 @@ Computation times ================= -**00:37.867** total execution time for **auto_examples_3validation** files: +**00:16.004** total execution time for 1 file **from auto_examples/3validation**: -+-------------------------------------------------------------------------------------+-----------+--------+ -| :ref:`sphx_glr_auto_examples_3validation_plot_bootstrap.py` (``plot_bootstrap.py``) | 00:37.867 | 0.0 MB | -+-------------------------------------------------------------------------------------+-----------+--------+ +.. container:: + + .. raw:: html + + + + + + + + .. list-table:: + :header-rows: 1 + :class: table table-striped sg-datatable + + * - Example + - Time + - Mem (MB) + * - :ref:`sphx_glr_auto_examples_3validation_plot_bootstrap.py` (``plot_bootstrap.py``) + - 00:16.004 + - 0.0 diff --git a/docs/auto_examples/auto_examples_jupyter.zip b/docs/auto_examples/auto_examples_jupyter.zip index 1a2ad1b8..76606f1f 100644 Binary files a/docs/auto_examples/auto_examples_jupyter.zip and b/docs/auto_examples/auto_examples_jupyter.zip differ diff --git a/docs/auto_examples/auto_examples_python.zip b/docs/auto_examples/auto_examples_python.zip index e8271add..e0b05b70 100644 Binary files a/docs/auto_examples/auto_examples_python.zip and b/docs/auto_examples/auto_examples_python.zip differ diff --git a/docs/auto_examples/index.rst b/docs/auto_examples/index.rst index 32c2a625..67544df8 100644 --- a/docs/auto_examples/index.rst +++ b/docs/auto_examples/index.rst @@ -28,7 +28,7 @@ Here you can find some examples of how to use the library. .. raw:: html -
    +
    .. only:: html @@ -62,7 +62,7 @@ Here you can find some examples of how to use the library. .. raw:: html -
    +
    .. only:: html @@ -212,7 +212,7 @@ Here you can find some examples of how to use the library. .. raw:: html -
    +
    .. only:: html diff --git a/docs/conf.py b/docs/conf.py index bb57acb9..1a44863f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -124,7 +124,7 @@ # Label for this link "name": "GitHub", # URL where the link will redirect - "url": "https://github.com/nicrie/xeofs", # required + "url": "https://github.com/xarray-contrib/xeofs", # required # Icon class (if "type": "fontawesome"), or path to local image (if "type": "local") "icon": "fa-brands fa-square-github", # The type of image to be used (see below for details) diff --git a/docs/environment.yml b/docs/environment.yml index 210140ee..1a391d27 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -3,27 +3,9 @@ channels: - conda-forge - nodefaults # https://github.com/readthedocs/readthedocs.org/issues/9527 dependencies: - - python==3.11 - - numpy - - pandas - - xarray - - conda - - scikit-learn - - statsmodels - - dask - - yaml - - matplotlib - - seaborn - - cartopy - - ipython - - ipykernel + - python=3.11 - rpy2 - - sphinx-gallery - - sphinx-design - - sphinx-copybutton - - nbsphinx - - pydata-sphinx-theme - - sphinx - - nbconvert + - pandoc + - pip - pip: - - xeofs + - -e ../.[docs] diff --git a/docs/overview_2_features.rst b/docs/overview_2_features.rst index 55327578..9c626840 100644 --- a/docs/overview_2_features.rst +++ b/docs/overview_2_features.rst @@ -141,6 +141,13 @@ the input type. For instance, executing PCA on a singular ``xr.DataArray`` will A mixed list containing both ``xr.DataArray`` and ``xr.Dataset`` objects is not currently supported. +.. note:: + + Some methods like PCA/EOF analysis can also handle complex-valued input data. However, due to a limitation_ in the + underlying ``dask`` library, complex-valued data is not supported when using ``dask``. + +.. _limitation: https://github.com/dask/dask/issues/7639 + Handling Missing Values ----------------------- @@ -193,7 +200,7 @@ significant speed advantages. The dashed line marks data sets with about 3 MiB; You can find the script to run the performance tests here_. -.. _here: https://github.com/nicrie/xeofs/tree/main/docs/perf +.. _here: https://github.com/xarray-contrib/xeofs/tree/main/docs/perf Implement Your Own Model ------------------------- @@ -392,5 +399,5 @@ toolkit for dimensionality reduction techniques. .. _xMCA: https://github.com/Yefee/xMCA .. _eofs: https://github.com/ajdawson/eofs .. _`sklearn documentation on PCA`: https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html -.. _`GitHub`: https://github.com/nicrie/xeofs/issues +.. _`GitHub`: https://github.com/xarray-contrib/xeofs/issues diff --git a/docs/overview_3_contributing.rst b/docs/overview_3_contributing.rst index b1adaa43..3cf44aa4 100644 --- a/docs/overview_3_contributing.rst +++ b/docs/overview_3_contributing.rst @@ -35,7 +35,7 @@ Next, clone your fork to your computer: git clone https://github.com/your-user-name/xeofs.git cd xeofs - git remote add upstream https://github.com/nicrie/xeofs.git + git remote add upstream https://github.com/xarray-contrib/xeofs.git This command sequence creates a local directory named *xeofs* and links your version to the primary xeofs project. @@ -46,21 +46,21 @@ Using the commands below, prepare your environment: .. code-block:: bash - conda create -n xeofs python=3.10 poetry + conda create -n xeofs python=3.11 rpy2 pandoc conda activate xeofs - poetry install --with dev,docs + pip install -e .[docs,dev] This will install all necessary dependencies, including those for development and documentation. If you're only updating the code (without modifying online documentation), you can skip the docs dependency: .. code-block:: bash - poetry install --with dev + pip install -e .[dev] On the other hand, if you're just updating documentation: .. code-block:: bash - poetry install --with docs + pip install -e .[docs] Additionally, install the pre-commit hooks: diff --git a/docs/perf/figure_timings.py b/docs/perf/figure_timings.py index e0f0ecc9..3dd4beda 100644 --- a/docs/perf/figure_timings.py +++ b/docs/perf/figure_timings.py @@ -26,11 +26,14 @@ def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False): def __call__(self, value, clip=None): result, is_scalar = self.process_value(value) - x, y = [np.log(self.vmin), np.log(self.midpoint), np.log(self.vmax)], [ - 0, - 0.5, - 1, - ] + x, y = ( + [np.log(self.vmin), np.log(self.midpoint), np.log(self.vmax)], + [ + 0, + 0.5, + 1, + ], + ) return np.ma.array(np.interp(np.log(value), x, y), mask=result.mask, copy=False) diff --git a/docs/perf/xeofs_timings.py b/docs/perf/xeofs_timings.py index 8e8b9796..9898a233 100644 --- a/docs/perf/xeofs_timings.py +++ b/docs/perf/xeofs_timings.py @@ -4,7 +4,6 @@ import xeofs as xe import xarray as xr import dask -import matplotlib.pyplot as plt from tqdm import tqdm import timeit diff --git a/docs/quickstart.ipynb b/docs/quickstart.ipynb index 607276a5..13870615 100644 --- a/docs/quickstart.ipynb +++ b/docs/quickstart.ipynb @@ -26,20 +26,9 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import xarray as xr\n", "import xeofs as xe\n", @@ -57,433 +46,9 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    <xarray.Dataset>\n",
    -       "Dimensions:  (lat: 25, time: 2920, lon: 53)\n",
    -       "Coordinates:\n",
    -       "  * lat      (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n",
    -       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
    -       "  * time     (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n",
    -       "Data variables:\n",
    -       "    air      (time, lat, lon) float32 ...\n",
    -       "Attributes: (5)
    " - ], - "text/plain": [ - "\n", - "Dimensions: (lat: 25, time: 2920, lon: 53)\n", - "Coordinates:\n", - " * lat (lat) float32 75.0 72.5 70.0 67.5 65.0 ... 25.0 22.5 20.0 17.5 15.0\n", - " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", - " * time (time) datetime64[ns] 2013-01-01 ... 2014-12-31T18:00:00\n", - "Data variables:\n", - " air (time, lat, lon) float32 ...\n", - "Attributes: (5)" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "t2m = xr.tutorial.open_dataset('air_temperature')\n", "t2m" @@ -501,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -521,20 +86,9 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "model.fit(t2m, dim='time')" ] @@ -556,394 +110,9 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    <xarray.DataArray 'explained_variance_ratio' (mode: 2)>\n",
    -       "array([0.79683532, 0.0270206 ])\n",
    -       "Coordinates:\n",
    -       "  * mode     (mode) int64 1 2\n",
    -       "Attributes: (13)
    " - ], - "text/plain": [ - "\n", - "array([0.79683532, 0.0270206 ])\n", - "Coordinates:\n", - " * mode (mode) int64 1 2\n", - "Attributes: (13)" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "model.explained_variance_ratio()" ] @@ -965,442 +134,9 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
    \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    <xarray.Dataset>\n",
    -       "Dimensions:  (lat: 25, lon: 53, mode: 2)\n",
    -       "Coordinates:\n",
    -       "  * lat      (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 65.0 67.5 70.0 72.5 75.0\n",
    -       "  * lon      (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n",
    -       "  * mode     (mode) int64 1 2\n",
    -       "Data variables:\n",
    -       "    air      (mode, lat, lon) float64 0.0022 0.002131 ... 0.02168 0.0221
    " - ], - "text/plain": [ - "\n", - "Dimensions: (lat: 25, lon: 53, mode: 2)\n", - "Coordinates:\n", - " * lat (lat) float32 15.0 17.5 20.0 22.5 25.0 ... 65.0 67.5 70.0 72.5 75.0\n", - " * lon (lon) float32 200.0 202.5 205.0 207.5 ... 322.5 325.0 327.5 330.0\n", - " * mode (mode) int64 1 2\n", - "Data variables:\n", - " air (mode, lat, lon) float64 0.0022 0.002131 ... 0.02168 0.0221" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "components = model.components()\n", "components" @@ -1423,30 +159,9 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHFCAYAAAAOmtghAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAABQEklEQVR4nO3df3gU1b0/8PfsJrubQBJ+Z4mEEBAwiIgmFkFpsJUgiFrxKi0qIuIVI1XIl1oBn4dIlViKGC0CighYi9h7UUsVhVgx2gKVnwWRotZIELJGEEggyf483z+42bpkzxnZzTLL7Pv1PPu0zJnP7Dkzs+Mn58zM0YQQAkREREQmYTG6AkREREStickNERERmQqTGyIiIjIVJjdERERkKkxuiIiIyFSY3BAREZGpMLkhIiIiU2FyQ0RERKbC5IaIiIhMhckNkUl99dVX0DQNK1asMLoqYb311lsYP348LrnkEiQnJ0PTNKOrREQmweSGiAzxxhtvYMuWLejXrx8uvfRSo6tDRCaSZHQFiCgxLV26FBbL6b+vpkyZgu3btxtcIyIyC/bcEMVIaWkpNE3D7t27ceuttyIjIwMdOnRASUkJfD4f9u/fj+uuuw5paWno0aMH5s2b12Ib1dXVuOOOO9ClSxfY7Xbk5eXhqaeeQiAQCFnv8OHDuO2225CWloaMjAyMHTsWLpcrbL22bduGG2+8ER06dIDD4cBll12GP/3pTzHZByrNiQ0RUWtjzw1RjN1222244447cN9996GiogLz5s2D1+vFe++9h+LiYkyfPh2rVq3Cr3/9a1x44YUYM2YMAODbb7/FkCFD4PF48Jvf/AY9evTAW2+9henTp+Pf//43Fi1aBABobGzEtddei8OHD6OsrAx9+vTB22+/jbFjx7aoy8aNG3Hddddh0KBBWLJkCTIyMrB69WqMHTsWDQ0NmDBhgrItfr8fQgjdNlssFiYvRGQcQUQxMXv2bAFAPPXUUyHLBw4cKACI119/PbjM6/WKzp07izFjxgSXPfLIIwKA+Mc//hESf//99wtN08T+/fuFEEIsXrxYABB//vOfQ9a79957BQCxfPny4LKLLrpIXHbZZcLr9YasO3r0aNG1a1fh9/uVbcrJyREAdD+zZ8/W3T/f98ADDwhejoiotbDnhijGRo8eHfLvvLw8/POf/8TIkSODy5KSknDhhRfiwIEDwWXvv/8++vXrhx/96Ech8RMmTMDixYvx/vvvo0+fPti4cSPS0tJw4403hqw3btw4LF26NPjvL774Av/6178wf/58AIDP5wuWjRo1Cm+99Rb279+PvLw8aVv+8pe/wO1267Y5KytLdx0iolhhckMUYx06dAj5t81mQ2pqKhwOR4vldXV1wX8fPXoUPXr0aLG95sTh6NGjwf/NzMxssZ7T6Qz59zfffAMAmD59OqZPnx62rkeOHFG2pV+/fj94WIqIyChMbojiVMeOHVFTU9Ni+eHDhwEAnTp1Cq738ccft1jvzBuKm9efMWNG8L6eM/Xt21dZp169eoX0LsnMnj0bpaWluusREcUCkxuiOPXTn/4UZWVl2LFjBy6//PLg8pdffhmapuGaa64BAFxzzTX405/+hLVr14YMTa1atSpke3379kXv3r3xz3/+E3Pnzo2oThyWIqLzAZMbojg1bdo0vPzyy7j++usxZ84c5OTk4O2338aiRYtw//33o0+fPgCA8ePH4+mnn8b48ePxxBNPoHfv3li3bh3Wr1/fYpvPP/88Ro4ciREjRmDChAm44IIL8N1332Hfvn3YsWMH/ud//kdZp0suuaTV2nfgwAFs3boVAPDvf/8bAPC///u/AIAePXqgoKCg1b6LiBILkxuiONW5c2ds2rQJM2bMwIwZM1BXV4eePXti3rx5KCkpCa6XmpqK999/Hw899BAeeeQRaJqGoqIirF69GkOGDAnZ5jXXXIOPP/4YTzzxBKZOnYpjx46hY8eO6NevH2677bZz2r6NGzfi7rvvDll26623AgDuuuuuuJ02gojinyZ+yN2BREREROcJPtJAREREpsLkhoiIiEyFyQ0RERGZCpMbIiIiMhUmN0RERGQqTG6IiIjIVEz/nptAIIDDhw8jLS0NmqYZXR0iIopjQgjU19cjKysrpnOkNTU1wePxRL0dm83WYp46SoDk5vDhw8jOzja6GkREdB45ePAgunXrFpNtNzU1ITenLVy1/qi35XQ6UVVVxQTnDKZPbtLS0gAAeSsehDXV3qrbtmjq9x8maQF5mVV9Uidb5OXJOrFJFvn3WvXqrIhVted0rLxedotXGZti9UnLbBZ52elty8uTtegvHrFgVexLDepjpIrV4xfyv0R9wqqMbQzYpGUev/pSctKfLC1zB+RlANCkiG30qb/3lFde5yaf+nsb3fJyj1v9vX6PorxJfgw0j7qnQAsoep/1TgtVx7VFfc6pSoVV5z2wqibpdaarrlc6sULRJk1Rp0BjEw5NLwv+tyMWPB4PXLV+HNjeA+lpkfcO1dUHkJP/FTweD5ObM5g+uWkeirKm2s95cmNVJQq6CYq8XD82mgQlNsmNzaq+EqnK7RZ1rKo8WXUVM5AqQbEYlNx4dZKbgCoJ0UlubH55khFQJC8A4FeUe3USlCRFcmP1qmOtVnm5RVEGAMKq2B+Kc1Kz6iQ3foOSG0Ws2ZKb4Drn4DaGtmka2qZF/j0B3R2YuEyf3BAREcUjvwjAH8UESH4R+R86ZsfkhoiIyAABCAR0emr14im8+OyzJyIiIooQe26IiIgMEEBA91YpvXgKj8kNERGRAfxCwC8iH1qKJtbsOCxFREREpsKeGyIiIgPwhuLYYXJDRERkgAAE/ExuYoLDUkRERGQq7LkhIiIyAIelYofJDRERkQH4tFTscFiKiIiITCVhem78fgvgD5/LaYrJ2SyqydeimDjTppgF+3S5YhJKxQSVQAwnv9T53hSrR1qWntSkjG1rdUvL0qzqWNWM4zZNvZ+joZrgUm9yS4cmr3OqRb4v9GL1qCbaaxLySSYBoEkxcWaT0Jn8UjFhZywn//MI+SVOb6LQk375LMtHvG2VsYcb20nLDp1Kl5bVnlDPRO0+Lp/811qnvpwnNcj3s3JCTh06k7ojYJP/TlRlAKA6rYRV5wV2qsk+FaHncrqmAPTnO9WLp/ASJrkhIiKKJ/4on5aKJtbsmNwQEREZwC8Q5azgrVcXs+E9N0RERGQq7LkhIiIyAO+5iR0mN0RERAYIQIM/ihvqY3kz/vmOw1JERERkKuy5ISIiMkBAnP5EE0/hMbkhIiIygD/KYaloYs2Ow1JERERkKuy5ISIiMgB7bmKHyQ0REZEBAkJDQETxtFQUsWbHYSkiIiIyFfbcEBERGYDDUrHDnhsiIiID+GGJ+hOJRYsWITc3Fw6HA/n5+fjoo4+U61dWViI/Px8OhwM9e/bEkiVLQspXrFgBTdNafJqamiKqX2tImJ6bNEcTklLCvxQgNdkjjUtN8krL2ia71d+ZJD+w6YoyAGhrlW/bYZHXCQCSNb+0zK4T69Dk5W0sOu21NspjNfk+1vtei6Z+mYM1ipeQqy4OsRzPVh2jZE3dHlsU7fUo2tsk1JeDhoAt4liPorxJJCtjmwLy8vpAijLWrYjV+6u3rVX+G82wNihju9jq5LHJneV1Cqj/Y1VzSt4endMGqp++4nQEACh2IwLJ6t+n364ot+lUOkkRq/OOF80nP76aW7GfG63qDbciEeU9NyKC2Ndeew1Tp07FokWLcNVVV+H555/HyJEj8emnn6J79+4t1q+qqsKoUaNw77334pVXXsHf//53FBcXo3PnzrjllluC66Wnp2P//v0hsQ6H4+wb1UoSJrkhIiJKdAsWLMA999yDSZMmAQDKy8uxfv16LF68GGVlZS3WX7JkCbp3747y8nIAQF5eHrZt24b58+eHJDeapsHpdJ6TNvwQHJYiIiIyQPM9N9F8AKCuri7k43aH72X3eDzYvn07ioqKQpYXFRVh06ZNYWM2b97cYv0RI0Zg27Zt8Hr/0x148uRJ5OTkoFu3bhg9ejR27twZza6JmqHJTY8ePcKO0z3wwAMAACEESktLkZWVhZSUFAwbNgx79+41sspEREStwi8sUX8AIDs7GxkZGcFPuB4YADhy5Aj8fj8yMzNDlmdmZsLlcoWNcblcYdf3+Xw4cuQIAOCiiy7CihUrsHbtWrz66qtwOBy46qqr8Pnnn0e7iyJm6LDU1q1b4ff/Z7D3k08+wfDhw3HrrbcCAObNm4cFCxZgxYoV6NOnDx5//HEMHz4c+/fvR1pamlHVJiIiihsHDx5Eenp68N92u125vqaF3qsjhGixTG/97y+/8sorceWVVwbLr7rqKlx++eX4/e9/j2efffaHNaKVGZrcdO4cemPdk08+iV69eqGwsBBCCJSXl2PWrFkYM2YMAGDlypXIzMzEqlWrcN999xlRZSIiolYRgIZAFAMogf+7qzo9PT0kuZHp1KkTrFZri16a2traFr0zzZxOZ9j1k5KS0LFjx7AxFosFV1xxhaE9N3Fzz43H48Err7yCiRMnQtM0VFVVweVyhYz12e12FBYWSscGAcDtdrcYfyQiIoo3rXXPzQ9ls9mQn5+PioqKkOUVFRUYMmRI2JjBgwe3WH/Dhg0oKChAcnL4x+iEENi1axe6du16VvVrTXGT3Lz55ps4fvw4JkyYAADBTPFsxgYBoKysLGTsMTs7O2Z1JiIiOp+UlJTgxRdfxEsvvYR9+/Zh2rRpqK6uxuTJkwEAM2bMwPjx44PrT548GQcOHEBJSQn27duHl156CcuWLcP06dOD6zz22GNYv349vvzyS+zatQv33HMPdu3aFdymEeLmUfBly5Zh5MiRyMrKCll+tmODM2bMQElJSfDfdXV1THCIiCjufP+m4MjidV72E8bYsWNx9OhRzJkzBzU1Nejfvz/WrVuHnJwcAEBNTQ2qq6uD6+fm5mLdunWYNm0annvuOWRlZeHZZ58NeQz8+PHj+O///m+4XC5kZGTgsssuw4cffogf/ehHEbctWnGR3Bw4cADvvfceXn/99eCy5uflXS5XSNeWamwQOD10pXczFRERkdFO33MTxcSZEcYWFxejuLg4bNmKFStaLCssLMSOHTuk23v66afx9NNPR1SXWImLYanly5ejS5cuuP7664PLcnNz4XQ6Q8b6PB4PKisrpWODRERERIb33AQCASxfvhx33XUXkpL+Ux1N0zB16lTMnTsXvXv3Ru/evTF37lykpqZi3LhxBtaYiIgoeoEo5oc6HX/2w1KJwvDk5r333kN1dTUmTpzYouzhhx9GY2MjiouLcezYMQwaNAgbNmzgO26IiOi8Z8Q9N4nC8OSmqKgo+EKgM2mahtLSUpSWlp7bShEREcVYAJZWec8NtWR4cnOuBBSzrzb65FPeev3yGWKb/Ord1yR5BwAA+IR65lmvojzVop5h227xSct034ug+J21gXpW8FjRm/VbNYt2G53pjh2KJ++SFWUA4FX81dSk8xeVN4qZgJMVs6Sn6tRZ1V6Lzn4OQD7re4NQ7+ejitmuD/vULx/7VlH+ZVMXZew3TfJeXr2bMTsky2f+dtpPKGMtinNS9b0nm9QPQ1iOy68p9qPq9iguC/C2VYbC007eHtFWfexVPwXLKfV1MLlOft4kn1SGIkkxcXuS/FSG32NBtbyYzhMJk9wQERHFE7/Q4I/iD51oYs2OyQ0REZEB/FHeUOznsJRUXDwKTkRERNRa2HNDRERkgICwIBDF01IBPi0lxeSGiIjIAByWih0OSxEREZGpsOeGiIjIAAFE98ST+uUNiY3JDRERkQGif4kfB19kuGeIiIjIVNhzQ0REZIDo55Zi/4QMkxsiIiIDBKDpTgOiF0/hMbkhIiIyAHtuYod7hoiIiEyFPTdEREQGiP4lfuyfkEmY5ObYqRRYhSNsmVC8Z8Dvi/zksVrlbyFITvYrYx02rzzWon67gabJ31pp1YlNSZJ/b7rNrYztbK+Xl9lOKmMzk09Iy7Jt3yljs5KOS8vaWdT7OcOSLC1LglUZ64ZPWmZRlAFAg+LNot4o3nuRrKnP1xRN3t5kTX058Ap5mxqEej83BOTfe9zfRhl7wp8i365fvl0AaFKUN/nV7fUoyhsV7QEAb0B+7nx2vLO0rN7VVrndtl/Lj6/jqPpttQGb/LzypilDIeyK64biegMA1uPyfZV2QH2upx+Qn1eOb9XXI0uT/Fqm4vOrt9uaAkJDIJr33HBWcCmmfURERGQqCdNzQ0REFE8CUQ5L8SV+ckxuiIiIDBD9rOBMbmS4Z4iIiMhU2HNDRERkAD80+KN4EV80sWbH5IaIiMgAHJaKHe4ZIiIiMhX23BARERnAj+iGltRvl0psTG6IiIgMwGGp2GFyQ0REZABOnBk73DNERERkKuy5ISIiMoCAhkAU99wIPgouxeSGiIjIAByWih3uGSIiIjKVhOm58TYmw68lhy8U8riAxyot0xrlZQAgvPIuQ7/OM3yqTYskRYUBCFtAXqgqA2Cxyytms/uUsW1S2kvLOqWeUsbmtDkmLfO3Vefg7SwN8liLWxnrFfL90aTzoGVAdeLoSLPI22SJoqtZr05HA03SsiahF2uXlh32dVHGHvLKz40j3jRlrDsgv0ylWr3K2PY2+bnxrbutMvbwqXRp2affZipjG0/ZpGXiqHw/tjmsPtfbuOTHyH5Cfb76bfJtC039vdZG+THQdH4GjqPysrZfq4+fo1Z+/CwNHmWs0BS/I6u8TPOrr3OtKSA0BEQUv/coYs0uYZIbIiKieOKPclbwaGLNjnuGiIiITIU9N0RERAbgsFTsMLkhIiIyQAAWBKIYQIkm1uy4Z4iIiMhU2HNDRERkAL/Q4I9iaCmaWLNjckNERGQA3nMTO0xuiIiIDCCinBVc8A3FUtwzREREZCrsuSEiIjKAHxr8UbyRPJpYs2NyQ0REZICAiO6+mUDkM8CYHoeliIiIyFTYc0NERGSAQJQ3FEcTa3ZMboiIiAwQgIZAFPfNRBNrdgmT3FhrHLA4HGcdZ2uSl9mPqWMd38kHRG31AWWsphhM9dvV2bo7XX5YPRnKUGW5J109wNvYJkVadrxtG2XskQx5+Sm/TRmr5KhWFjdYT0W8adXNfFad2FRNfvwdWuQXrAahPkZHA3Zp2WFfO2XsIW97eZlbXgYA33rSpGV6x9dm8UnL2iU3KmM72+qlZSlWjzJWdS/ESbe6zgGv/AxIalKcN27lZmHxyY+vxaM+9kkNXmlZcr36nBMWebmqTqe/V378LG552ekvlm87kJKsjlXQfIrrbxS/P4ofCZPcEBERxRO+oTh2mNwQEREZgPfcxI7he+bQoUO444470LFjR6SmpmLgwIHYvn17sFwIgdLSUmRlZSElJQXDhg3D3r17DawxERERxTNDk5tjx47hqquuQnJyMt555x18+umneOqpp9CuXbvgOvPmzcOCBQuwcOFCbN26FU6nE8OHD0d9vXwsnYiIKN4FoAXnl4rowxuKpQwdlvrtb3+L7OxsLF++PLisR48ewf8vhEB5eTlmzZqFMWPGAABWrlyJzMxMrFq1Cvfdd9+5rjIREVGrEFE+LSWY3EgZ2nOzdu1aFBQU4NZbb0WXLl1w2WWXYenSpcHyqqoquFwuFBUVBZfZ7XYUFhZi06ZNYbfpdrtRV1cX8iEiIoo3UfXaRDmjuNkZmtx8+eWXWLx4MXr37o3169dj8uTJePDBB/Hyyy8DAFwuFwAgMzMzJC4zMzNYdqaysjJkZGQEP9nZ2bFtBBEREcUVQ5ObQCCAyy+/HHPnzsVll12G++67D/feey8WL14csp52xnsHhBAtljWbMWMGTpw4EfwcPHgwZvUnIiKKVPPTUtF8IrFo0SLk5ubC4XAgPz8fH330kXL9yspK5Ofnw+FwoGfPnliyZIl03dWrV0PTNPzsZz+LqG6txdDkpmvXrujXr1/Isry8PFRXn37xmtPpBIAWvTS1tbUtenOa2e12pKenh3yIiIjijRHDUq+99hqmTp2KWbNmYefOnRg6dChGjhwZ/O/umaqqqjBq1CgMHToUO3fuxMyZM/Hggw9izZo1LdY9cOAApk+fjqFDh551vVqbocnNVVddhf3794cs++yzz5CTkwMAyM3NhdPpREVFRbDc4/GgsrISQ4YMOad1JSIiOt8tWLAA99xzDyZNmoS8vDyUl5cjOzu7xYhJsyVLlqB79+4oLy9HXl4eJk2ahIkTJ2L+/Pkh6/n9ftx+++147LHH0LNnz3PRFCVDk5tp06Zhy5YtmDt3Lr744gusWrUKL7zwAh544AEAp4ejpk6dirlz5+KNN97AJ598ggkTJiA1NRXjxo0zsupERERRaZ5bKprP2fB4PNi+fXvIQzoAUFRUJH1IZ/PmzS3WHzFiBLZt2wav9z9TesyZMwedO3fGPffcc1Z1ihVDHwW/4oor8MYbb2DGjBmYM2cOcnNzUV5ejttvvz24zsMPP4zGxkYUFxfj2LFjGDRoEDZs2IC0NPlcNURERPEu2ieemmPPfCrYbrfDbm85j9yRI0fg9/vP6iEdl8sVdn2fz4cjR46ga9eu+Pvf/45ly5Zh165dEbeltRk+/cLo0aMxevRoabmmaSgtLUVpaem5qxQREdF54syngmfPnq38b+bZPKQjW795eX19Pe644w4sXboUnTp1Osuax47hyQ0REVEiaq2em4MHD4Y8PBOu1wYAOnXqBKvVelYP6TidzrDrJyUloWPHjti7dy+++uor3HDDDf+pV+D0rOtJSUnYv38/evXqdfaNi1LCJDftPhOw2kTYMtXTdBavvMxWH1B+p63eJy2zNsjLAEALhK8rAAir+laplG/l5d626kPubmeVljV2Uv8ImzrIt+3poI79zicv3+1V1/k7d6q07Mu0zsrYninfSsuyko8pYztaT0rL2mgeZaxfcWIF4FfGplnkxzdDU58bFrilZfWWRmUs0F5a4hbJyshTfpu07Lg7Red75TwB9bnRySY/RskW9e+3a8oJaZnNoj5Gh+3y4384qZ20rNHnUG7X2iQ/vqprFQAkNcjLLD759eb098rba/Go96Pml5cLq85/2DX59UgLqL8XfkWbFL0UyrJW1lrJzQ99MthmsyE/Px8VFRW4+eabg8srKipw0003hY0ZPHgw/vKXv4Qs27BhAwoKCpCcnIyLLroIe/bsCSl/9NFHUV9fj2eeecawd80lTHJDRESU6EpKSnDnnXeioKAAgwcPxgsvvIDq6mpMnjwZwOl3xR06dCj4Mt3Jkydj4cKFKCkpwb333ovNmzdj2bJlePXVVwEADocD/fv3D/mO5vkhz1x+LjG5ISIiMkBr9dycjbFjx+Lo0aOYM2cOampq0L9/f6xbty74CpaampqQd97k5uZi3bp1mDZtGp577jlkZWXh2WefxS233BJxvc8FJjdEREQGEECUE2dGpri4GMXFxWHLVqxY0WJZYWEhduzY8YO3H24b5xqTGyIiIgMY0XOTKAx9iR8RERFRa2PPDRERkQHYcxM7TG6IiIgMwOQmdjgsRURERKbCnhsiIiIDsOcmdpjcEBERGUAIDSKKBCWaWLPjsBQRERGZCntuiIiIDBCAFtVL/KKJNTsmN0RERAbgPTexkzDJTdtDHiQlRTAKp5h4VjXbLQBoindjB5LVdVHFQqhfum1xy2fwtSvKACC5Xj4Lr61ePfNzUqM8tsEvLwMAj1e+P+pPqb/30yNtpGX7UzKVse0y5FMl92p3VBk7MOOgtCzPcUgZ29laLy3zWnRmFId8Rvl2Oqd4mkV+HHok1SljkxWzlXfWiT1sl88ofsgtLwOAOsVM2cma+jeomvm7wa8+r+oV3+uwqqfg7tOuVlrWJVU+U/m/Ursot3siJU1a5ktVH3zHUfl/CG0ndWYFd8v3o96s4BavfNsWn8411Kso15kUXHnTheIaKiy8W8MMEia5ISIiiie8oTh2mNwQEREZgMNSscPkhoiIyADsuYkdDi4SERGRqbDnhoiIyAAiymEp9tzIMbkhIiIygIDuw6+68RQeh6WIiIjIVNhzQ0REZIAANGh8Q3FMMLkhIiIyAJ+Wih0OSxEREZGpsOeGiIjIAAGhQeNL/GKCyQ0REZEBhIjyaSk+LiXFYSkiIiIyFfbcEBERGYA3FMdOwiQ31gYfrEm+s47TAop+P3/kfYKaXn9iIKAIVp/QwqLokNPpq0s66ZeWWRu9ylhrk0NapvmSlbGaT94mb7q60gGbvDzQpI79zm2VljW61XU+6bNJy+rbyfcFAPRxuKRl7aynlLFtLG5pWZqlSRnr0OS/gSYhb8/pcvn+UNUJALKSj0nLrFCc6wCOWNOkZX4Reeez26++/KnuZ/AE1LGqo5+a5JGWOTPqlNs9mCU/X0+JVGUsAvL2WNU/bWh+1TVH5xhokV8nlVtW1gmA6tqtuL6ey4SByU3sJExyQ0REFE94Q3Hs8J4bIiIiMhX23BARERmAT0vFDpMbIiIiA5xObqK556YVK2MyHJYiIiIiU2HPDRERkQH4tFTsMLkhIiIygPi/TzTxFB6HpYiIiMhU2HNDRERkAA5LxQ6TGyIiIiNwXCpmmNwQEREZIcqeG7DnRor33BAREZGpsOeGiIjIAHxDcewwuSEiIjIAbyiOnYRJbixePywB/9kHqlLjaNLmgLpYU25b53utqjrrjEQqvtfS6FOG2n3yRmmBFPX3wiYtOWVR/4A97RXt1fnti4B8haYGeZ0AoNrSXlqmN1vvqTS7tCwn5YgytoP1lLSsjcWtjLVo8mN0wp+qjK1q6iwtO+ZTxyZr8t9eW6u6zip1PvV5VedzSMua/MnKWE/AqohVXzoP1MnPje/q5PvK16CuE7zy369F9bsH4E+Vn5NeRRkAaIrfifAoQ9Xb9au/V/X71N12gN0aiSxhkhsiIqK4IrTobgpmz40UkxsiIiID8J6b2DH0aanS0lJomhbycTqdwXIhBEpLS5GVlYWUlBQMGzYMe/fuNbDGREREFO8MfxT84osvRk1NTfCzZ8+eYNm8efOwYMECLFy4EFu3boXT6cTw4cNRX19vYI2JiIhagWiFD4Vl+LBUUlJSSG9NMyEEysvLMWvWLIwZMwYAsHLlSmRmZmLVqlW47777znVViYiIWg2floodw3tuPv/8c2RlZSE3Nxc///nP8eWXXwIAqqqq4HK5UFRUFFzXbrejsLAQmzZtkm7P7Xajrq4u5ENERESJw9DkZtCgQXj55Zexfv16LF26FC6XC0OGDMHRo0fhcrkAAJmZmSExmZmZwbJwysrKkJGREfxkZ2fHtA1EREQR45BUTBg6LDVy5Mjg/7/kkkswePBg9OrVCytXrsSVV14JANC00G43IUSLZd83Y8YMlJSUBP9dV1fHBIeIiOIOh6Vix/Bhqe9r06YNLrnkEnz++efB+3DO7KWpra1t0ZvzfXa7Henp6SEfIiKiuMMbimMmrpIbt9uNffv2oWvXrsjNzYXT6URFRUWw3OPxoLKyEkOGDDGwlkRERBTPDB2Wmj59Om644QZ0794dtbW1ePzxx1FXV4e77roLmqZh6tSpmDt3Lnr37o3evXtj7ty5SE1Nxbhx44ysNhERUSvQoDtHjG48hWNocvP111/jF7/4BY4cOYLOnTvjyiuvxJYtW5CTkwMAePjhh9HY2Iji4mIcO3YMgwYNwoYNG5CWlmZktYmIiKIX7dASh6WkDE1uVq9erSzXNA2lpaUoLS09NxUiIiKi857hL/EjIiJKSOy5iZnESW58AhCBsEWaavaxWM1MFsMZz7Twzfw/fmWssFrlZRb1/eeWBo+0zN7oVcamQ/5Umy/Vpoz1p8jHnUWSzpi0XxHrV7e3qSlZWvb18XbKWI9fvp/rfA5lbGf7SWlZW2uTMtZukR+HBr9dGfvZSflTil+e6KCMVT2y2rWt+kWb7eyN0rIGn/rcOO5W70sVR5JPWuYLqM+NRo/83PAdk9cp+Tv5eQHo/LZ1LimavDm6k0sLi3wF5fUTgOaXl+vFxup2FNW1TO8616o4K3jMxNXTUkRERETRSpyeGyIiojgiRHSd+DEcADjvseeGiIjICAa9xG/RokXIzc2Fw+FAfn4+PvroI+X6lZWVyM/Ph8PhQM+ePbFkyZKQ8tdffx0FBQVo164d2rRpg4EDB+IPf/hDZJVrJUxuiIiIEsRrr72GqVOnYtasWdi5cyeGDh2KkSNHorq6Ouz6VVVVGDVqFIYOHYqdO3di5syZePDBB7FmzZrgOh06dMCsWbOwefNm7N69G3fffTfuvvturF+//lw1qwUmN0REREZovqE4ms9ZWrBgAe655x5MmjQJeXl5KC8vR3Z2NhYvXhx2/SVLlqB79+4oLy9HXl4eJk2ahIkTJ2L+/PnBdYYNG4abb74ZeXl56NWrFx566CEMGDAAf/vb3yLeNdFickNERGQATUT/AU5PEP39j9vtDvt9Ho8H27dvR1FRUcjyoqIibNq0KWzM5s2bW6w/YsQIbNu2DV5vy6cvhRD461//iv379+PHP/5xBHuldTC5ISIiMkIr3XOTnZ2NjIyM4KesrCzs1x05cgR+v7/F5NOZmZktJqlu5nK5wq7v8/lw5MiR4LITJ06gbdu2sNlsuP766/H73/8ew4cPP4ud0br4tBQREdF57ODBg0hP/8+7wux29TurNC10OEsI0WKZ3vpnLk9LS8OuXbtw8uRJ/PWvf0VJSQl69uyJYcOG/dBmtComN0REREZopZf4paenhyQ3Mp06dYLVam3RS1NbW9uid6aZ0+kMu35SUhI6duwYXGaxWHDhhRcCAAYOHIh9+/ahrKzMsOSGw1JERERGOMePgttsNuTn56OioiJkeUVFBYYMGRI2ZvDgwS3W37BhAwoKCpCcLH8TtxBCeu/PucCeGyIiogRRUlKCO++8EwUFBRg8eDBeeOEFVFdXY/LkyQCAGTNm4NChQ3j55ZcBAJMnT8bChQtRUlKCe++9F5s3b8ayZcvw6quvBrdZVlaGgoIC9OrVCx6PB+vWrcPLL78sfQLrXGByQ0REZAQDJs4cO3Ysjh49ijlz5qCmpgb9+/fHunXrkJOTAwCoqakJeedNbm4u1q1bh2nTpuG5555DVlYWnn32Wdxyyy3BdU6dOoXi4mJ8/fXXSElJwUUXXYRXXnkFY8eOjaJx0WFyQ0REZASDZgUvLi5GcXFx2LIVK1a0WFZYWIgdO3ZIt/f444/j8ccfj6wyMcJ7boiIiMgQfr8flZWVOHbsWKtuN3F6bqza6U8Y6snHIr+TXfMrNhzNjGeWKHJSv19ZrCnqJST77z/bDsi36/UpQy0eeazeIQgkKeqsEyus8lhrss6+0uSxbrf6p+UKyJ9s8AasytiTqfLHPNsmqW/gS7F6pGXJmuIYALAo2mvR+ROyvkle52pfe2VsTZL+UyAyqmMkdE4Ol1t+s6RHUQYAvgb58U86Jf/9Jp9SbhbWRnmZRX26wiI/9LB61cdPC0RzvZLvZ6EoA3SuoTpU1yvlqa5Tp1bVSk9Lnc+sVitGjBiBffv2oX179bXgbET0X8mJEyeivr6+xfJTp05h4sSJUVeKiIjI7FrrDcXnu0suuQRffvllq24zouRm5cqVaGxs+SdEY2Nj8A5rIiIiIj1PPPEEpk+fjrfeegs1NTUtppOIxFkNS9XV1UEIASEE6uvr4XA4gmV+vx/r1q1Dly5dIqoIERFRQjHohuJ4c9111wEAbrzxxpC3Hje/OdmvcztFOGeV3LRr1w6apkHTNPTp06dFuaZpeOyxx866EkRERJSYNm7c2OrbPKvkZuPGjRBC4Cc/+QnWrFmDDh06BMtsNhtycnKQlZXV6pUkIiIyGw3R3Tdz/t9OfFphYWGrb/OskpvmClRVVSE7OxuWaJ7aISIiooS0e/du9O/fHxaLBbt371auO2DAgLPefkSPgje/ybChoQHV1dXweEKfMYykIkRERAklgR8FHzhwIFwuF7p06YKBAwdC07TgbOPfd07uuWn27bff4u6778Y777wTtjySihARESWUBL6huKqqCp07dw7+/9YWUXIzdepUHDt2DFu2bME111yDN954A9988w0ef/xxPPXUU61dRyIiIjKR5hGg7///Tz/9tMVokKZpIev+UBElN++//z7+/Oc/44orroDFYkFOTg6GDx+O9PR0lJWV4frrr49ks0RERIkjgXtuvu/LL7/EzTffjD179oQMTzU/Fh7JaFBEdwSfOnUq+D6bDh064NtvvwVw+i2Dqsm1iIiI6DS+ofi0hx56CLm5ufjmm2+QmpqKTz75BB9++CEKCgrwwQcfRLTNiJKbvn37Yv/+/QBO3xT0/PPP49ChQ1iyZAm6du0aUUWIiIgo8WzevBlz5sxB586dYbFYYLVacfXVV6OsrAwPPvhgRNuM+J6bmpoaAMDs2bMxYsQIvPLKK7DZbFi5cmVEFSEiIkooHJYCcHrYqW3btgCATp064fDhw+jbty9ycnKCHSlnK6Lk5vbbbw/+/8suuwxfffUV/vWvf6F79+7o1KlTRBWJNWHRICJ4L49qlmy9mb1FkuoxPZ26KGbDVdYpSppHPnu37kOHqpm/hXrGadW+8jmkRQAAf4pi5meHzszeihnFNUvk+zngVx9ft09eXhtIU8b6A/LYdg7FtNEAknRm/lYJKB47TbF5lbGqmc7dHvVlSK9cSXHSek7alKFJLnl5yhH11yomX4emOCUt6t0Ii09xvuocWlW5arsAYPEoZoTXm1FcWWed31g0L7hTtFfzywtVZa2OyQ0AoH///ti9ezd69uyJQYMGYd68ebDZbHjhhRfQs2fPiLb5g68aJSUlP3ijCxYsiKgyRERElFgeffRRnDp1CgDw+OOPY/To0Rg6dCg6duyI1157LaJt/uDkZufOnT9ove9PekVEREThRXtTsFluKB4xYkTw//fs2ROffvopvvvuO7Rv3z7inOIHJzexmNiKiIgoYSXwG4r1fH/uykhEMZhNREREEeM9NzHDmS+JiIjIVNhzQ0REZADecxM7TG6IiIiMwGGpmOGwFBEREZkKe26IiIiMEO38UOy5kWJyQ0REZAQOS8UMh6WIiIjIVNhzQ0REZAT23MQMkxsiIiID8FHw2OGwFBEREZlKwvTciCQLRNLZ53JCkRlrgYA6WKdYRRN+eaFXZ8OqSuvVya9YQbVdAPD55GWNTcpQW+0paZn9hF0Z29BNXqbZFfsRgGaRt0kE1PO2CMW8LgG/zrmmiPXqfO9xS4q0zB+I/O8VfxTz1DR5kpXlbrf8UuP3WtUbV5x2escITfJt275VX/5SvpWXJderfwtWr7zM4pXHaurTVfmXuuZX18miKNcUddKNDahjlfXSi1WU67VXGeuTX+c01TWQzhsJk9wQERHFFd5zEzNMboiIiAzAe25iJ27uuSkrK4OmaZg6dWpwmRACpaWlyMrKQkpKCoYNG4a9e/caV0kiIiKKe3GR3GzduhUvvPACBgwYELJ83rx5WLBgARYuXIitW7fC6XRi+PDhqK+vN6imRERErUhE8SEpw5ObkydP4vbbb8fSpUvRvn374HIhBMrLyzFr1iyMGTMG/fv3x8qVK9HQ0IBVq1YZWGMiIqJWEE1iwwRHyfDk5oEHHsD111+Pa6+9NmR5VVUVXC4XioqKgsvsdjsKCwuxadMm6fbcbjfq6upCPkRERJQ4DL2hePXq1dixYwe2bt3aoszlcgEAMjMzQ5ZnZmbiwIED0m2WlZXhsccea92KEhERtTLeUBw7hvXcHDx4EA899BBeeeUVOBwO6XqaFvoeCyFEi2XfN2PGDJw4cSL4OXjwYKvVmYiIqNVwWCpmDOu52b59O2pra5Gfnx9c5vf78eGHH2LhwoXYv38/gNM9OF27dg2uU1tb26I35/vsdjvsdvVL34iIiMi8DOu5+elPf4o9e/Zg165dwU9BQQFuv/127Nq1Cz179oTT6URFRUUwxuPxoLKyEkOGDDGq2kRERK2ieVgqmg+FZ1jPTVpaGvr37x+yrE2bNujYsWNw+dSpUzF37lz07t0bvXv3xty5c5Gamopx48YZUWUiIqLWwzcUx0xcv6H44YcfRmNjI4qLi3Hs2DEMGjQIGzZsQFpamtFVIyIiojgVV8nNBx98EPJvTdNQWlqK0tJSQ+pDREQUM+y5iZm4Sm6IiIgSBR8Fj52ESW6EVYOwhn+EXFPNcC9/6hxCU9+PrQXkG1aVAQB0ipXf61ec8X6dDXs88jIR+S8p0NioXuHf1dKi9u1TlKHuDHn5Kc2mrleKX1qmWSJvrwgoThwdOlVGQMi3fbJJHez1yn/yAb/6fBaKUyfgtSpj0aQo19vNVtX5rN7PtqPy7011qb/WVif/XuU1A4DVLY9NapIHW7zqnaH6bVu86kppAcW2dX7bqvYKncdSlPtKVSfoXEO98t8uoN5XQvE6Eaiun62NPTcxY/gbiomIiIhaU8L03BAREcUV9tzEDJMbIiIiA/Cem9jhsBQRERGZCntuiIiIjMBhqZhhckNERGQADkvFDoeliIiIyFTYc0NERGQEDkvFDJMbIiIiIzC5iRkOSxEREZGpsOeGiIjIABqUM/z8oHgKjz03RERERhCt8InAokWLkJubC4fDgfz8fHz00UfK9SsrK5Gfnw+Hw4GePXtiyZIlIeVLly7F0KFD0b59e7Rv3x7XXnstPv7448gq10qY3BARERmg+VHwaD5n67XXXsPUqVMxa9Ys7Ny5E0OHDsXIkSNRXR1+8uKqqiqMGjUKQ4cOxc6dOzFz5kw8+OCDWLNmTXCdDz74AL/4xS+wceNGbN68Gd27d0dRUREOHToU6a6JGpMbIiKiBLFgwQLcc889mDRpEvLy8lBeXo7s7GwsXrw47PpLlixB9+7dUV5ejry8PEyaNAkTJ07E/Pnzg+v88Y9/RHFxMQYOHIiLLroIS5cuRSAQwF//+tdz1awWEueeG007/QlDWOTpr+ZXlAXUabMWCMjLvH5lLFSxHp1Yv6Jcp87wqWLldQIg3b8AoNlsylD/iTppmW3fQWWs09JdWvZdnUMZ29BVnt9709X7SnXe6P7ZYJXH6uxleKIYaA+4rdIyzaOutOaVf7EloFMpRaM0vdPKJ992UqM61nFUXpZyRP3FtpOK36BP57evuG5YvIrvFXrXFNX1SBmq3LbetQyq66DO16qug3rtVW7Xp9Ng1TVUda1SXT9bWys9LVVXF3r9tNvtsNvtLVb3eDzYvn07HnnkkZDlRUVF2LRpU9iv2Lx5M4qKikKWjRgxAsuWLYPX60VycnKLmIaGBni9XnTo0OFsWtOq2HNDRERklFa43yY7OxsZGRnBT1lZWdivOnLkCPx+PzIzM0OWZ2ZmwuVyhY1xuVxh1/f5fDhy5EjYmEceeQQXXHABrr32WmXTYylxem6IiIhM6ODBg0hPTw/+O1yvzfed2XMlhFD3ZoVZP9xyAJg3bx5effVVfPDBB3A41D3nscTkhoiIyACtNbdUenp6SHIj06lTJ1it1ha9NLW1tS16Z5o5nc6w6yclJaFjx44hy+fPn4+5c+fivffew4ABA86iJa2Pw1JERERGOMePgttsNuTn56OioiJkeUVFBYYMGRI2ZvDgwS3W37BhAwoKCkLut/nd736H3/zmN3j33XdRUFBwdhWLASY3RERECaKkpAQvvvgiXnrpJezbtw/Tpk1DdXU1Jk+eDACYMWMGxo8fH1x/8uTJOHDgAEpKSrBv3z689NJLWLZsGaZPnx5cZ968eXj00Ufx0ksvoUePHnC5XHC5XDh58uQ5b18zDksREREZoLWGpc7G2LFjcfToUcyZMwc1NTXo378/1q1bh5ycHABATU1NyDtvcnNzsW7dOkybNg3PPfccsrKy8Oyzz+KWW24JrrNo0SJ4PB7813/9V8h3zZ49G6WlpRG1LVpMboiIiIxg0MSZxcXFKC4uDlu2YsWKFssKCwuxY8cO6fa++uqryCoSQxyWIiIiIlNhzw0REZEBjBiWShRMboiIiIxg0LBUImByQ0REZAQmNzHDe26IiIjIVNhzQ0REZADecxM7CZPcaH4BTXYmqGbLVczgqzd7rHJGcb1Zwb0+eZlPUQaoZ/bWo5qlV2+2XFWsRT13sMUhnwvF9234ydmaJW9rkpZ1auqljP3W0kZeKHTmO1bMxSJ0+kQDLSfS/U9skjo4kCyf2Vskqa92Fr9i/hjFrN8AYHUrYnVOSdVF2Kozs7f9hKpM3d7kk/Jz1urW2VeKWadVv20AgGKWbYtiRnHNrzPTteqaojfDtvK3rTMbuSJWKH4HerGqmbt1RVFn1XiO7jFoTRyWihkOSxEREZGpJEzPDRERUTzRhNDvcdOJp/CY3BARERmBw1Ixw2EpIiIiMhX23BARERmAT0vFDpMbIiIiI3BYKmY4LEVERESmwp4bIiIiA3BYKnaY3BARERmBw1Ixw+SGiIjIAOy5iR3ec0NERESmwp4bIiIiI3BYKmaY3BARERmEQ0uxwWEpIiIiMpWE6bmxNHhhsYbP5ZSTjwUC0iLNJy8DAPj88jKPJ/JYPT6ftEgoyqIWiGICOJtNWmbR2a7/5ElpWVJ1rTI2rUu2fLs29c8jkCwv03RODeV2bZqy3JeiKFeHIqlRXmZtUsdqilNSr72q8qQG9fFNOSr/Ylud+nzW/PJtq8oAAIrrgqZ3riu/V96eaOqkLNMr1zt+qn2hDlXTq7M/ih+SiuK6joA3Nt8ZjhD6+0AvnsJKmOSGiIgonvBpqdjhsBQRERGZiqHJzeLFizFgwACkp6cjPT0dgwcPxjvvvBMsF0KgtLQUWVlZSElJwbBhw7B3714Da0xERNRKRCt8KCxDk5tu3brhySefxLZt27Bt2zb85Cc/wU033RRMYObNm4cFCxZg4cKF2Lp1K5xOJ4YPH476+nojq01ERBQ1LRD9h8IzNLm54YYbMGrUKPTp0wd9+vTBE088gbZt22LLli0QQqC8vByzZs3CmDFj0L9/f6xcuRINDQ1YtWqVkdUmIiKiOBY399z4/X6sXr0ap06dwuDBg1FVVQWXy4WioqLgOna7HYWFhdi0aZOBNSUiImoFHJaKGcOfltqzZw8GDx6MpqYmtG3bFm+88Qb69esXTGAyMzND1s/MzMSBAwek23O73XC73cF/19XVxabiREREUeDTUrFjeM9N3759sWvXLmzZsgX3338/7rrrLnz66afBck0LfYuCEKLFsu8rKytDRkZG8JOdLX+PCRERkWGa33MTzYfCMjy5sdlsuPDCC1FQUICysjJceumleOaZZ+B0OgEALpcrZP3a2toWvTnfN2PGDJw4cSL4OXjwYEzrT0RERPHF8OTmTEIIuN1u5Obmwul0oqKiIljm8XhQWVmJIUOGSOPtdnvw0fLmDxERUbxpHpaK5kPhGXrPzcyZMzFy5EhkZ2ejvr4eq1evxgcffIB3330XmqZh6tSpmDt3Lnr37o3evXtj7ty5SE1Nxbhx44ysNhERUfQ4K3jMGJrcfPPNN7jzzjtRU1ODjIwMDBgwAO+++y6GDx8OAHj44YfR2NiI4uJiHDt2DIMGDcKGDRuQlpZmZLWJiIgojhma3CxbtkxZrmkaSktLUVpaem4qREREdI7waanYMfxRcCIiooTEWcFjJmGSG4vbC4tVcv+0X/EO64CizOtVf6nPLy/zK8p0YoVerIrej0HVXj0Wxf3penVWPN6vpTiUoVZbsrRM1J9Uxrb97JiitL0ytqmDVV6os5stit3hs8v3BQD4UhXb1TklHcflxzepUafSinNH7y9IYZG3yeJRn3O2E/JGWZp0Gqyi81vQfIp66f2O/Kp9FcV/kFTXqlj+tgOKbQud7WqK64LivACgvm6otqsnoNhuwBf5diluJExyQ0REFE84LBU7TG6IiIiMwKelYibu3nNDREREFA323BARERmAw1Kxw+SGiIjICAGhvln7h8RTWExuiIiIjMB7bmKG99wQERGRqbDnhoiIyAAaorznptVqYj5MboiIiIzANxTHDIeliIiIyFTYc0NERGQAPgoeO0xuiIiIjMCnpWKGw1JERERkKuy5ISIiMoAmRFSzxEc1w7zJJU5y4/YAFsmDcz7FFPeBgLzM71d/p09eLvRiVSetTqxQ1FmzqDvrVLG6d+Zr8gcTNatVHRsFLcURefCJemlRm8/VD1o6MlLkhXrPaCr2ld+u3ld+h/wYan71MUpqlJ87mldx7AFoPsV5pXNuiKTIO4ktjV7593oUv11A+RtU/rajpXpzrIjiN+aPIlYlit+2sgwAhM4xijexPC9afNf/faKJp7A4LEVERESmkjg9N0RERHGEw1Kxw+SGiIjICHxaKmaY3BARERmBbyiOGd5zQ0RERKbC5IaIiMgAzW8ojuYTiUWLFiE3NxcOhwP5+fn46KOPlOtXVlYiPz8fDocDPXv2xJIlS0LK9+7di1tuuQU9evSApmkoLy+PrGKtiMkNERGREZqHpaL5nKXXXnsNU6dOxaxZs7Bz504MHToUI0eORHV1ddj1q6qqMGrUKAwdOhQ7d+7EzJkz8eCDD2LNmjXBdRoaGtCzZ088+eSTcDqdEe+O1sTkhoiIKEEsWLAA99xzDyZNmoS8vDyUl5cjOzsbixcvDrv+kiVL0L17d5SXlyMvLw+TJk3CxIkTMX/+/OA6V1xxBX73u9/h5z//Oex2+7lqihKTGyIiIgNogeg/AFBXVxfycbvdYb/P4/Fg+/btKCoqClleVFSETZs2hY3ZvHlzi/VHjBiBbdu2weuVv2DTaExuiIiIjNBKw1LZ2dnIyMgIfsrKysJ+3ZEjR+D3+5GZmRmyPDMzEy6XK2yMy+UKu77P58ORI0daYSfEBh8FJyIiOo8dPHgQ6enpwX/rDQ1pZ0yZIYRosUxv/XDL4wmTGyIiIiO00kv80tPTQ5IbmU6dOsFqtbbopamtrW3RO9PM6XSGXT8pKQkdO3aMrN7nAIeliIiIDNA8/UI0n7Nhs9mQn5+PioqKkOUVFRUYMmRI2JjBgwe3WH/Dhg0oKChAcnLy2TX4HGJyQ0RElCBKSkrw4osv4qWXXsK+ffswbdo0VFdXY/LkyQCAGTNmYPz48cH1J0+ejAMHDqCkpAT79u3DSy+9hGXLlmH69OnBdTweD3bt2oVdu3bB4/Hg0KFD2LVrF7744otz3r5miTMs5fUCFkkup5ri3u9XlKnnmxcej7zM51PGKumNcyqyeeHV+V6LYtvRjK/K9n0zq7xc03RiVfWK4i8L7VSDsjypMfwTCQAAoT43VMcoKUn9sxQpNnmZLfKftObX+SvQK/8taB6dpyZUx0hx7AGof2c+xe8TABS/QUTzG4yVKH7bUYnX1/ir9kc0+0oVG9A5p1qTAdMvjB07FkePHsWcOXNQU1OD/v37Y926dcjJyQEA1NTUhLzzJjc3F+vWrcO0adPw3HPPISsrC88++yxuueWW4DqHDx/GZZddFvz3/PnzMX/+fBQWFuKDDz6IvH1RSJzkhoiIKJ4IADp/B+nGR6C4uBjFxcVhy1asWNFiWWFhIXbs2CHdXo8ePYI3GccLJjdEREQGiOS+mTPjKTzec0NERESmwp4bIiIiIwhEec9Nq9XEdJjcEBERGcGAG4oTBYeliIiIyFTYc0NERGSEAIBoZjCI5kkrk2NyQ0REZAA+LRU7HJYiIiIiU2HPDRERkRF4Q3HMMLkhIiIyApObmOGwFBEREZkKe26IiIiMwJ6bmEmc5Mbrk89MHeks2qoZw3W2qyugitXZrmpmb50ZmDW92btVrNaIQ5Uzf+vNGq2imvFdj4jiGU2d2ddFY5OiUH18tbS28sK0NspYZV+tzq7SVDNwuxWzbwP6v5VI6W1XMaO40Ju5PQq6M9lLRFUn5TUDkc+SHSVNcV2Ipr2q7epS7Ytorhlni4+Cx0ziJDdERERxhI+Cxw7vuSEiIiJTMTS5KSsrwxVXXIG0tDR06dIFP/vZz7B///6QdYQQKC0tRVZWFlJSUjBs2DDs3bvXoBoTERG1kuZ7bqL5UFiGJjeVlZV44IEHsGXLFlRUVMDn86GoqAinTp0KrjNv3jwsWLAACxcuxNatW+F0OjF8+HDU19cbWHMiIqIoBUT0HwrL0Htu3n333ZB/L1++HF26dMH27dvx4x//GEIIlJeXY9asWRgzZgwAYOXKlcjMzMSqVatw3333GVFtIiIiimNxdc/NiRMnAAAdOnQAAFRVVcHlcqGoqCi4jt1uR2FhITZt2mRIHYmIiFoFh6ViJm6elhJCoKSkBFdffTX69+8PAHC5XACAzMzMkHUzMzNx4MCBsNtxu91wu93Bf9fV1cWoxkRERNGINkFhciMTNz03U6ZMwe7du/Hqq6+2KNPOeAeDEKLFsmZlZWXIyMgIfrKzs2NSXyIiIopPcZHc/PKXv8TatWuxceNGdOvWLbjc6XQC+E8PTrPa2toWvTnNZsyYgRMnTgQ/Bw8ejF3FiYiIIsVhqZgxNLkRQmDKlCl4/fXX8f777yM3NzekPDc3F06nExUVFcFlHo8HlZWVGDJkSNht2u12pKenh3yIiIjiDp+WihlD77l54IEHsGrVKvz5z39GWlpasIcmIyMDKSkp0DQNU6dOxdy5c9G7d2/07t0bc+fORWpqKsaNG2dk1YmIiChOGZrcLF68GAAwbNiwkOXLly/HhAkTAAAPP/wwGhsbUVxcjGPHjmHQoEHYsGED0tLSznFtiYiIWpEInP5EE09hGZrciB8wXqhpGkpLS1FaWhr7ChEREZ0rnBU8ZuLmUXAiIqKEEhCI6nFu3nMjlTDJjfB4IGRTy6umuFdkxkIVpxMbryelqk2aRef+c8nj+QCgWa3q71V0r2p+9dfCIv9eo/4qEn51pYXHIy/065xXqv2s2hc6sfDp7GjV/vD51LGKNqmOvV6s8rcL9XGI5nyGTqzQDPh9R3Ou65yv0fghPfQRbVfnGqq85lgVx0913Om8kTDJDRERUVzhsFTMMLkhIiIygkCUyU2r1cR04uIlfkRERESthT03RERERuCwVMwwuSEiIjJCIAAginfV6D3UksA4LEVERESmwp4bIiIiI3BYKmaY3BARERmByU3McFiKiIiITIU9N0REREbg9Asxw+SGiIjIAEIE9Kcf0Ymn8JjcEBERGUGI6HpfeM+NFO+5ISIiIlNhzw0REZERRJT33LDnRiphkhvh9ULIprKP1Qmi6m7UGyvVFJ1qFkk7WoFmtSq+V6ejT7Efhc8XYY0AofcGT9VbOvXqrIgVfr86VsUfxTi63vc2NMjLdM4NTXFeBVTbBSC88mOo6Z2TSfJLjaZzjITiGOnFasnJ6nrFSqTnThTnazTXMdU+jppiX+gdP8iu2YDuvlL9jpRn67l8628gAGhRfB/vuZHisBQRERGZSsL03BAREcUVDkvFDJMbIiIiA4hAACKKYSk+Ci7HYSkiIiIyFfbcEBERGYHDUjHD5IaIiMgIAQFoTG5igcNSREREZCrsuSEiIjKCEIDee7x04ykcJjdEREQGEAEBEcWwlGByI8XkhoiIyAgigOh6bvgouAzvuSEiIiJTYc8NERGRATgsFTtMboiIiIzAYamYMX1y05zZ+oRXtVKsvjyK71TMWyuimRVcZ9ZooZgVXMTpKKbqB65XZ0WsEFHMCh7FRUfvleqa4vhrAY86VjUruFDHqvaHqk6ngxUze+scI9X+0IuF6nyOpUiPfxTna1Szghv0H0nd46e8DkYeqwXk54Xv/34H56JXxAdvVO/w80Hx37UEZ/rkpr6+HgDwYeMag2tCdA6o8xPjxGu9iCTq6+uRkZERk23bbDY4nU78zbUu6m05nU7YbLZWqJW5aMLkg3aBQACHDx9GWloaNE1DXV0dsrOzcfDgQaSnpxtdvZhje80rkdoKsL1mFy/tFUKgvr4eWVlZsFhi11vd1NQEjyf6rN9ms8HhcLRCjczF9D03FosF3bp1a7E8PT09IS4Yzdhe80qktgJsr9nFQ3tj1WPzfQ6Hg0lJDMXpTRREREREkWFyQ0RERKaScMmN3W7H7NmzYbfbja7KOcH2mlcitRVge80u0dpLsWX6G4qJiIgosSRczw0RERGZG5MbIiIiMhUmN0RERGQqTG6IiIjIVM775KasrAxXXHEF0tLS0KVLF/zsZz/D/v37Q9YRQqC0tBRZWVlISUnBsGHDsHfv3pB13G43fvnLX6JTp05o06YNbrzxRnz99dfnsik/iF57vV4vfv3rX+OSSy5BmzZtkJWVhfHjx+Pw4cMh2zFLe8903333QdM0lJeXhyw3W3v37duHG2+8ERkZGUhLS8OVV16J6urqYLmZ2nvy5ElMmTIF3bp1Q0pKCvLy8rB48eKQdc6X9i5evBgDBgwIvqhu8ODBeOedd4LlZrpWAer2mu1aRXFGnOdGjBghli9fLj755BOxa9cucf3114vu3buLkydPBtd58sknRVpamlizZo3Ys2ePGDt2rOjatauoq6sLrjN58mRxwQUXiIqKCrFjxw5xzTXXiEsvvVT4fD4jmiWl197jx4+La6+9Vrz22mviX//6l9i8ebMYNGiQyM/PD9mOWdr7fW+88Ya49NJLRVZWlnj66adDyszU3i+++EJ06NBB/OpXvxI7duwQ//73v8Vbb70lvvnmm+A6ZmrvpEmTRK9evcTGjRtFVVWVeP7554XVahVvvvlmcJ3zpb1r164Vb7/9tti/f7/Yv3+/mDlzpkhOThaffPKJEMJc1yoh1O0127WK4st5n9ycqba2VgAQlZWVQgghAoGAcDqd4sknnwyu09TUJDIyMsSSJUuEEKcTguTkZLF69ergOocOHRIWi0W8++6757YBZ+nM9obz8ccfCwDiwIEDQghztvfrr78WF1xwgfjkk09ETk5OSHJjtvaOHTtW3HHHHdIYs7X34osvFnPmzAlZ7/LLLxePPvqoEOL8bq8QQrRv3168+OKLpr9WNWtubzhmulaRsc77YakznThxAgDQoUMHAEBVVRVcLheKioqC69jtdhQWFmLTpk0AgO3bt8Pr9Yask5WVhf79+wfXiVdntle2jqZpaNeuHQDztTcQCODOO+/Er371K1x88cUtYszU3kAggLfffht9+vTBiBEj0KVLFwwaNAhvvvlmMMZM7QWAq6++GmvXrsWhQ4cghMDGjRvx2WefYcSIEQDO3/b6/X6sXr0ap06dwuDBg01/rTqzveGY6VpFxjJVciOEQElJCa6++mr0798fAOByuQAAmZmZIetmZmYGy1wuF2w2G9q3by9dJx6Fa++Zmpqa8Mgjj2DcuHHByejM1t7f/va3SEpKwoMPPhg2zkztra2txcmTJ/Hkk0/iuuuuw4YNG3DzzTdjzJgxqKysBGCu9gLAs88+i379+qFbt26w2Wy47rrrsGjRIlx99dUAzr/27tmzB23btoXdbsfkyZPxxhtvoF+/fqa9VsnaeyYzXavIeKaaFXzKlCnYvXs3/va3v7Uo0zQt5N9CiBbLzvRD1jGSqr3A6Rv2fv7znyMQCGDRokW62zsf27t9+3Y888wz2LFjx1nX/XxsbyAQAADcdNNNmDZtGgBg4MCB2LRpE5YsWYLCwkLp9s7H9gKnk5stW7Zg7dq1yMnJwYcffoji4mJ07doV1157rXR78drevn37YteuXTh+/DjWrFmDu+66K5iYAua7Vsna+/0Ex2zXKjKeaXpufvnLX2Lt2rXYuHEjunXrFlzudDoBoEWWX1tbG/wLyel0wuPx4NixY9J14o2svc28Xi9uu+02VFVVoaKiIviXEGCu9n700Ueora1F9+7dkZSUhKSkJBw4cAD/7//9P/To0QOAudrbqVMnJCUltfjLNy8vL/i0lJna29jYiJkzZ2LBggW44YYbMGDAAEyZMgVjx47F/PnzAZx/7bXZbLjwwgtRUFCAsrIyXHrppXjmmWdMe62StbeZ2a5VFB/O++RGCIEpU6bg9ddfx/vvv4/c3NyQ8tzcXDidTlRUVASXeTweVFZWYsiQIQCA/Px8JCcnh6xTU1ODTz75JLhOvNBrL/Cfi8Xnn3+O9957Dx07dgwpN1N777zzTuzevRu7du0KfrKysvCrX/0K69evB2Cu9tpsNlxxxRUtHpf+7LPPkJOTA8Bc7fV6vfB6vbBYQi9VVqs12It1PrU3HCEE3G636a5VMs3tBcx1raI4cy7vXo6F+++/X2RkZIgPPvhA1NTUBD8NDQ3BdZ588kmRkZEhXn/9dbFnzx7xi1/8Iuzjld26dRPvvfee2LFjh/jJT34Sl48b6rXX6/WKG2+8UXTr1k3s2rUrZB232x3cjlnaG86ZT0sJYa72vv766yI5OVm88MIL4vPPPxe///3vhdVqFR999FFwHTO1t7CwUFx88cVi48aN4ssvvxTLly8XDodDLFq0KLjO+dLeGTNmiA8//FBUVVWJ3bt3i5kzZwqLxSI2bNgghDDXtUoIdXvNdq2i+HLeJzcAwn6WL18eXCcQCIjZs2cLp9Mp7Ha7+PGPfyz27NkTsp3GxkYxZcoU0aFDB5GSkiJGjx4tqqurz3Fr9Om1t6qqSrrOxo0bg9sxS3vDCZfcmK29y5YtExdeeKFwOBzi0ksvDXnnixDmam9NTY2YMGGCyMrKEg6HQ/Tt21c89dRTIhAIBNc5X9o7ceJEkZOTI2w2m+jcubP46U9/GkxshDDXtUoIdXvNdq2i+KIJIUSseoWIiIiIzrXz/p4bIiIiou9jckNERESmwuSGiIiITIXJDREREZkKkxsiIiIyFSY3REREZCpMboiIiMhUmNwQmdCwYcMwdepUo6tBRGQIJjdERERkKkxuiIiIyFSY3BCZ3LFjxzB+/Hi0b98eqampGDlyJD7//PNg+YoVK9CuXTusX78eeXl5aNu2La677jrU1NQYWGsiosgxuSEyuQkTJmDbtm1Yu3YtNm/eDCEERo0aBa/XG1ynoaEB8+fPxx/+8Ad8+OGHqK6uxvTp0w2sNRFR5JKMrgARxc7nn3+OtWvX4u9//zuGDBkCAPjjH/+I7OxsvPnmm7j11lsBAF6vF0uWLEGvXr0AAFOmTMGcOXMMqzcRUTTYc0NkYvv27UNSUhIGDRoUXNaxY0f07dsX+/btCy5LTU0NJjYA0LVrV9TW1p7TuhIRtRYmN0QmJoSQLtc0Lfjv5OTkkHJN06SxRETxjskNkYn169cPPp8P//jHP4LLjh49is8++wx5eXkG1oyIKHaY3BCZWO/evXHTTTfh3nvvxd/+9jf885//xB133IELLrgAN910k9HVIyKKCSY3RCa3fPly5OfnY/To0Rg8eDCEEFi3bl2LoSgiIrPQBAfWiYiIyETYc0NERESmwuSGiIiITIXJDREREZkKkxsiIiIyFSY3REREZCpMboiIiMhUmNwQERGRqTC5ISIiIlNhckNERESmwuSGiIiITIXJDREREZkKkxsiIiIylf8PjpmStxiTNCIAAAAASUVORK5CYII=", - "text/plain": [ - "
    " - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "components[\"air\"].sel(mode=1).plot()" ] @@ -1468,30 +183,9 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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iIjIACZLRERERAYwWSIiIiIygMkSERERkQFMlojI7U2ZMgVNmjSROgwiclKss0RELq1snSx9nnvuOcybNw/5+fmoVKmSg6IiIjlhskRELi0lJUX59cqVK/Huu+/i7Nmzym3+/v4ICQmRIjQikgk+hiMilxYZGan8FxISAoVCobVN8zHc0KFD0bdvX0yfPh0REREoX7483n//fRQVFeH1119HxYoVUbVqVXzzzTdq3+v69esYOHAgKlSogEqVKqFPnz64cuWKYxtMRDbHZImISIetW7fixo0b+OeffzB79mxMmTIFvXv3RoUKFbB3716MHj0ao0ePRnJyMgAgJycHHTt2RGBgIP755x/8+++/CAwMRPfu3VFQUCBxa4jIGkyWiIh0qFixIubOnYu6deti2LBhqFu3LnJycvDmm2+idu3amDx5Mnx8fLBz504AwI8//ggPDw98/fXXaNSoEeLi4vDtt98iKSkJf//9t7SNISKreEkdABGRM2rQoAE8PB7cT0ZERKBhw4bK156enqhUqRJSU1MBAAcPHsSFCxcQFBSk9j55eXm4ePGiY4ImIrtgskREpIO3t7faa4VCoXNbSUkJAKCkpATNmzfH8uXLtd4rLCzMfoESkd0xWSIisoFmzZph5cqVCA8PR3BwsNThEJENccwSEZENDB48GKGhoejTpw927NiBy5cvY/v27XjllVdw7do1qcMjIiswWSIisoGAgAD8888/qFatGvr164e4uDgMGzYMubm57GkikjkWpSQiIiIygD1LRERERAYwWSIiIiIygMkSERERkQFMloiIiIgMYLJEREREZACTJSIiIiIDmCwRERERGcBkiYiIiMgAJktEREREBjBZIiIiIjKAyRIRERGRAUyWiIiIiAz4f54APIGe5PaPAAAAAElFTkSuQmCC", - "text/plain": [ - "
    " - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "model.scores().sel(mode=1).plot()" ] @@ -1499,9 +193,9 @@ ], "metadata": { "kernelspec": { - "display_name": "xeofs", + "display_name": "Python 3", "language": "python", - "name": "xeofs" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -1513,9 +207,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" - }, - "orig_nbformat": 4 + "version": "3.10.12" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/examples/1single/eof-smode.jpg b/examples/1single/eof-smode.jpg index c071a469..4a2e7329 100644 Binary files a/examples/1single/eof-smode.jpg and b/examples/1single/eof-smode.jpg differ diff --git a/examples/1single/eof-tmode.jpg b/examples/1single/eof-tmode.jpg index 16cb3157..3e005db8 100644 Binary files a/examples/1single/eof-tmode.jpg and b/examples/1single/eof-tmode.jpg differ diff --git a/examples/1single/mreof-analysis.jpg b/examples/1single/mreof-analysis.jpg index 5bc702f6..a75b5fbb 100644 Binary files a/examples/1single/mreof-analysis.jpg and b/examples/1single/mreof-analysis.jpg differ diff --git a/examples/1single/multivariate-eof-analysis.jpg b/examples/1single/multivariate-eof-analysis.jpg index 84160621..18a30b92 100644 Binary files a/examples/1single/multivariate-eof-analysis.jpg and b/examples/1single/multivariate-eof-analysis.jpg differ diff --git a/examples/1single/plot_complex_eof.py b/examples/1single/plot_complex_eof.py index d07be820..d72e8132 100644 --- a/examples/1single/plot_complex_eof.py +++ b/examples/1single/plot_complex_eof.py @@ -2,14 +2,14 @@ Complex/Hilbert EOF analysis ============================================ -We demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_. -This method extends traditional EOF analysis into the complex domain, allowing +We demonstrate how to execute a Complex EOF (or Hilbert EOF) analysis [1]_ [2]_ [3]_. +This method extends traditional EOF analysis into the complex domain, allowing the EOF components to have real and imaginary parts. This capability can reveal -oscillatory patterns in datasets, which are common in Earth observations. +oscillatory patterns in datasets, which are common in Earth observations. For example, beyond typical examples like seasonal cycles, you can think of internal waves in the ocean, or the Quasi-Biennial Oscillation in the atmosphere. -Using monthly sea surface temperature data from 1970 to 2021 as an example, we +Using monthly sea surface temperature data from 1970 to 2021 as an example, we highlight the method's key features and address edge effects as a common challenge. .. [1] Rasmusson, E. M., Arkin, P. A., Chen, W.-Y. & Jalickee, J. B. Biennial variations in surface temperature over the United States as revealed by singular decomposition. Monthly Weather Review 109, 587–598 (1981). diff --git a/examples/1single/plot_eeof.py b/examples/1single/plot_eeof.py index 2a7ab1d1..ab804f5b 100644 --- a/examples/1single/plot_eeof.py +++ b/examples/1single/plot_eeof.py @@ -2,12 +2,12 @@ Extented EOF analysis ===================== -This example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial -data. EEOF analysis, also termed as Multivariate/Multichannel Singular -Spectrum Analysis, advances traditional EOF analysis to capture propagating -signals or oscillations in multivariate datasets. At its core, this -involves the formulation of a lagged covariance matrix that encapsulates -both spatial and temporal correlations. Subsequently, this matrix is +This example demonstrates Extended EOF (EEOF) analysis on ``xarray`` tutorial +data. EEOF analysis, also termed as Multivariate/Multichannel Singular +Spectrum Analysis, advances traditional EOF analysis to capture propagating +signals or oscillations in multivariate datasets. At its core, this +involves the formulation of a lagged covariance matrix that encapsulates +both spatial and temporal correlations. Subsequently, this matrix is decomposed to yield its eigenvectors (components) and eigenvalues (explained variance). Let's begin by setting up the required packages and fetching the data: diff --git a/examples/1single/plot_eof-smode.py b/examples/1single/plot_eof-smode.py index 4a947fc8..f9cd5f38 100644 --- a/examples/1single/plot_eof-smode.py +++ b/examples/1single/plot_eof-smode.py @@ -5,7 +5,6 @@ EOF analysis in S-mode maximises the temporal variance. """ - # Load packages and data: import xarray as xr import matplotlib.pyplot as plt diff --git a/examples/1single/plot_eof-tmode.py b/examples/1single/plot_eof-tmode.py index 2afe0fdc..6a618e3e 100644 --- a/examples/1single/plot_eof-tmode.py +++ b/examples/1single/plot_eof-tmode.py @@ -6,6 +6,7 @@ Load packages and data: """ + import xarray as xr import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec diff --git a/examples/1single/plot_gwpca.py b/examples/1single/plot_gwpca.py index a0842832..f1542228 100644 --- a/examples/1single/plot_gwpca.py +++ b/examples/1single/plot_gwpca.py @@ -3,8 +3,8 @@ =========================== Geographically Weighted Principal Component Analysis (GWPCA) is a spatial analysis method that identifies and visualizes local spatial patterns and relationships in multivariate datasets across various geographic areas. It operates by applying PCA within a moving window over a geographical region, which enables the extraction of local principal components that can differ across locations. -TIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_. -The dataset comprises 10 variables (chemical elements) and spans 768 samples. +TIn this demonstration, we'll apply GWPCA to a dataset detailing the chemical compositions of soils from countries around the Baltic Sea [1]_. This example is inspired by a tutorial originally crafted and published by Chris Brunsdon [2]_. +The dataset comprises 10 variables (chemical elements) and spans 768 samples. Here, each sample refers to a pair of latitude and longitude coordinates, representing specific sampling stations. .. [1] Reimann, C. et al. Baltic soil survey: total concentrations of major and selected trace elements in arable soils from 10 countries around the Baltic Sea. Science of The Total Environment 257, 155–170 (2000). @@ -12,17 +12,17 @@ -.. note:: The dataset we're using is found in the R package - `mvoutlier `_. - To access it, we'll employ the Python package - `rpy2 `_ which facilitates - interaction with R packages from within Python. +.. note:: The dataset we're using is found in the R package + `mvoutlier `_. + To access it, we'll employ the Python package + `rpy2 `_ which facilitates + interaction with R packages from within Python. -.. note:: Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension. +.. note:: Presently, there's no support for ``xarray.Dataset`` lacking an explicit feature dimension. As a workaround, ``xarray.DataArray.to_array`` can be used to convert the ``Dataset`` to an ``DataArray``. .. warning:: Bear in mind that GWPCA requires significant computational power. - The ``xeofs`` implementation is optimized for CPU efficiency and is best suited + The ``xeofs`` implementation is optimized for CPU efficiency and is best suited for smaller to medium data sets. For more extensive datasets where parallel processing becomes essential, it's advisable to turn to the R package `GWmodel `_. This package harnesses CUDA to enable GPU-accelerated GWPCA for optimized performance. @@ -30,6 +30,7 @@ Let's import the necessary packages. """ + # For the analysis import numpy as np import xarray as xr diff --git a/examples/1single/plot_mreof.py b/examples/1single/plot_mreof.py index cafbe67e..5bbc6a0f 100644 --- a/examples/1single/plot_mreof.py +++ b/examples/1single/plot_mreof.py @@ -5,7 +5,6 @@ Multivariate EOF analysis with additional Varimax rotation. """ - # Load packages and data: import xarray as xr import matplotlib.pyplot as plt @@ -61,8 +60,8 @@ for i, (a, comps) in enumerate(zip(ax, rcomponents)): a.coastlines(color=".5") comps.sel(mode=mode).plot(ax=a, **kwargs) - a.set_xticks([]) - a.set_yticks([]) + a.set_xticks([], []) + a.set_yticks([], []) a.set_xlabel("") a.set_ylabel("") a.set_title("Subset {:}".format(i + 1)) diff --git a/examples/1single/plot_multivariate-eof.py b/examples/1single/plot_multivariate-eof.py index 85331795..31c6f623 100644 --- a/examples/1single/plot_multivariate-eof.py +++ b/examples/1single/plot_multivariate-eof.py @@ -5,7 +5,6 @@ Multivariate EOF analysis. """ - # Load packages and data: import xarray as xr import matplotlib.pyplot as plt @@ -58,8 +57,8 @@ for i, (a, comps) in enumerate(zip(ax, components)): a.coastlines(color=".5") comps.sel(mode=mode).plot(ax=a, **kwargs) - a.set_xticks([]) - a.set_yticks([]) + a.set_xticks([], []) + a.set_yticks([], []) a.set_xlabel("") a.set_ylabel("") a.set_title("Subset {:}".format(i + 1)) diff --git a/examples/1single/plot_rotated_eof.py b/examples/1single/plot_rotated_eof.py index f28a2446..0f8b296b 100644 --- a/examples/1single/plot_rotated_eof.py +++ b/examples/1single/plot_rotated_eof.py @@ -2,25 +2,26 @@ Rotated EOF analysis ======================== -EOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting -the derived eigenvectors (EOFs) as climatic variability patterns. However, due to -the inherent orthogonality constraint in EOF analysis, the interpretation of all -but the first EOF can be problematic. Rotated EOF analysis, using optimization criteria -like Varimax and Promax, offers a solution by releasing this orthogonality constraint, +EOF (Empirical Orthogonal Function) analysis is commonly used in climate science, interpreting +the derived eigenvectors (EOFs) as climatic variability patterns. However, due to +the inherent orthogonality constraint in EOF analysis, the interpretation of all +but the first EOF can be problematic. Rotated EOF analysis, using optimization criteria +like Varimax and Promax, offers a solution by releasing this orthogonality constraint, thus enabling a more accurate interpretation of variability patterns. -Both Varimax (orthogonal) and Promax (oblique) rotations result in "sparse" solutions, -meaning the EOFs become more interpretable by limiting the number of variables that -contribute to each EOF. This rotation effectively serves as a regularization method -for the EOF solution, with the strength of regularization determined by the power parameter; +Both Varimax (orthogonal) and Promax (oblique) rotations result in "sparse" solutions, +meaning the EOFs become more interpretable by limiting the number of variables that +contribute to each EOF. This rotation effectively serves as a regularization method +for the EOF solution, with the strength of regularization determined by the power parameter; the higher the value, the sparser the EOFs. -Promax rotation, with a small regularization value (i.e., power=1), reverts to Varimax -rotation. In this context, we compare the first three modes of EOF analysis: (1) +Promax rotation, with a small regularization value (i.e., power=1), reverts to Varimax +rotation. In this context, we compare the first three modes of EOF analysis: (1) without regularization, (2) with Varimax rotation, and (3) with Promax rotation. We'll start by loading the necessary packages and data: """ + import xarray as xr import matplotlib.pyplot as plt import seaborn as sns diff --git a/examples/1single/plot_weighted-eof.py b/examples/1single/plot_weighted-eof.py index 23721267..26a88473 100644 --- a/examples/1single/plot_weighted-eof.py +++ b/examples/1single/plot_weighted-eof.py @@ -10,6 +10,7 @@ Load packages and data: """ + import xarray as xr import matplotlib.pyplot as plt import seaborn as sns @@ -78,7 +79,7 @@ a2.set_title("", loc="center") a2.set_title(titles[i], loc="left", weight="bold") if i < 3: - a2.set_xticks([]) + a2.set_xticks([], []) sns.despine(ax=a2, trim=True, bottom=True) else: sns.despine(ax=a2, trim=True, bottom=False) diff --git a/examples/1single/rotated_eof.jpg b/examples/1single/rotated_eof.jpg index b42de89e..28b6966b 100644 Binary files a/examples/1single/rotated_eof.jpg and b/examples/1single/rotated_eof.jpg differ diff --git a/examples/1single/weighted_eof.jpg b/examples/1single/weighted_eof.jpg index c96eb7cb..07008c8f 100644 Binary files a/examples/1single/weighted_eof.jpg and b/examples/1single/weighted_eof.jpg differ diff --git a/examples/2multi/mca.jpg b/examples/2multi/mca.jpg index 9e883078..664242ae 100644 Binary files a/examples/2multi/mca.jpg and b/examples/2multi/mca.jpg differ diff --git a/examples/2multi/plot_cca.py b/examples/2multi/plot_cca.py index b84cf0dc..e57af825 100644 --- a/examples/2multi/plot_cca.py +++ b/examples/2multi/plot_cca.py @@ -2,10 +2,10 @@ Canonical Correlation Analysis ============================== -In this example, we're going to perform a Canonical Correlation Analysis (CCA) -on three datasets using the ERSSTv5 monthly sea surface temperature (SST) data -from 1970 to 2022. We divide this data into three areas: the Indian Ocean, -the Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these +In this example, we're going to perform a Canonical Correlation Analysis (CCA) +on three datasets using the ERSSTv5 monthly sea surface temperature (SST) data +from 1970 to 2022. We divide this data into three areas: the Indian Ocean, +the Pacific Ocean, and the Atlantic Ocean. Our goal is to perform CCA on these regions. First, we'll import the necessary modules. diff --git a/examples/2multi/plot_mca.py b/examples/2multi/plot_mca.py index 9b804644..d3b48de7 100644 --- a/examples/2multi/plot_mca.py +++ b/examples/2multi/plot_mca.py @@ -5,7 +5,6 @@ Maximum Covariance Analysis (MCA) between two data sets. """ - # Load packages and data: import numpy as np import xarray as xr diff --git a/examples/2multi/plot_rotated_mca.py b/examples/2multi/plot_rotated_mca.py index 59d337bc..a7ec89fe 100644 --- a/examples/2multi/plot_rotated_mca.py +++ b/examples/2multi/plot_rotated_mca.py @@ -5,7 +5,6 @@ Rotated Maximum Covariance Analysis (MCA) between two data sets. """ - # Load packages and data: import numpy as np import xarray as xr diff --git a/examples/2multi/rotated_mca.jpg b/examples/2multi/rotated_mca.jpg index 4da1a316..47e11346 100644 Binary files a/examples/2multi/rotated_mca.jpg and b/examples/2multi/rotated_mca.jpg differ diff --git a/examples/3validation/bootstrap.jpg b/examples/3validation/bootstrap.jpg index 918a8089..6767652c 100644 Binary files a/examples/3validation/bootstrap.jpg and b/examples/3validation/bootstrap.jpg differ diff --git a/examples/3validation/plot_bootstrap.py b/examples/3validation/plot_bootstrap.py index 5a53af99..02cec5dc 100644 --- a/examples/3validation/plot_bootstrap.py +++ b/examples/3validation/plot_bootstrap.py @@ -6,7 +6,6 @@ for both EOFs and PCs. """ - # Load packages and data: import numpy as np import xarray as xr @@ -49,7 +48,7 @@ is_significant = q025 - q975.shift({"mode": -1}) > 0 n_significant_modes = ( - is_significant.where(is_significant == True).cumsum(skipna=False).max().fillna(0) + is_significant.where(is_significant is True).cumsum(skipna=False).max().fillna(0) ) print("{:} modes are significant at alpha=0.05".format(n_significant_modes.values)) diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 408f05d8..00000000 --- a/poetry.lock +++ /dev/null @@ -1,3163 +0,0 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. - -[[package]] -name = "accessible-pygments" -version = "0.0.4" -description = "A collection of accessible pygments styles" -optional = false -python-versions = "*" -files = [ - {file = "accessible-pygments-0.0.4.tar.gz", hash = "sha256:e7b57a9b15958e9601c7e9eb07a440c813283545a20973f2574a5f453d0e953e"}, - {file = "accessible_pygments-0.0.4-py2.py3-none-any.whl", hash = "sha256:416c6d8c1ea1c5ad8701903a20fcedf953c6e720d64f33dc47bfb2d3f2fa4e8d"}, -] - -[package.dependencies] -pygments = ">=1.5" - -[[package]] -name = "alabaster" -version = "0.7.13" -description = "A configurable sidebar-enabled Sphinx theme" -optional = false -python-versions = ">=3.6" -files = [ - {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, - {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, -] - -[[package]] -name = "asciitree" -version = "0.3.3" -description = "Draws ASCII trees." -optional = false -python-versions = "*" -files = [ - {file = "asciitree-0.3.3.tar.gz", hash = "sha256:4aa4b9b649f85e3fcb343363d97564aa1fb62e249677f2e18a96765145cc0f6e"}, -] - -[[package]] -name = "attrs" -version = "23.1.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] - -[[package]] -name = "babel" -version = "2.13.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"}, - {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"}, -] - -[package.extras] -dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] - -[[package]] -name = "beautifulsoup4" -version = "4.12.2" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.6.0" -files = [ - {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, - {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "black" -version = "23.7.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -files = [ - {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, - {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, - {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, - {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, - {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, - {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, - {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, - {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, - {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, - {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, - {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "bleach" -version = "6.1.0" -description = "An easy safelist-based HTML-sanitizing tool." -optional = false -python-versions = ">=3.8" -files = [ - {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, - {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, -] - -[package.dependencies] -six = ">=1.9.0" -webencodings = "*" - -[package.extras] -css = ["tinycss2 (>=1.1.0,<1.3)"] - -[[package]] -name = "build" -version = "0.10.0" -description = "A simple, correct Python build frontend" -optional = false -python-versions = ">= 3.7" -files = [ - {file = "build-0.10.0-py3-none-any.whl", hash = "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171"}, - {file = "build-0.10.0.tar.gz", hash = "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "os_name == \"nt\""} -packaging = ">=19.0" -pyproject_hooks = "*" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"] -test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"] -typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"] -virtualenv = ["virtualenv (>=20.0.35)"] - -[[package]] -name = "cachecontrol" -version = "0.13.1" -description = "httplib2 caching for requests" -optional = false -python-versions = ">=3.7" -files = [ - {file = "cachecontrol-0.13.1-py3-none-any.whl", hash = "sha256:95dedbec849f46dda3137866dc28b9d133fc9af55f5b805ab1291833e4457aa4"}, - {file = "cachecontrol-0.13.1.tar.gz", hash = "sha256:f012366b79d2243a6118309ce73151bf52a38d4a5dac8ea57f09bd29087e506b"}, -] - -[package.dependencies] -filelock = {version = ">=3.8.0", optional = true, markers = "extra == \"filecache\""} -msgpack = ">=0.5.2" -requests = ">=2.16.0" - -[package.extras] -dev = ["CacheControl[filecache,redis]", "black", "build", "cherrypy", "mypy", "pytest", "pytest-cov", "sphinx", "tox", "types-redis", "types-requests"] -filecache = ["filelock (>=3.8.0)"] -redis = ["redis (>=2.10.5)"] - -[[package]] -name = "certifi" -version = "2023.7.22" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "cfgv" -version = "3.4.0" -description = "Validate configuration and produce human readable error messages." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, -] - -[[package]] -name = "cftime" -version = "1.6.3" -description = "Time-handling functionality from netcdf4-python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "cftime-1.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b62d42546fa5c914dfea5b15a9aaed2087ea1211cc36d08c374502ef95892038"}, - {file = "cftime-1.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb6dd70b2ccabfe1a14b7fbb0bbdce0418e71697094373c0d573c880790fa291"}, - {file = "cftime-1.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9878bfd8c1c3f24184ecbd528f739ba46ebaceaf1c8a24d348d7befb117a285"}, - {file = "cftime-1.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:3cf6e216a4c06f9a628cdf8e9c9d5e8097fb3eb02dd087dd14ab3b18478a7271"}, - {file = "cftime-1.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d2c01456d9d7b46aa710a41d1c711a50d5ea259aff4a987d0e973d1093bc922"}, - {file = "cftime-1.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:80eb1170ce1639016f55760847f4aadd04b0312496c5bac2797e930914bba48d"}, - {file = "cftime-1.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d87dadd0824262bdd7493babd2a44447da0a22175ded8ae9e060a3aebec7c5d7"}, - {file = "cftime-1.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:0a38eb9f5c733a23e1714bd3ef2762ed5acee34f127670f8fb4ad6464946f6b3"}, - {file = "cftime-1.6.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2d113a01ab924445e61d65c26bbd95bc08e4a22878d3b947064bba056c884c4a"}, - {file = "cftime-1.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f11685663a6af97418908060492a07663c16d42519c139ca03c2ffb1377fd25"}, - {file = "cftime-1.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a98abb1d46d118e52b0611ce668a0b714b407be26177ef0581ecf5e95f894725"}, - {file = "cftime-1.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:4d6fbd5f41b322cfa7b0ac3aaadeceb4450100a164b5bccbbb9e7c5048489a88"}, - {file = "cftime-1.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bedb577bc8b8f3f10f5336c0792e5dae88605781890f50f36b45bb46907968e8"}, - {file = "cftime-1.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:022dabf1610cdd04a693e730fa8f71d307059717f29dba921e7486e553412bb4"}, - {file = "cftime-1.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbf782ab4ac0605bdec2b941952c897595613203942b7f8c2fccd17efa5147df"}, - {file = "cftime-1.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:9eb177a02db7cd84aa6962278e4bd2d3106a545de82e6aacd9404f1e153661db"}, - {file = "cftime-1.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b86be8c2f254147be4ba88f12099466dde457a4a3a21de6c69d52a7224c13ae"}, - {file = "cftime-1.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:523b9a6bf03f5e36407979e248381d0fcab2d225b915bbde77d00c6dde192b90"}, - {file = "cftime-1.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a14d2c7d22fd2a6dfa6ad563283b6d6679f1df95e0ed8d14b8f284dad402887"}, - {file = "cftime-1.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:d9b00c2844c7a1701d8ede5336b6321dfee256ceab81a34a1aff0483d56891a6"}, - {file = "cftime-1.6.3.tar.gz", hash = "sha256:d0a6b29f72a13f08e008b9becff247cc75c84acb213332ede18879c5b6aa4dfd"}, -] - -[package.dependencies] -numpy = {version = ">1.13.3", markers = "python_version < \"3.12.0.rc1\""} - -[[package]] -name = "charset-normalizer" -version = "3.3.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, - {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, -] - -[[package]] -name = "cleo" -version = "2.0.1" -description = "Cleo allows you to create beautiful and testable command-line interfaces." -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "cleo-2.0.1-py3-none-any.whl", hash = "sha256:6eb133670a3ed1f3b052d53789017b6e50fca66d1287e6e6696285f4cb8ea448"}, - {file = "cleo-2.0.1.tar.gz", hash = "sha256:eb4b2e1f3063c11085cebe489a6e9124163c226575a3c3be69b2e51af4a15ec5"}, -] - -[package.dependencies] -crashtest = ">=0.4.1,<0.5.0" -rapidfuzz = ">=2.2.0,<3.0.0" - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "cloudpickle" -version = "3.0.0" -description = "Pickler class to extend the standard pickle.Pickler functionality" -optional = false -python-versions = ">=3.8" -files = [ - {file = "cloudpickle-3.0.0-py3-none-any.whl", hash = "sha256:246ee7d0c295602a036e86369c77fecda4ab17b506496730f2f576d9016fd9c7"}, - {file = "cloudpickle-3.0.0.tar.gz", hash = "sha256:996d9a482c6fb4f33c1a35335cf8afd065d2a56e973270364840712d9131a882"}, -] - -[[package]] -name = "colorama" -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" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "coverage" -version = "6.5.0" -description = "Code coverage measurement for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, - {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, - {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, - {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, - {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, - {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, - {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, - {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, - {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, - {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, - {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, - {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, - {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, - {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, - {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, - {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, -] - -[package.extras] -toml = ["tomli"] - -[[package]] -name = "crashtest" -version = "0.4.1" -description = "Manage Python errors with ease" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "crashtest-0.4.1-py3-none-any.whl", hash = "sha256:8d23eac5fa660409f57472e3851dab7ac18aba459a8d19cbbba86d3d5aecd2a5"}, - {file = "crashtest-0.4.1.tar.gz", hash = "sha256:80d7b1f316ebfbd429f648076d6275c877ba30ba48979de4191714a75266f0ce"}, -] - -[[package]] -name = "cryptography" -version = "41.0.5" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = ">=3.7" -files = [ - {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:da6a0ff8f1016ccc7477e6339e1d50ce5f59b88905585f77193ebd5068f1e797"}, - {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b948e09fe5fb18517d99994184854ebd50b57248736fd4c720ad540560174ec5"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e6031e113b7421db1de0c1b1f7739564a88f1684c6b89234fbf6c11b75147"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e270c04f4d9b5671ebcc792b3ba5d4488bf7c42c3c241a3748e2599776f29696"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ec3b055ff8f1dce8e6ef28f626e0972981475173d7973d63f271b29c8a2897da"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7d208c21e47940369accfc9e85f0de7693d9a5d843c2509b3846b2db170dfd20"}, - {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8254962e6ba1f4d2090c44daf50a547cd5f0bf446dc658a8e5f8156cae0d8548"}, - {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a48e74dad1fb349f3dc1d449ed88e0017d792997a7ad2ec9587ed17405667e6d"}, - {file = "cryptography-41.0.5-cp37-abi3-win32.whl", hash = "sha256:d3977f0e276f6f5bf245c403156673db103283266601405376f075c849a0b936"}, - {file = "cryptography-41.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:73801ac9736741f220e20435f84ecec75ed70eda90f781a148f1bad546963d81"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3be3ca726e1572517d2bef99a818378bbcf7d7799d5372a46c79c29eb8d166c1"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e886098619d3815e0ad5790c973afeee2c0e6e04b4da90b88e6bd06e2a0b1b72"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:573eb7128cbca75f9157dcde974781209463ce56b5804983e11a1c462f0f4e88"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:227ec057cd32a41c6651701abc0328135e472ed450f47c2766f23267b792a88e"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:22892cc830d8b2c89ea60148227631bb96a7da0c1b722f2aac8824b1b7c0b6b8"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5a70187954ba7292c7876734183e810b728b4f3965fbe571421cb2434d279179"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:88417bff20162f635f24f849ab182b092697922088b477a7abd6664ddd82291d"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c707f7afd813478e2019ae32a7c49cd932dd60ab2d2a93e796f68236b7e1fbf1"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:580afc7b7216deeb87a098ef0674d6ee34ab55993140838b14c9b83312b37b86"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1e91467c65fe64a82c689dc6cf58151158993b13eb7a7f3f4b7f395636723"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84"}, - {file = "cryptography-41.0.5.tar.gz", hash = "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7"}, -] - -[package.dependencies] -cffi = ">=1.12" - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -nox = ["nox"] -pep8test = ["black", "check-sdist", "mypy", "ruff"] -sdist = ["build"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "dask" -version = "2023.10.0" -description = "Parallel PyData with Task Scheduling" -optional = false -python-versions = ">=3.9" -files = [ - {file = "dask-2023.10.0-py3-none-any.whl", hash = "sha256:cb133919ff6f1fc021efe1eef24df0e4acecf33a7708e7b04d2dea6b45e166bb"}, - {file = "dask-2023.10.0.tar.gz", hash = "sha256:3fdfdbdb5f9f3a556487bf37142e5a730dab2f2c8eca0b6c79d11199c30220e3"}, -] - -[package.dependencies] -click = ">=8.0" -cloudpickle = ">=1.5.0" -fsspec = ">=2021.09.0" -importlib-metadata = ">=4.13.0" -packaging = ">=20.0" -partd = ">=1.2.0" -pyyaml = ">=5.3.1" -toolz = ">=0.10.0" - -[package.extras] -array = ["numpy (>=1.21)"] -complete = ["dask[array,dataframe,diagnostics,distributed]", "lz4 (>=4.3.2)", "pyarrow (>=7.0)"] -dataframe = ["dask[array]", "pandas (>=1.3)"] -diagnostics = ["bokeh (>=2.4.2)", "jinja2 (>=2.10.3)"] -distributed = ["distributed (==2023.10.0)"] -test = ["pandas[test]", "pre-commit", "pytest", "pytest-cov", "pytest-rerunfailures", "pytest-timeout", "pytest-xdist"] - -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - -[[package]] -name = "distlib" -version = "0.3.7" -description = "Distribution utilities" -optional = false -python-versions = "*" -files = [ - {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, - {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, -] - -[[package]] -name = "docutils" -version = "0.20.1" -description = "Docutils -- Python Documentation Utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, - {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, -] - -[[package]] -name = "dulwich" -version = "0.21.6" -description = "Python Git Library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "dulwich-0.21.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7f89bee4c97372e8aaf8ffaf5899f1bcd5184b5306d7eaf68738c1101ceba10e"}, - {file = "dulwich-0.21.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:847bb52562a211b596453a602e75739350c86d7edb846b5b1c46896a5c86b9bb"}, - {file = "dulwich-0.21.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e09d0b4e985b371aa6728773781b19298d361a00772e20f98522868cf7edc6f"}, - {file = "dulwich-0.21.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dfb50b3915e223a97f50fbac0dbc298d5fffeaac004eeeb3d552c57fe38416f"}, - {file = "dulwich-0.21.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a64eca1601e79c16df78afe08da9ac9497b934cbc5765990ca7d89a4b87453d9"}, - {file = "dulwich-0.21.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1fedd924763a5d640348db43a267a394aa80d551228ad45708e0b0cc2130bb62"}, - {file = "dulwich-0.21.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:edc21c3784dd9d9b85abd9fe53f81a884e2cdcc4e5e09ada17287420d64cfd46"}, - {file = "dulwich-0.21.6-cp310-cp310-win32.whl", hash = "sha256:daa3584beabfcf0da76df57535a23c80ff6d8ccde6ddbd23bdc79d317a0e20a7"}, - {file = "dulwich-0.21.6-cp310-cp310-win_amd64.whl", hash = "sha256:40623cc39a3f1634663d22d87f86e2e406cc8ff17ae7a3edc7fcf963c288992f"}, - {file = "dulwich-0.21.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e8ed878553f0b76facbb620b455fafa0943162fe8e386920717781e490444efa"}, - {file = "dulwich-0.21.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a89b19f4960e759915dbc23a4dd0abc067b55d8d65e9df50961b73091b87b81a"}, - {file = "dulwich-0.21.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28acbd08d6b38720d99cc01da9dd307a2e0585e00436c95bcac6357b9a9a6f76"}, - {file = "dulwich-0.21.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2f2683e0598f7c7071ef08a0822f062d8744549a0d45f2c156741033b7e3d7d"}, - {file = "dulwich-0.21.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54342cf96fe8a44648505c65f23d18889595762003a168d67d7263df66143bd2"}, - {file = "dulwich-0.21.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2a3fc071e5b14f164191286f7ffc02f60fe8b439d01fad0832697cc08c2237dd"}, - {file = "dulwich-0.21.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32d7acfe3fe2ce4502446d8f7a5ab34cfd24c9ff8961e60337638410906a8fbb"}, - {file = "dulwich-0.21.6-cp311-cp311-win32.whl", hash = "sha256:5e58171a5d70f7910f73d25ff82a058edff09a4c1c3bd1de0dc6b1fbc9a42c3e"}, - {file = "dulwich-0.21.6-cp311-cp311-win_amd64.whl", hash = "sha256:ceabe8f96edfb9183034a860f5dc77586700b517457032867b64a03c44e5cf96"}, - {file = "dulwich-0.21.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4fdc2f081bc3e9e120079c2cea4be213e3f127335aca7c0ab0c19fe791270caa"}, - {file = "dulwich-0.21.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fe957564108f74325d0d042d85e0c67ef470921ca92b6e7d330c7c49a3b9c1d"}, - {file = "dulwich-0.21.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2912c8a845c8ccbc79d068a89db7172e355adeb84eb31f062cd3a406d528b30"}, - {file = "dulwich-0.21.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:81e237a6b1b20c79ef62ca19a8fb231f5519bab874b9a1c2acf9c05edcabd600"}, - {file = "dulwich-0.21.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:513d045e74307eeb31592255c38f37042c9aa68ce845a167943018ab5138b0e3"}, - {file = "dulwich-0.21.6-cp37-cp37m-win32.whl", hash = "sha256:e1ac882afa890ef993b8502647e6c6d2b3977ce56e3fe80058ce64607cbc7107"}, - {file = "dulwich-0.21.6-cp37-cp37m-win_amd64.whl", hash = "sha256:5d2ccf3d355850674f75655154a6519bf1f1664176c670109fa7041019b286f9"}, - {file = "dulwich-0.21.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:28c9724a167c84a83fc6238e0781f4702b5fe8c53ede31604525fb1a9d1833f4"}, - {file = "dulwich-0.21.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c816be529680659b6a19798287b4ec6de49040f58160d40b1b2934fd6c28e93f"}, - {file = "dulwich-0.21.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b0545f0fa9444a0eb84977d08e302e3f55fd7c34a0466ec28bedc3c839b2fc1f"}, - {file = "dulwich-0.21.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b1682e8e826471ea3c22b8521435e93799e3db8ad05dd3c8f9b1aaacfa78147"}, - {file = "dulwich-0.21.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ad45928a65f39ea0f451f9989b7aaedba9893d48c3189b544a70c6a1043f71"}, - {file = "dulwich-0.21.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1c9e55233f19cd19c484f607cd90ab578ac50ebfef607f77e3b35c2b6049470"}, - {file = "dulwich-0.21.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:18697b58e0fc5972de68b529b08ac9ddda3f39af27bcf3f6999635ed3da7ef68"}, - {file = "dulwich-0.21.6-cp38-cp38-win32.whl", hash = "sha256:22798e9ba59e32b8faff5d9067e2b5a308f6b0fba9b1e1e928571ad278e7b36c"}, - {file = "dulwich-0.21.6-cp38-cp38-win_amd64.whl", hash = "sha256:6c91e1ed20d3d9a6aaaed9e75adae37272b3fcbcc72bab1eb09574806da88563"}, - {file = "dulwich-0.21.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8b84450766a3b151c3676fec3e3ed76304e52a84d5d69ade0f34fff2782c1b41"}, - {file = "dulwich-0.21.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3da632648ee27b64bb5b285a3a94fddf297a596891cca12ac0df43c4f59448f"}, - {file = "dulwich-0.21.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cef50c0a19f322b7150248b8fa0862ce1652dec657e340c4020573721e85f215"}, - {file = "dulwich-0.21.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ac20dfcfd6057efb8499158d23f2c059f933aefa381e192100e6d8bc25d562"}, - {file = "dulwich-0.21.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81d10aa50c0a9a6dd495990c639358e3a3bbff39e17ff302179be6e93b573da7"}, - {file = "dulwich-0.21.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a9b52a08d49731375662936d05a12c4a64a6fe0ce257111f62638e475fb5d26d"}, - {file = "dulwich-0.21.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed2f1f638b9adfba862719693b371ffe5d58e94d552ace9a23dea0fb0db6f468"}, - {file = "dulwich-0.21.6-cp39-cp39-win32.whl", hash = "sha256:bf90f2f9328a82778cf85ab696e4a7926918c3f315c75fc432ba31346bfa89b7"}, - {file = "dulwich-0.21.6-cp39-cp39-win_amd64.whl", hash = "sha256:e0dee3840c3c72e1d60c8f87a7a715d8eac023b9e1b80199d97790f7a1c60d9c"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:32d3a35caad6879d04711b358b861142440a543f5f4e02df67b13cbcd57f84a6"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c04df87098053b7767b46fc04b7943d75443f91c73560ca50157cdc22e27a5d3"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e07f145c7b0d82a9f77d157f493a61900e913d1c1f8b1f40d07d919ffb0929a4"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:008ff08629ab16d3638a9f36cfc6f5bd74b4d594657f2dc1583d8d3201794571"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bf469cd5076623c2aad69d01ce9d5392fcb38a5faef91abe1501be733453e37d"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6592ef2d16ac61a27022647cf64a048f5be6e0a6ab2ebc7322bfbe24fb2b971b"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99577b2b37f64bc87280079245fb2963494c345d7db355173ecec7ab3d64b949"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d7cd9fb896c65e4c28cb9332f2be192817805978dd8dc299681c4fe83c631158"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9002094198e57e88fe77412d3aa64dd05978046ae725a16123ba621a7704628"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9b6f8a16f32190aa88c37ef013858b3e01964774bc983900bd0d74ecb6576e6"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee8aba4dec4d0a52737a8a141f3456229c87dcfd7961f8115786a27b6ebefed"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a780e2a0ff208c4f218e72eff8d13f9aff485ff9a6f3066c22abe4ec8cec7dcd"}, - {file = "dulwich-0.21.6.tar.gz", hash = "sha256:30fbe87e8b51f3813c131e2841c86d007434d160bd16db586b40d47f31dd05b0"}, -] - -[package.dependencies] -urllib3 = ">=1.25" - -[package.extras] -fastimport = ["fastimport"] -https = ["urllib3 (>=1.24.1)"] -paramiko = ["paramiko"] -pgp = ["gpg"] - -[[package]] -name = "exceptiongroup" -version = "1.1.3" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "fasteners" -version = "0.19" -description = "A python package that provides useful locks" -optional = false -python-versions = ">=3.6" -files = [ - {file = "fasteners-0.19-py3-none-any.whl", hash = "sha256:758819cb5d94cdedf4e836988b74de396ceacb8e2794d21f82d131fd9ee77237"}, - {file = "fasteners-0.19.tar.gz", hash = "sha256:b4f37c3ac52d8a445af3a66bce57b33b5e90b97c696b7b984f530cf8f0ded09c"}, -] - -[[package]] -name = "fastjsonschema" -version = "2.18.1" -description = "Fastest Python implementation of JSON schema" -optional = false -python-versions = "*" -files = [ - {file = "fastjsonschema-2.18.1-py3-none-any.whl", hash = "sha256:aec6a19e9f66e9810ab371cc913ad5f4e9e479b63a7072a2cd060a9369e329a8"}, - {file = "fastjsonschema-2.18.1.tar.gz", hash = "sha256:06dc8680d937628e993fa0cd278f196d20449a1adc087640710846b324d422ea"}, -] - -[package.extras] -devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] - -[[package]] -name = "filelock" -version = "3.13.0" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.8" -files = [ - {file = "filelock-3.13.0-py3-none-any.whl", hash = "sha256:a552f4fde758f4eab33191e9548f671970f8b06d436d31388c9aa1e5861a710f"}, - {file = "filelock-3.13.0.tar.gz", hash = "sha256:63c6052c82a1a24c873a549fbd39a26982e8f35a3016da231ead11a5be9dad44"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] -typing = ["typing-extensions (>=4.8)"] - -[[package]] -name = "flake8" -version = "4.0.1" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, -] - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" - -[[package]] -name = "fsspec" -version = "2023.10.0" -description = "File-system specification" -optional = false -python-versions = ">=3.8" -files = [ - {file = "fsspec-2023.10.0-py3-none-any.whl", hash = "sha256:346a8f024efeb749d2a5fca7ba8854474b1ff9af7c3faaf636a4548781136529"}, - {file = "fsspec-2023.10.0.tar.gz", hash = "sha256:330c66757591df346ad3091a53bd907e15348c2ba17d63fd54f5c39c4457d2a5"}, -] - -[package.extras] -abfs = ["adlfs"] -adl = ["adlfs"] -arrow = ["pyarrow (>=1)"] -dask = ["dask", "distributed"] -devel = ["pytest", "pytest-cov"] -dropbox = ["dropbox", "dropboxdrivefs", "requests"] -full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] -fuse = ["fusepy"] -gcs = ["gcsfs"] -git = ["pygit2"] -github = ["requests"] -gs = ["gcsfs"] -gui = ["panel"] -hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] -libarchive = ["libarchive-c"] -oci = ["ocifs"] -s3 = ["s3fs"] -sftp = ["paramiko"] -smb = ["smbprotocol"] -ssh = ["paramiko"] -tqdm = ["tqdm"] - -[[package]] -name = "identify" -version = "2.5.31" -description = "File identification library for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "identify-2.5.31-py2.py3-none-any.whl", hash = "sha256:90199cb9e7bd3c5407a9b7e81b4abec4bb9d249991c79439ec8af740afc6293d"}, - {file = "identify-2.5.31.tar.gz", hash = "sha256:7736b3c7a28233637e3c36550646fc6389bedd74ae84cb788200cc8e2dd60b75"}, -] - -[package.extras] -license = ["ukkonen"] - -[[package]] -name = "idna" -version = "3.4" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] - -[[package]] -name = "imagesize" -version = "1.4.1" -description = "Getting image size from png/jpeg/jpeg2000/gif file" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, - {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, -] - -[[package]] -name = "importlib-metadata" -version = "6.8.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "installer" -version = "0.7.0" -description = "A library for installing Python wheels." -optional = false -python-versions = ">=3.7" -files = [ - {file = "installer-0.7.0-py3-none-any.whl", hash = "sha256:05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53"}, - {file = "installer-0.7.0.tar.gz", hash = "sha256:a26d3e3116289bb08216e0d0f7d925fcef0b0194eedfa0c944bcaaa106c4b631"}, -] - -[[package]] -name = "jaraco-classes" -version = "3.3.0" -description = "Utility functions for Python class constructs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jaraco.classes-3.3.0-py3-none-any.whl", hash = "sha256:10afa92b6743f25c0cf5f37c6bb6e18e2c5bb84a16527ccfc0040ea377e7aaeb"}, - {file = "jaraco.classes-3.3.0.tar.gz", hash = "sha256:c063dd08e89217cee02c8d5e5ec560f2c8ce6cdc2fcdc2e68f7b2e5547ed3621"}, -] - -[package.dependencies] -more-itertools = "*" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[[package]] -name = "jeepney" -version = "0.8.0" -description = "Low-level, pure Python DBus protocol wrapper." -optional = false -python-versions = ">=3.7" -files = [ - {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"}, - {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"}, -] - -[package.extras] -test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] -trio = ["async_generator", "trio"] - -[[package]] -name = "jinja2" -version = "3.1.2" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "joblib" -version = "1.3.2" -description = "Lightweight pipelining with Python functions" -optional = false -python-versions = ">=3.7" -files = [ - {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, - {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, -] - -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[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 (>=1.11)"] - -[[package]] -name = "jupyter-client" -version = "8.4.0" -description = "Jupyter protocol implementation and client libraries" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_client-8.4.0-py3-none-any.whl", hash = "sha256:6a2a950ec23a8f62f9e4c66acec7f0ea6c7d1f80ba0992e747b10c56ce2e6dbe"}, - {file = "jupyter_client-8.4.0.tar.gz", hash = "sha256:dc1b857d5d7d76ac101766c6e9b646bf18742721126e72e5d484c75a993cada2"}, -] - -[package.dependencies] -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -python-dateutil = ">=2.8.2" -pyzmq = ">=23.0" -tornado = ">=6.2" -traitlets = ">=5.3" - -[package.extras] -docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] - -[[package]] -name = "jupyter-core" -version = "5.4.0" -description = "Jupyter core package. A base package on which Jupyter projects rely." -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_core-5.4.0-py3-none-any.whl", hash = "sha256:66e252f675ac04dcf2feb6ed4afb3cd7f68cf92f483607522dc251f32d471571"}, - {file = "jupyter_core-5.4.0.tar.gz", hash = "sha256:e4b98344bb94ee2e3e6c4519a97d001656009f9cb2b7f2baf15b3c205770011d"}, -] - -[package.dependencies] -platformdirs = ">=2.5" -pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} -traitlets = ">=5.3" - -[package.extras] -docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] -test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "jupyterlab-pygments" -version = "0.2.2" -description = "Pygments theme using JupyterLab CSS variables" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, - {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, -] - -[[package]] -name = "keyring" -version = "24.2.0" -description = "Store and access your passwords safely." -optional = false -python-versions = ">=3.8" -files = [ - {file = "keyring-24.2.0-py3-none-any.whl", hash = "sha256:4901caaf597bfd3bbd78c9a0c7c4c29fcd8310dab2cffefe749e916b6527acd6"}, - {file = "keyring-24.2.0.tar.gz", hash = "sha256:ca0746a19ec421219f4d713f848fa297a661a8a8c1504867e55bfb5e09091509"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.11.4", markers = "python_version < \"3.12\""} -"jaraco.classes" = "*" -jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} -pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} -SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} - -[package.extras] -completion = ["shtab"] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[[package]] -name = "llvmlite" -version = "0.40.1" -description = "lightweight wrapper around basic LLVM functionality" -optional = false -python-versions = ">=3.8" -files = [ - {file = "llvmlite-0.40.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ce9b1c7a59936382ffde7871978cddcda14098e5a76d961e204523e5c372fb"}, - {file = "llvmlite-0.40.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3673c53cb21c65d2ff3704962b5958e967c6fc0bd0cff772998face199e8d87b"}, - {file = "llvmlite-0.40.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bba2747cf5b4954e945c287fe310b3fcc484e2a9d1b0c273e99eb17d103bb0e6"}, - {file = "llvmlite-0.40.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbd5e82cc990e5a3e343a3bf855c26fdfe3bfae55225f00efd01c05bbda79918"}, - {file = "llvmlite-0.40.1-cp310-cp310-win32.whl", hash = "sha256:09f83ea7a54509c285f905d968184bba00fc31ebf12f2b6b1494d677bb7dde9b"}, - {file = "llvmlite-0.40.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b37297f3cbd68d14a97223a30620589d98ad1890e5040c9e5fc181063f4ed49"}, - {file = "llvmlite-0.40.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a66a5bd580951751b4268f4c3bddcef92682814d6bc72f3cd3bb67f335dd7097"}, - {file = "llvmlite-0.40.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:467b43836b388eaedc5a106d76761e388dbc4674b2f2237bc477c6895b15a634"}, - {file = "llvmlite-0.40.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c23edd196bd797dc3a7860799054ea3488d2824ecabc03f9135110c2e39fcbc"}, - {file = "llvmlite-0.40.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a36d9f244b6680cb90bbca66b146dabb2972f4180c64415c96f7c8a2d8b60a36"}, - {file = "llvmlite-0.40.1-cp311-cp311-win_amd64.whl", hash = "sha256:5b3076dc4e9c107d16dc15ecb7f2faf94f7736cd2d5e9f4dc06287fd672452c1"}, - {file = "llvmlite-0.40.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a7525db121f2e699809b539b5308228854ccab6693ecb01b52c44a2f5647e20"}, - {file = "llvmlite-0.40.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:84747289775d0874e506f907a4513db889471607db19b04de97d144047fec885"}, - {file = "llvmlite-0.40.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e35766e42acef0fe7d1c43169a8ffc327a47808fae6a067b049fe0e9bbf84dd5"}, - {file = "llvmlite-0.40.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cda71de10a1f48416309e408ea83dab5bf36058f83e13b86a2961defed265568"}, - {file = "llvmlite-0.40.1-cp38-cp38-win32.whl", hash = "sha256:96707ebad8b051bbb4fc40c65ef93b7eeee16643bd4d579a14d11578e4b7a647"}, - {file = "llvmlite-0.40.1-cp38-cp38-win_amd64.whl", hash = "sha256:e44f854dc11559795bcdeaf12303759e56213d42dabbf91a5897aa2d8b033810"}, - {file = "llvmlite-0.40.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f643d15aacd0b0b0dc8b74b693822ba3f9a53fa63bc6a178c2dba7cc88f42144"}, - {file = "llvmlite-0.40.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:39a0b4d0088c01a469a5860d2e2d7a9b4e6a93c0f07eb26e71a9a872a8cadf8d"}, - {file = "llvmlite-0.40.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9329b930d699699846623054121ed105fd0823ed2180906d3b3235d361645490"}, - {file = "llvmlite-0.40.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2dbbb8424037ca287983b115a29adf37d806baf7e1bf4a67bd2cffb74e085ed"}, - {file = "llvmlite-0.40.1-cp39-cp39-win32.whl", hash = "sha256:e74e7bec3235a1e1c9ad97d897a620c5007d0ed80c32c84c1d787e7daa17e4ec"}, - {file = "llvmlite-0.40.1-cp39-cp39-win_amd64.whl", hash = "sha256:ff8f31111bb99d135ff296757dc81ab36c2dee54ed4bd429158a96da9807c316"}, - {file = "llvmlite-0.40.1.tar.gz", hash = "sha256:5cdb0d45df602099d833d50bd9e81353a5e036242d3c003c5b294fc61d1986b4"}, -] - -[[package]] -name = "locket" -version = "1.0.0" -description = "File-based locks for Python on Linux and Windows" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "locket-1.0.0-py2.py3-none-any.whl", hash = "sha256:b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3"}, - {file = "locket-1.0.0.tar.gz", hash = "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632"}, -] - -[[package]] -name = "markupsafe" -version = "2.1.3" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, -] - -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = "*" -files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] - -[[package]] -name = "mistune" -version = "3.0.2" -description = "A sane and fast Markdown parser with useful plugins and renderers" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, - {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, -] - -[[package]] -name = "more-itertools" -version = "10.1.0" -description = "More routines for operating on iterables, beyond itertools" -optional = false -python-versions = ">=3.8" -files = [ - {file = "more-itertools-10.1.0.tar.gz", hash = "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a"}, - {file = "more_itertools-10.1.0-py3-none-any.whl", hash = "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6"}, -] - -[[package]] -name = "msgpack" -version = "1.0.7" -description = "MessagePack serializer" -optional = false -python-versions = ">=3.8" -files = [ - {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862"}, - {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329"}, - {file = "msgpack-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b"}, - {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6"}, - {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee"}, - {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d"}, - {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d"}, - {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1"}, - {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681"}, - {file = "msgpack-1.0.7-cp310-cp310-win32.whl", hash = "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9"}, - {file = "msgpack-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415"}, - {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84"}, - {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93"}, - {file = "msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8"}, - {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46"}, - {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b"}, - {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e"}, - {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002"}, - {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c"}, - {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e"}, - {file = "msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1"}, - {file = "msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82"}, - {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b"}, - {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4"}, - {file = "msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee"}, - {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5"}, - {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672"}, - {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075"}, - {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba"}, - {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c"}, - {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5"}, - {file = "msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9"}, - {file = "msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf"}, - {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5b6ccc0c85916998d788b295765ea0e9cb9aac7e4a8ed71d12e7d8ac31c23c95"}, - {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:235a31ec7db685f5c82233bddf9858748b89b8119bf4538d514536c485c15fe0"}, - {file = "msgpack-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cab3db8bab4b7e635c1c97270d7a4b2a90c070b33cbc00c99ef3f9be03d3e1f7"}, - {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bfdd914e55e0d2c9e1526de210f6fe8ffe9705f2b1dfcc4aecc92a4cb4b533d"}, - {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36e17c4592231a7dbd2ed09027823ab295d2791b3b1efb2aee874b10548b7524"}, - {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38949d30b11ae5f95c3c91917ee7a6b239f5ec276f271f28638dec9156f82cfc"}, - {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ff1d0899f104f3921d94579a5638847f783c9b04f2d5f229392ca77fba5b82fc"}, - {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dc43f1ec66eb8440567186ae2f8c447d91e0372d793dfe8c222aec857b81a8cf"}, - {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dd632777ff3beaaf629f1ab4396caf7ba0bdd075d948a69460d13d44357aca4c"}, - {file = "msgpack-1.0.7-cp38-cp38-win32.whl", hash = "sha256:4e71bc4416de195d6e9b4ee93ad3f2f6b2ce11d042b4d7a7ee00bbe0358bd0c2"}, - {file = "msgpack-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:8f5b234f567cf76ee489502ceb7165c2a5cecec081db2b37e35332b537f8157c"}, - {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfef2bb6ef068827bbd021017a107194956918ab43ce4d6dc945ffa13efbc25f"}, - {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:484ae3240666ad34cfa31eea7b8c6cd2f1fdaae21d73ce2974211df099a95d81"}, - {file = "msgpack-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3967e4ad1aa9da62fd53e346ed17d7b2e922cba5ab93bdd46febcac39be636fc"}, - {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dd178c4c80706546702c59529ffc005681bd6dc2ea234c450661b205445a34d"}, - {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ffbc252eb0d229aeb2f9ad051200668fc3a9aaa8994e49f0cb2ffe2b7867e7"}, - {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:822ea70dc4018c7e6223f13affd1c5c30c0f5c12ac1f96cd8e9949acddb48a61"}, - {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:384d779f0d6f1b110eae74cb0659d9aa6ff35aaf547b3955abf2ab4c901c4819"}, - {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f64e376cd20d3f030190e8c32e1c64582eba56ac6dc7d5b0b49a9d44021b52fd"}, - {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ed82f5a7af3697b1c4786053736f24a0efd0a1b8a130d4c7bfee4b9ded0f08f"}, - {file = "msgpack-1.0.7-cp39-cp39-win32.whl", hash = "sha256:f26a07a6e877c76a88e3cecac8531908d980d3d5067ff69213653649ec0f60ad"}, - {file = "msgpack-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:1dc93e8e4653bdb5910aed79f11e165c85732067614f180f70534f056da97db3"}, - {file = "msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "nbclient" -version = "0.8.0" -description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "nbclient-0.8.0-py3-none-any.whl", hash = "sha256:25e861299e5303a0477568557c4045eccc7a34c17fc08e7959558707b9ebe548"}, - {file = "nbclient-0.8.0.tar.gz", hash = "sha256:f9b179cd4b2d7bca965f900a2ebf0db4a12ebff2f36a711cb66861e4ae158e55"}, -] - -[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", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] -test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] - -[[package]] -name = "nbconvert" -version = "7.9.2" -description = "Converting Jupyter Notebooks" -optional = false -python-versions = ">=3.8" -files = [ - {file = "nbconvert-7.9.2-py3-none-any.whl", hash = "sha256:39fe4b8bdd1b0104fdd86fc8a43a9077ba64c720bda4c6132690d917a0a154ee"}, - {file = "nbconvert-7.9.2.tar.gz", hash = "sha256:e56cc7588acc4f93e2bb5a34ec69028e4941797b2bfaf6462f18a41d1cc258c9"}, -] - -[package.dependencies] -beautifulsoup4 = "*" -bleach = "!=5.0.0" -defusedxml = "*" -jinja2 = ">=3.0" -jupyter-core = ">=4.7" -jupyterlab-pygments = "*" -markupsafe = ">=2.0" -mistune = ">=2.0.3,<4" -nbclient = ">=0.5.0" -nbformat = ">=5.7" -packaging = "*" -pandocfilters = ">=1.4.1" -pygments = ">=2.4.1" -tinycss2 = "*" -traitlets = ">=5.1" - -[package.extras] -all = ["nbconvert[docs,qtpdf,serve,test,webpdf]"] -docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] -qtpdf = ["nbconvert[qtpng]"] -qtpng = ["pyqtwebengine (>=5.15)"] -serve = ["tornado (>=6.1)"] -test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pytest", "pytest-dependency"] -webpdf = ["playwright"] - -[[package]] -name = "nbformat" -version = "5.9.2" -description = "The Jupyter Notebook format" -optional = false -python-versions = ">=3.8" -files = [ - {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"}, - {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"}, -] - -[package.dependencies] -fastjsonschema = "*" -jsonschema = ">=2.6" -jupyter-core = "*" -traitlets = ">=5.1" - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["pep440", "pre-commit", "pytest", "testpath"] - -[[package]] -name = "nbsphinx" -version = "0.9.3" -description = "Jupyter Notebook Tools for Sphinx" -optional = false -python-versions = ">=3.6" -files = [ - {file = "nbsphinx-0.9.3-py3-none-any.whl", hash = "sha256:6e805e9627f4a358bd5720d5cbf8bf48853989c79af557afd91a5f22e163029f"}, - {file = "nbsphinx-0.9.3.tar.gz", hash = "sha256:ec339c8691b688f8676104a367a4b8cf3ea01fd089dc28d24dec22d563b11562"}, -] - -[package.dependencies] -docutils = "*" -jinja2 = "*" -nbconvert = "!=5.4" -nbformat = "*" -sphinx = ">=1.8" -traitlets = ">=5" - -[[package]] -name = "netcdf4" -version = "1.6.4" -description = "Provides an object-oriented python interface to the netCDF version 4 library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "netCDF4-1.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:59eba11eac34f9c7bd209121b26954c71ff69a2eb2838d2ac339b39ea60a95c0"}, - {file = "netCDF4-1.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:541286ce7318033b326da2e4325f08037b561887d5fd25d12c2b0cad74eb1edc"}, - {file = "netCDF4-1.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6620f7962daff02df2fbcbc8f7af53edf21512bc7f5697d846d424a094f96345"}, - {file = "netCDF4-1.6.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dcf74f7b15ae6105c09df93af22ad61366a288fbb329fdbe3b9606c56c788f5"}, - {file = "netCDF4-1.6.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b368fc185cac7d8890a8cf1016488cd252a144008144d06a615925b09bf8d67e"}, - {file = "netCDF4-1.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:eb19c51fa090b562be4f87ff736b629ffafc03d7bf1fa10f623f957d49417b4f"}, - {file = "netCDF4-1.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a7efab50d5a4da6227244e544a74f676b732ccdff2b8a4678174c15a3f8dff"}, - {file = "netCDF4-1.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9b7ad3f66d50970fa1bd5509c52bb8a99740c8a79fafa83bfd0bc7348b6ab5a"}, - {file = "netCDF4-1.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c5cad50d4e6e5a3b35c76862c58393ddf93baa44de98b6e040ac21896145881"}, - {file = "netCDF4-1.6.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c2395c53a37717b1047650e1c9de68a3d69542bb25df5c594e1e14e9480bb18"}, - {file = "netCDF4-1.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:c85f77599c61a88d512d6536e181ff1c01fd16f4740367e4f8e5cacb36500293"}, - {file = "netCDF4-1.6.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e3efefdb9fc936503e89ff5b40b33f2c96527bae1e9672a2d369c5f7cb30bbd"}, - {file = "netCDF4-1.6.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74a3e720a9764d13d669763c1f3c73f3f719ef181dccecad062440eea03f069e"}, - {file = "netCDF4-1.6.4-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c67bc7fafced3f9370fdef6ce7abe235a771bed7ebe534f4ba3c84d9689dae23"}, - {file = "netCDF4-1.6.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b599a3b5c0d0e3affa70d7954c2b0c4ab7d7bdb52b0e413c811da9725982de33"}, - {file = "netCDF4-1.6.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b21d47c23edd02ff83160c8ccc1e4d4946a91d454b246e7f63d7a6d63901707c"}, - {file = "netCDF4-1.6.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8eff69acdf250ebaf817cc9bbfb457d241f92f989c7f9cca33eb29985c0f9797"}, - {file = "netCDF4-1.6.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d6bcdf27fd611eaec891f4281caf5c56bbad6f5fc245ce3e6dd2dc4fc3fad56"}, - {file = "netCDF4-1.6.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99a3d476242d489da26f71e318ddd314723ca766f4db11270863a764b107bc3"}, - {file = "netCDF4-1.6.4-cp38-cp38-win_amd64.whl", hash = "sha256:422077c7303cb17cbe8b9ace965cafda1f9d4c9b035809fc5c87091e7ff4d606"}, - {file = "netCDF4-1.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0050e49889c357ae0a73f96e2b9988f250396689b78142de88a39ac8b1e702aa"}, - {file = "netCDF4-1.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a2cd2e2a9da98f1838e1edfeb011b840a434e04d156052b936ffe49f5298126"}, - {file = "netCDF4-1.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:695cd0a40df49b4218350686c44e13b3a4671e53ee33faf7439a89940cbccc68"}, - {file = "netCDF4-1.6.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e582e6e41b27fc3a3296239afe065941bda60118d585df0ad41603f6f962888e"}, - {file = "netCDF4-1.6.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7b4ab3f0cd28a6685031e8b9be00c3047b4256da576c9de540440d013a31cea"}, - {file = "netCDF4-1.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:1a950b3d8fcffca05e371a4cb64dc76580375588d1fca43b788192f409108ebe"}, - {file = "netCDF4-1.6.4.tar.gz", hash = "sha256:66da6542cbc7a6045cd1d979397dfd5a3f6c880c76d52b8f98bb108c82ee8c6e"}, -] - -[package.dependencies] -certifi = "*" -cftime = "*" -numpy = "*" - -[[package]] -name = "nodeenv" -version = "1.8.0" -description = "Node.js virtual environment builder" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" -files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, -] - -[package.dependencies] -setuptools = "*" - -[[package]] -name = "numba" -version = "0.57.1" -description = "compiling Python code using LLVM" -optional = false -python-versions = ">=3.8" -files = [ - {file = "numba-0.57.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db8268eb5093cae2288942a8cbd69c9352f6fe6e0bfa0a9a27679436f92e4248"}, - {file = "numba-0.57.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:643cb09a9ba9e1bd8b060e910aeca455e9442361e80fce97690795ff9840e681"}, - {file = "numba-0.57.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:53e9fab973d9e82c9f8449f75994a898daaaf821d84f06fbb0b9de2293dd9306"}, - {file = "numba-0.57.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c0602e4f896e6a6d844517c3ab434bc978e7698a22a733cc8124465898c28fa8"}, - {file = "numba-0.57.1-cp310-cp310-win32.whl", hash = "sha256:3d6483c27520d16cf5d122868b79cad79e48056ecb721b52d70c126bed65431e"}, - {file = "numba-0.57.1-cp310-cp310-win_amd64.whl", hash = "sha256:a32ee263649aa3c3587b833d6311305379529570e6c20deb0c6f4fb5bc7020db"}, - {file = "numba-0.57.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c078f84b5529a7fdb8413bb33d5100f11ec7b44aa705857d9eb4e54a54ff505"}, - {file = "numba-0.57.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e447c4634d1cc99ab50d4faa68f680f1d88b06a2a05acf134aa6fcc0342adeca"}, - {file = "numba-0.57.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4838edef2df5f056cb8974670f3d66562e751040c448eb0b67c7e2fec1726649"}, - {file = "numba-0.57.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9b17fbe4a69dcd9a7cd49916b6463cd9a82af5f84911feeb40793b8bce00dfa7"}, - {file = "numba-0.57.1-cp311-cp311-win_amd64.whl", hash = "sha256:93df62304ada9b351818ba19b1cfbddaf72cd89348e81474326ca0b23bf0bae1"}, - {file = "numba-0.57.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8e00ca63c5d0ad2beeb78d77f087b3a88c45ea9b97e7622ab2ec411a868420ee"}, - {file = "numba-0.57.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ff66d5b022af6c7d81ddbefa87768e78ed4f834ab2da6ca2fd0d60a9e69b94f5"}, - {file = "numba-0.57.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:60ec56386076e9eed106a87c96626d5686fbb16293b9834f0849cf78c9491779"}, - {file = "numba-0.57.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c057ccedca95df23802b6ccad86bb318be624af45b5a38bb8412882be57a681"}, - {file = "numba-0.57.1-cp38-cp38-win32.whl", hash = "sha256:5a82bf37444039c732485c072fda21a361790ed990f88db57fd6941cd5e5d307"}, - {file = "numba-0.57.1-cp38-cp38-win_amd64.whl", hash = "sha256:9bcc36478773ce838f38afd9a4dfafc328d4ffb1915381353d657da7f6473282"}, - {file = "numba-0.57.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae50c8c90c2ce8057f9618b589223e13faa8cbc037d8f15b4aad95a2c33a0582"}, - {file = "numba-0.57.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9a1b2b69448e510d672ff9a6b18d2db9355241d93c6a77677baa14bec67dc2a0"}, - {file = "numba-0.57.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3cf78d74ad9d289fbc1e5b1c9f2680fca7a788311eb620581893ab347ec37a7e"}, - {file = "numba-0.57.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f47dd214adc5dcd040fe9ad2adbd2192133c9075d2189ce1b3d5f9d72863ef05"}, - {file = "numba-0.57.1-cp39-cp39-win32.whl", hash = "sha256:a3eac19529956185677acb7f01864919761bfffbb9ae04bbbe5e84bbc06cfc2b"}, - {file = "numba-0.57.1-cp39-cp39-win_amd64.whl", hash = "sha256:9587ba1bf5f3035575e45562ada17737535c6d612df751e811d702693a72d95e"}, - {file = "numba-0.57.1.tar.gz", hash = "sha256:33c0500170d213e66d90558ad6aca57d3e03e97bb11da82e6d87ab793648cb17"}, -] - -[package.dependencies] -llvmlite = "==0.40.*" -numpy = ">=1.21,<1.25" - -[[package]] -name = "numcodecs" -version = "0.12.1" -description = "A Python package providing buffer compression and transformation codecs for use in data storage and communication applications." -optional = false -python-versions = ">=3.8" -files = [ - {file = "numcodecs-0.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d37f628fe92b3699e65831d5733feca74d2e33b50ef29118ffd41c13c677210e"}, - {file = "numcodecs-0.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:941b7446b68cf79f089bcfe92edaa3b154533dcbcd82474f994b28f2eedb1c60"}, - {file = "numcodecs-0.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e79bf9d1d37199ac00a60ff3adb64757523291d19d03116832e600cac391c51"}, - {file = "numcodecs-0.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:82d7107f80f9307235cb7e74719292d101c7ea1e393fe628817f0d635b7384f5"}, - {file = "numcodecs-0.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eeaf42768910f1c6eebf6c1bb00160728e62c9343df9e2e315dc9fe12e3f6071"}, - {file = "numcodecs-0.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:135b2d47563f7b9dc5ee6ce3d1b81b0f1397f69309e909f1a35bb0f7c553d45e"}, - {file = "numcodecs-0.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a191a8e347ecd016e5c357f2bf41fbcb026f6ffe78fff50c77ab12e96701d155"}, - {file = "numcodecs-0.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:21d8267bd4313f4d16f5b6287731d4c8ebdab236038f29ad1b0e93c9b2ca64ee"}, - {file = "numcodecs-0.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2f84df6b8693206365a5b37c005bfa9d1be486122bde683a7b6446af4b75d862"}, - {file = "numcodecs-0.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:760627780a8b6afdb7f942f2a0ddaf4e31d3d7eea1d8498cf0fd3204a33c4618"}, - {file = "numcodecs-0.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c258bd1d3dfa75a9b708540d23b2da43d63607f9df76dfa0309a7597d1de3b73"}, - {file = "numcodecs-0.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:e04649ea504aff858dbe294631f098fbfd671baf58bfc04fc48d746554c05d67"}, - {file = "numcodecs-0.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:caf1a1e6678aab9c1e29d2109b299f7a467bd4d4c34235b1f0e082167846b88f"}, - {file = "numcodecs-0.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c17687b1fd1fef68af616bc83f896035d24e40e04e91e7e6dae56379eb59fe33"}, - {file = "numcodecs-0.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29dfb195f835a55c4d490fb097aac8c1bcb96c54cf1b037d9218492c95e9d8c5"}, - {file = "numcodecs-0.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:2f1ba2f4af3fd3ba65b1bcffb717fe65efe101a50a91c368f79f3101dbb1e243"}, - {file = "numcodecs-0.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2fbb12a6a1abe95926f25c65e283762d63a9bf9e43c0de2c6a1a798347dfcb40"}, - {file = "numcodecs-0.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f2207871868b2464dc11c513965fd99b958a9d7cde2629be7b2dc84fdaab013b"}, - {file = "numcodecs-0.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abff3554a6892a89aacf7b642a044e4535499edf07aeae2f2e6e8fc08c9ba07f"}, - {file = "numcodecs-0.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:ef964d4860d3e6b38df0633caf3e51dc850a6293fd8e93240473642681d95136"}, - {file = "numcodecs-0.12.1.tar.gz", hash = "sha256:05d91a433733e7eef268d7e80ec226a0232da244289614a8f3826901aec1098e"}, -] - -[package.dependencies] -numpy = ">=1.7" - -[package.extras] -docs = ["mock", "numpydoc", "sphinx (<7.0.0)", "sphinx-issues"] -msgpack = ["msgpack"] -test = ["coverage", "flake8", "pytest", "pytest-cov"] -test-extras = ["importlib-metadata"] -zfpy = ["zfpy (>=1.0.0)"] - -[[package]] -name = "numpy" -version = "1.24.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.8" -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"}, -] - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "pandas" -version = "2.1.1" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pandas-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58d997dbee0d4b64f3cb881a24f918b5f25dd64ddf31f467bb9b67ae4c63a1e4"}, - {file = "pandas-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02304e11582c5d090e5a52aec726f31fe3f42895d6bfc1f28738f9b64b6f0614"}, - {file = "pandas-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffa8f0966de2c22de408d0e322db2faed6f6e74265aa0856f3824813cf124363"}, - {file = "pandas-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1f84c144dee086fe4f04a472b5cd51e680f061adf75c1ae4fc3a9275560f8f4"}, - {file = "pandas-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ce97667d06d69396d72be074f0556698c7f662029322027c226fd7a26965cb"}, - {file = "pandas-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:4c3f32fd7c4dccd035f71734df39231ac1a6ff95e8bdab8d891167197b7018d2"}, - {file = "pandas-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e2959720b70e106bb1d8b6eadd8ecd7c8e99ccdbe03ee03260877184bb2877d"}, - {file = "pandas-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25e8474a8eb258e391e30c288eecec565bfed3e026f312b0cbd709a63906b6f8"}, - {file = "pandas-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8bd1685556f3374520466998929bade3076aeae77c3e67ada5ed2b90b4de7f0"}, - {file = "pandas-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc3657869c7902810f32bd072f0740487f9e030c1a3ab03e0af093db35a9d14e"}, - {file = "pandas-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:05674536bd477af36aa2effd4ec8f71b92234ce0cc174de34fd21e2ee99adbc2"}, - {file = "pandas-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:b407381258a667df49d58a1b637be33e514b07f9285feb27769cedb3ab3d0b3a"}, - {file = "pandas-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c747793c4e9dcece7bb20156179529898abf505fe32cb40c4052107a3c620b49"}, - {file = "pandas-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3bcad1e6fb34b727b016775bea407311f7721db87e5b409e6542f4546a4951ea"}, - {file = "pandas-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5ec7740f9ccb90aec64edd71434711f58ee0ea7f5ed4ac48be11cfa9abf7317"}, - {file = "pandas-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29deb61de5a8a93bdd033df328441a79fcf8dd3c12d5ed0b41a395eef9cd76f0"}, - {file = "pandas-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4f99bebf19b7e03cf80a4e770a3e65eee9dd4e2679039f542d7c1ace7b7b1daa"}, - {file = "pandas-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:84e7e910096416adec68075dc87b986ff202920fb8704e6d9c8c9897fe7332d6"}, - {file = "pandas-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366da7b0e540d1b908886d4feb3d951f2f1e572e655c1160f5fde28ad4abb750"}, - {file = "pandas-2.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e50e72b667415a816ac27dfcfe686dc5a0b02202e06196b943d54c4f9c7693e"}, - {file = "pandas-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc1ab6a25da197f03ebe6d8fa17273126120874386b4ac11c1d687df288542dd"}, - {file = "pandas-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0dbfea0dd3901ad4ce2306575c54348d98499c95be01b8d885a2737fe4d7a98"}, - {file = "pandas-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0489b0e6aa3d907e909aef92975edae89b1ee1654db5eafb9be633b0124abe97"}, - {file = "pandas-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:4cdb0fab0400c2cb46dafcf1a0fe084c8bb2480a1fa8d81e19d15e12e6d4ded2"}, - {file = "pandas-2.1.1.tar.gz", hash = "sha256:fecb198dc389429be557cde50a2d46da8434a17fe37d7d41ff102e3987fd947b"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.22.4", markers = "python_version < \"3.11\""}, - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, -] -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.1" - -[package.extras] -all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"] -aws = ["s3fs (>=2022.05.0)"] -clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"] -compression = ["zstandard (>=0.17.0)"] -computation = ["scipy (>=1.8.1)", "xarray (>=2022.03.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pyxlsb (>=1.0.9)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)"] -feather = ["pyarrow (>=7.0.0)"] -fss = ["fsspec (>=2022.05.0)"] -gcp = ["gcsfs (>=2022.05.0)", "pandas-gbq (>=0.17.5)"] -hdf5 = ["tables (>=3.7.0)"] -html = ["beautifulsoup4 (>=4.11.1)", "html5lib (>=1.1)", "lxml (>=4.8.0)"] -mysql = ["SQLAlchemy (>=1.4.36)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.8.10)"] -parquet = ["pyarrow (>=7.0.0)"] -performance = ["bottleneck (>=1.3.4)", "numba (>=0.55.2)", "numexpr (>=2.8.0)"] -plot = ["matplotlib (>=3.6.1)"] -postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"] -spss = ["pyreadstat (>=1.1.5)"] -sql-other = ["SQLAlchemy (>=1.4.36)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.8.0)"] - -[[package]] -name = "pandocfilters" -version = "1.5.0" -description = "Utilities for writing pandoc filters in python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, - {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, -] - -[[package]] -name = "partd" -version = "1.4.1" -description = "Appendable key-value storage" -optional = false -python-versions = ">=3.7" -files = [ - {file = "partd-1.4.1-py3-none-any.whl", hash = "sha256:27e766663d36c161e2827aa3e28541c992f0b9527d3cca047e13fb3acdb989e6"}, - {file = "partd-1.4.1.tar.gz", hash = "sha256:56c25dd49e6fea5727e731203c466c6e092f308d8f0024e199d02f6aa2167f67"}, -] - -[package.dependencies] -locket = "*" -toolz = "*" - -[package.extras] -complete = ["blosc", "numpy (>=1.9.0)", "pandas (>=0.19.0)", "pyzmq"] - -[[package]] -name = "pathspec" -version = "0.11.2" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, -] - -[[package]] -name = "patsy" -version = "0.5.3" -description = "A Python package for describing statistical models and for building design matrices." -optional = false -python-versions = "*" -files = [ - {file = "patsy-0.5.3-py2.py3-none-any.whl", hash = "sha256:7eb5349754ed6aa982af81f636479b1b8db9d5b1a6e957a6016ec0534b5c86b7"}, - {file = "patsy-0.5.3.tar.gz", hash = "sha256:bdc18001875e319bc91c812c1eb6a10be4bb13cb81eb763f466179dca3b67277"}, -] - -[package.dependencies] -numpy = ">=1.4" -six = "*" - -[package.extras] -test = ["pytest", "pytest-cov", "scipy"] - -[[package]] -name = "pexpect" -version = "4.8.0" -description = "Pexpect allows easy control of interactive console applications." -optional = false -python-versions = "*" -files = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, -] - -[package.dependencies] -ptyprocess = ">=0.5" - -[[package]] -name = "pkginfo" -version = "1.9.6" -description = "Query metadata from sdists / bdists / installed packages." -optional = false -python-versions = ">=3.6" -files = [ - {file = "pkginfo-1.9.6-py3-none-any.whl", hash = "sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546"}, - {file = "pkginfo-1.9.6.tar.gz", hash = "sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046"}, -] - -[package.extras] -testing = ["pytest", "pytest-cov"] - -[[package]] -name = "platformdirs" -version = "3.11.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -optional = false -python-versions = ">=3.7" -files = [ - {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, - {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, -] - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] - -[[package]] -name = "pluggy" -version = "1.3.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, - {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "poetry" -version = "1.6.1" -description = "Python dependency management and packaging made easy." -optional = false -python-versions = ">=3.8,<4.0" -files = [ - {file = "poetry-1.6.1-py3-none-any.whl", hash = "sha256:9b4cb6079c08cc0d91e8cba18a6bd4d4f7d7830263a7fb18ecb3faa77937c988"}, - {file = "poetry-1.6.1.tar.gz", hash = "sha256:0ab9b1a592731cc8b252b8d6aaeea19c72cc0a109d7468b829ad57e6c48039d2"}, -] - -[package.dependencies] -build = ">=0.10.0,<0.11.0" -cachecontrol = {version = ">=0.13.0,<0.14.0", extras = ["filecache"]} -cleo = ">=2.0.0,<3.0.0" -crashtest = ">=0.4.1,<0.5.0" -dulwich = ">=0.21.2,<0.22.0" -installer = ">=0.7.0,<0.8.0" -jsonschema = ">=4.10.0,<4.18.0" -keyring = ">=24.0.0,<25.0.0" -packaging = ">=20.4" -pexpect = ">=4.7.0,<5.0.0" -pkginfo = ">=1.9.4,<2.0.0" -platformdirs = ">=3.0.0,<4.0.0" -poetry-core = "1.7.0" -poetry-plugin-export = ">=1.5.0,<2.0.0" -pyproject-hooks = ">=1.0.0,<2.0.0" -requests = ">=2.26,<3.0" -requests-toolbelt = ">=0.9.1,<2" -shellingham = ">=1.5,<2.0" -tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} -tomlkit = ">=0.11.4,<1.0.0" -trove-classifiers = ">=2022.5.19" -virtualenv = ">=20.22.0,<21.0.0" -xattr = {version = ">=0.10.0,<0.11.0", markers = "sys_platform == \"darwin\""} - -[[package]] -name = "poetry-core" -version = "1.7.0" -description = "Poetry PEP 517 Build Backend" -optional = false -python-versions = ">=3.8,<4.0" -files = [ - {file = "poetry_core-1.7.0-py3-none-any.whl", hash = "sha256:38e174cdb00a84ee4a1cab66a378b435747f72414f5573bc18cfc3850a94df38"}, - {file = "poetry_core-1.7.0.tar.gz", hash = "sha256:8f679b83bd9c820082637beca1204124d5d2a786e4818da47ec8acefd0353b74"}, -] - -[[package]] -name = "poetry-plugin-export" -version = "1.5.0" -description = "Poetry plugin to export the dependencies to various formats" -optional = false -python-versions = ">=3.8,<4.0" -files = [ - {file = "poetry_plugin_export-1.5.0-py3-none-any.whl", hash = "sha256:cd8267597970375ca29868daec5e7718bad500c7584663af3eeb0ed16f24e2bd"}, - {file = "poetry_plugin_export-1.5.0.tar.gz", hash = "sha256:ecc8738da0c81c3758e36b4e72e04ae59648a547492af2ffe6245af3594bb00f"}, -] - -[package.dependencies] -poetry = ">=1.5.0,<2.0.0" -poetry-core = ">=1.6.0,<2.0.0" - -[[package]] -name = "pooch" -version = "1.7.0" -description = "\"Pooch manages your Python library's sample data files: it automatically downloads and stores them in a local directory, with support for versioning and corruption checks.\"" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pooch-1.7.0-py3-none-any.whl", hash = "sha256:74258224fc33d58f53113cf955e8d51bf01386b91492927d0d1b6b341a765ad7"}, - {file = "pooch-1.7.0.tar.gz", hash = "sha256:f174a1041b6447f0eef8860f76d17f60ed2f857dc0efa387a7f08228af05d998"}, -] - -[package.dependencies] -packaging = ">=20.0" -platformdirs = ">=2.5.0" -requests = ">=2.19.0" - -[package.extras] -progress = ["tqdm (>=4.41.0,<5.0.0)"] -sftp = ["paramiko (>=2.7.0)"] -xxhash = ["xxhash (>=1.4.3)"] - -[[package]] -name = "pre-commit" -version = "3.5.0" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, - {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, -] - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" - -[[package]] -name = "ptyprocess" -version = "0.7.0" -description = "Run a subprocess in a pseudo terminal" -optional = false -python-versions = "*" -files = [ - {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, - {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, -] - -[[package]] -name = "pycodestyle" -version = "2.8.0" -description = "Python style guide checker" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, -] - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] - -[[package]] -name = "pydata-sphinx-theme" -version = "0.14.1" -description = "Bootstrap-based Sphinx theme from the PyData community" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydata_sphinx_theme-0.14.1-py3-none-any.whl", hash = "sha256:c436027bc76ae023df4e70517e3baf90cdda5a88ee46b818b5ef0cc3884aba04"}, - {file = "pydata_sphinx_theme-0.14.1.tar.gz", hash = "sha256:d8d4ac81252c16a002e835d21f0fea6d04cf3608e95045c816e8cc823e79b053"}, -] - -[package.dependencies] -accessible-pygments = "*" -Babel = "*" -beautifulsoup4 = "*" -docutils = "!=0.17.0" -packaging = "*" -pygments = ">=2.7" -sphinx = ">=5.0" -typing-extensions = "*" - -[package.extras] -a11y = ["pytest-playwright"] -dev = ["nox", "pre-commit", "pydata-sphinx-theme[doc,test]", "pyyaml"] -doc = ["ablog (>=0.11.0rc2)", "colorama", "ipyleaflet", "jupyter_sphinx", "jupyterlite-sphinx", "linkify-it-py", "matplotlib", "myst-nb", "nbsphinx", "numpy", "numpydoc", "pandas", "plotly", "rich", "sphinx-autoapi", "sphinx-copybutton", "sphinx-design", "sphinx-favicon (>=1.0.1)", "sphinx-sitemap", "sphinx-togglebutton", "sphinxcontrib-youtube (<1.4)", "sphinxext-rediraffe", "xarray"] -test = ["pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "pyflakes" -version = "2.4.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, -] - -[[package]] -name = "pygments" -version = "2.16.1" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.7" -files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, -] - -[package.extras] -plugins = ["importlib-metadata"] - -[[package]] -name = "pyproject-hooks" -version = "1.0.0" -description = "Wrappers to call pyproject.toml-based build backend hooks." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"}, - {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"}, -] - -[package.dependencies] -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[[package]] -name = "pyrsistent" -version = "0.20.0" -description = "Persistent/Functional/Immutable data structures" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, - {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, - {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, - {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, - {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, - {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, - {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, -] - -[[package]] -name = "pytest" -version = "7.4.2" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, - {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -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-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2023.3.post1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, -] - -[[package]] -name = "pywin32" -version = "306" -description = "Python for Window Extensions" -optional = false -python-versions = "*" -files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, -] - -[[package]] -name = "pywin32-ctypes" -version = "0.2.2" -description = "A (partial) reimplementation of pywin32 using ctypes/cffi" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"}, - {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, -] - -[[package]] -name = "pyzmq" -version = "25.1.1" -description = "Python bindings for 0MQ" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76"}, - {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71"}, - {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd"}, - {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7"}, - {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9"}, - {file = "pyzmq-25.1.1-cp310-cp310-win32.whl", hash = "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790"}, - {file = "pyzmq-25.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f"}, - {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83"}, - {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f"}, - {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505"}, - {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752"}, - {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca"}, - {file = "pyzmq-25.1.1-cp311-cp311-win32.whl", hash = "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329"}, - {file = "pyzmq-25.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6"}, - {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762"}, - {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b"}, - {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69"}, - {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e"}, - {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb"}, - {file = "pyzmq-25.1.1-cp312-cp312-win32.whl", hash = "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075"}, - {file = "pyzmq-25.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787"}, - {file = "pyzmq-25.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d"}, - {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb"}, - {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062"}, - {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22"}, - {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf"}, - {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e"}, - {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123"}, - {file = "pyzmq-25.1.1-cp36-cp36m-win32.whl", hash = "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71"}, - {file = "pyzmq-25.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3"}, - {file = "pyzmq-25.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115"}, - {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28"}, - {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0"}, - {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222"}, - {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf"}, - {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7"}, - {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae"}, - {file = "pyzmq-25.1.1-cp37-cp37m-win32.whl", hash = "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e"}, - {file = "pyzmq-25.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3"}, - {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a"}, - {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d"}, - {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995"}, - {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f"}, - {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618"}, - {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb"}, - {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2"}, - {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0"}, - {file = "pyzmq-25.1.1-cp38-cp38-win32.whl", hash = "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c"}, - {file = "pyzmq-25.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1"}, - {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45"}, - {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa"}, - {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414"}, - {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae"}, - {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6"}, - {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c"}, - {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8"}, - {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2"}, - {file = "pyzmq-25.1.1-cp39-cp39-win32.whl", hash = "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2"}, - {file = "pyzmq-25.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304"}, - {file = "pyzmq-25.1.1.tar.gz", hash = "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23"}, -] - -[package.dependencies] -cffi = {version = "*", markers = "implementation_name == \"pypy\""} - -[[package]] -name = "rapidfuzz" -version = "2.15.2" -description = "rapid fuzzy string matching" -optional = false -python-versions = ">=3.7" -files = [ - {file = "rapidfuzz-2.15.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b2e64e08588965b2490ee6b581d3901dd207ec3f6919b1c8da495183acfde953"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0af367ecb515ae695d7da21b0bd05784f388621e9d6a2e21dc96e6ba5d18d95f"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:892d0d75f0b820d949b0bf9502f746cfcbaab98d8a47653fa8369607fde250f1"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcf1d564ec948a4bf0750252579871be1790de66200f4cf8d624446017d74ee9"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab2f86733fe34cd825b6cbc688d41b7eb19ae0ce1ea7dc57eac13862d4b9ecb5"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8bdc497a8930428fa35158c58a744ddaa930621b80adfb61884456d8f184288a"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97f6c4948ca07ad1a30e70da56ec672422ef6bf18d10b6a881e7a64ba73a126d"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f3e2cc54edffd62ae38a03802b79c0f0cec6c2f89819607350fb5c4c00442d7"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0a252ccb39d628d0f68bab80ba18a02e0d1853a0ec71991e665a6bf81a28c79a"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ff82edd7ff9796e2ca349aa583fcb6b9ae96db0b6c5a76dcf0c1f67b1cb86964"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0860877f455833e5ed7113e859a9b2bf9670b22fdc7a48b81384a04c4a8e8a48"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:1a78c75ad082fdd58fdcf04551b7737c96aa9e870f1b008b881fc179e7dc6208"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a9df54f67a22a2447b8b6648880de9ede5e2a2e568644e1de770df9bef5c2fb4"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-win32.whl", hash = "sha256:055e85bb1237142da4ed024f9986c3720d484036f8dd550b090582f288b71bb9"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:8f220df380c127ef8a9129d8878dabf99ed0f543597cf81dfdd30eca03843666"}, - {file = "rapidfuzz-2.15.2-cp310-cp310-win_arm64.whl", hash = "sha256:49972e202251ba60de41a7add8e86a055478020eabf3339300f46a8fdc35d048"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29352510bcc2b7c3c7f3c1ab6f4c2115dc640cd79a9dc8e01adbae19fb96d359"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1ae3f741b9b3e95908158e6e56a5f11c1abc51754801dccd495e5cba734c541e"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a716bbded611cc82f7b27dcd7335b7bae49706c97a8738283464ff1536e7407"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ff36fb50f02259402d7cbdc96f75671b2cb14550db5ad6534a09a7f4940d796"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d60a2368e2564155d7209143a6b1dafa1eb457f31cf44698f917cba608d2341f"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c02fd6d75de19633f622daf6584cb6ed3148eac3a2b6b08fd3539c166de2921f"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5c875da0e0c9709dbdc6e33a7f061192e98943817e6d0e1f5d1d8b07050e349"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb74dcfadf0c5f520074455fe51fa0f62876e5473f5f60521d153afef888ef70"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b31f65137e8e45c4fb2dda394bb31598cff8290fb0ce5e66c8cf47d1bc554cb"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:689008633f88cf8802dbd281ac745775aeeee67525d532fcbabda0c8bc5b2e32"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:02fd52352346c965fdc9de9d26f55d61941cc27c876a589eeb3f4efdb7dffdb1"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:454ab8b5c8fc526243133dab013f0a3355efcc1200829cfba7ef56280c7763fc"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fd40f263d1ad1cdd4b657e867654674315eea9abf3fce64269610b7bc81265ee"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-win32.whl", hash = "sha256:66db4817c54a6ca91234959c4f6d0cb1fd943ddfb379ee7f9e6dce99b522554e"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:3f8eaf74105ffea1d15198b109ff0ca7b6dccafc61e05fa5f98a53d925707c57"}, - {file = "rapidfuzz-2.15.2-cp311-cp311-win_arm64.whl", hash = "sha256:ed0ec102b5e405d7562e4df05729a89467ae5c8a364c52fcf8c129398e82e6c5"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c0c8475f029a50bf65571b59d332fccd3eb33c5e49283868490a973e9ca7c33c"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ee9ee24eb431d5f73d0b255dc8e66272967a58cd6670cca984a81bbfc7dde904"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a1ecd818c108cefea2c02a9a716e223f811e612a050c8625555336b65d1cabef"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3eda119ebcf501dc35054abd9a187b5249b3d93b3965485371efb48e735b72c"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7ba83d0846991f67c2ec12ff8530b5e0f929e32a57352080b5f95aade0a62e"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c279864902a9538b17547e0d9399f05f36ebb9f3356bc5bc4cec2ba137fa5a17"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c94e247011fa7eea14d210123ebda2ecdf98ccc114254353edb4501ee8a19d7"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675c9052b3a04a4b33c92f0b8952ef2439163853422cc583286351ee82fc4d26"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c2d64820ae7a795082208a2d762c6a291aca116b86e35c2831e468ae3d4bb5cd"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:c0f12cc4a8216edfaa0511aae34d8b2f824a05cfe5a26a08de9cf180ae584e88"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e27da009ef39dc64297bcdf09c8d4c79ac90d0015fcf0a01af2a802cd7e1803"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:ea541d56fbb7de717a013790c2bce655252da220f23db0c6ce24f628cbe228e6"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9f52338e4e69aff4260c84275c7a704d198315b9b84303e67e584971409347d0"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-win32.whl", hash = "sha256:d5550e0078b2618c4ea7ea761053337eb7c5f5cc515f4941d8108ce9b0c7ee8c"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:19f72cfe2553c83c5e383851aba2891dafbb6446b6ae1ec0637333558ddd564e"}, - {file = "rapidfuzz-2.15.2-cp312-cp312-win_arm64.whl", hash = "sha256:423ef2ca785da77cd081d5bbc57035dc9b91500008a1b8e8e811a0ba3871a5ee"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0a02f1b08879a74aa7b4e562823f67a2e913fe3bd18c5346d9270d16fc588500"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a100ca26804b9ac2b2c0f70c632102bc0005d2cafe6d748f5d01dbe569c378bf"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e9fb88659cff92eba1b441efe426a4c349372137ee713b3a3933cc6ead73234"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:58073d3ebed8c0f51e163654dcb5e34f1e8b67f7b23361441861c6021243184b"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f55ad06ff79c2ffa3d1f5b38ce8f3082fa4db57c04be7de85243bd0625ca4ef"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ceecb57ec9e5c0d5bd9bd2881731c59cdc9a2c51711fd0b29b5bf14bdcab465f"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6c32c855e16ef3890037569f6f1299857172c674cd8946244e5fb7d5cacb771a"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e46f82fda6f969da8be5a8f33a057b2a9c6e7b80ab8679344a72e6fb708a48fc"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:6edc9b138797c60c1276171d8c97f53b17e304ade37c022ff97b1e995f79ba79"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:b32e4fd756a32f92b6f8b707a682ab4054b90c835021c01d81baba22f6277172"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5fb89d3a8d389eca258aba913adc81a8b8231b48896abbcb2f05768455584c4e"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-win32.whl", hash = "sha256:03ceea6cc9e4442379aa8581fbe61bad6e12d7938b16fbdc8442c8d915ad1154"}, - {file = "rapidfuzz-2.15.2-cp37-cp37m-win_amd64.whl", hash = "sha256:cb9f24fafb5ed77fc2ce23b1d8351efcfdb4c05b5f3b96bf004e89344a3d30ed"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aab133bea22acbd3fa3740989a2f21d0e275efede2bf406a25a84392086c32f9"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4e110224e0de4fe4876224104a79550d18df15459fe94adf24b4b644e31d69cc"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:780b006bd007e4a071a9c022733f56b0df1f8c269bb7e9dbe079a79e8d9d3b8d"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:898bee3fd785ee695d4cb0d3c689407809cafca472851904aa78143ca6634903"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34623f51ed5dcbb2ddb97b2fefda34e7b53a047c71aac5ec6b72e42d5263f8b2"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02b3612c9318006290e6e6d82f1f98b83aa4cf062075c5ea03fac71ba4d31499"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dd0aab9ffab0010ae28b60f64c98c09c93086b3dc0cb3da863e53a3ca14a2bd"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e772677a84a166531f975301cb91db234a56eb5b6785e79ff5cb335251580efc"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1b7a670aed23d9a8d27a0031fa059e8f50f3f7287bd5a075a448251029794de9"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:830f799e5ec534633dee3b26c6d5398461dd3ced22118ab590f7fd0f91263058"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:e427a9c9c1a8adac7b0293ddfe8f5885edf4f425cfd8a3b7ceae20434ec0663c"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3a3df80a264a999a120e637f98a1460d4f2c815323dd605e2022eef97db55448"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1496540d2ce8b1b9f340e652b9306674fa657d8d3a0b9629421cf31ace219092"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-win32.whl", hash = "sha256:aabd9da406fec009c08d2cd1bfa444ee568edf8e7c9a9d5e609885fc81c243a3"}, - {file = "rapidfuzz-2.15.2-cp38-cp38-win_amd64.whl", hash = "sha256:d21c66b15fbe253d48399a9d9db361ab2b3462a59b78c9279d9d7d347f5ded91"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ef4dea11b87234e8b08ee47df9d869ae071bdacb5e55df82673ab9fa622f1e0"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ee3d9bc953f232bffcbd973137505f6cf5be5ed9c2cdc5e4a5db4be33bf5a734"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:efb94f6adbbbdacac9f687eb151ae9220ee9f141bb259fe07e82a2087114c17e"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9c3e07d13661871aebc325b9b3acbd42355a1df1e21ad0435fc81980fd20607"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01bae563a010900abba857e485c3747a78d61c88431cc3d9bea894c7c3e521f"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a09187df670e344468597b2c6f5ddc7651be75c4b594baa62c9261a144e5c058"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fcbfe5497c93a1b8717ea38b41b47f7e9d155fbc36a6bbfa84b8c901875465af"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f997a93b85c5798fe139a46c68c85de06ff75b4fd52d52463e46573bff39774"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:199676b8a19746017a0fbad0eb11380cbda4f635b6d2ee477544743b7f99d947"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:499a170088049258d5118bff8cf88f88ef6054544edbea0f2920eba8669e5eb9"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:a69ebe7b493557c425ca1d64bf0b5599f0405772b5179070adc2f62f7867836f"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:00bd97cd31aad049400b70e0872b54457c4769b296176d5b064f6a5d6391909f"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cadabe1287314bc5053f57c6043df04e33cf5fba33514ca0f4c7b0b8476063a0"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-win32.whl", hash = "sha256:301709491a7960473c34501602cd85a7653df7e0d4189c0ded1e0fd86a83b6ca"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-win_amd64.whl", hash = "sha256:9c968a2330b6f2de93e6d54ef7ebd5e5724ee730cd6f225e977cebc7af1df366"}, - {file = "rapidfuzz-2.15.2-cp39-cp39-win_arm64.whl", hash = "sha256:c6776c27385f3fe5810f3c389f01957d5fa6c3c7f7a76fd9815f2933674f787f"}, - {file = "rapidfuzz-2.15.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0b4c632b684478fd8780970685a0c575a5bee65692727ff9898acf75d61cb3ff"}, - {file = "rapidfuzz-2.15.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b1cfca399461e1f534fbeb3c87f39f2c37ed71f8d1dfb02b78a5b3f81bf0ef"}, - {file = "rapidfuzz-2.15.2-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba35ec7256a86270a5e2d193ff0089cf84787a1aa94a48f5f6105f86feb8ca38"}, - {file = "rapidfuzz-2.15.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdfc137bbe2e942321f725004395444d2594077932ad55f927d6b6e884c09142"}, - {file = "rapidfuzz-2.15.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:153366a00ea22e79f051298fb9606bf9472bca5ce1b82319070fcbea2f7b97d7"}, - {file = "rapidfuzz-2.15.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6bf1c60432755ed8ab5870a932b7c9382435a240d727d3b5e68f9ff9f83a3556"}, - {file = "rapidfuzz-2.15.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a358eb275eadad0ac44f0fdb2255d6b373908c742f94e06b2190dbfaaaaa49b8"}, - {file = "rapidfuzz-2.15.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a34136ab5bbd1b9643f9072102a88471995100b5d734cfaa946d3b63e332e653"}, - {file = "rapidfuzz-2.15.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:796e53c5f78c159aff8e5003bca41bfe007c6a63ee7e7a289765a7db30429197"}, - {file = "rapidfuzz-2.15.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2ce4a91be05c28b57d5019b09cf0970305760623e34da95f2cddd9067e7fe91d"}, - {file = "rapidfuzz-2.15.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:237d5b4cbfacdef0a84f2ead0b4819c586bb74d05f4a380bd2f8489464b7b7fa"}, - {file = "rapidfuzz-2.15.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773dff970af0474d7d551a953a0075840ced30315d4885e038a289857ed33365"}, - {file = "rapidfuzz-2.15.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c536fbbebb496a76cac3a45f139bf023807b1fb6e2262e77f875fc9b6802ec4e"}, - {file = "rapidfuzz-2.15.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e85579a698c9436c2dac1583d4b07cca635faeb9a7adeab03d42938ec0fe9f58"}, - {file = "rapidfuzz-2.15.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:77c540546c0ea7cb229cd9823f9cd174c93988657727880bfdd6db7f353f93d6"}, - {file = "rapidfuzz-2.15.2.tar.gz", hash = "sha256:bfc1d38a7adcbe8912f980a5f46f27a801dd8655582ff0d4a2c0431c02b7ce33"}, -] - -[package.extras] -full = ["numpy"] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[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-toolbelt" -version = "1.0.0" -description = "A utility belt for advanced users of python-requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, - {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, -] - -[package.dependencies] -requests = ">=2.0.1,<3.0.0" - -[[package]] -name = "rpy2" -version = "3.5.14" -description = "Python interface to the R language (embedded R)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "rpy2-3.5.14-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cb7398adfcb6ca4faefbe856fb7af95eb11722ad18fbfcb4a79dbea1cf71c7c"}, - {file = "rpy2-3.5.14-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f35910208e5945b5108b7668bcb58127742f47fc0e8df8b2f4889c86be6f6519"}, - {file = "rpy2-3.5.14-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:adbd8e08f67f807fcca8e47473340e233a55c25fffd418081e6719316e03dbd7"}, - {file = "rpy2-3.5.14-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:ca95dee528d0a8032913de5fa85b8252b925f389aa2e2219d5314dcf43beeb1e"}, - {file = "rpy2-3.5.14.tar.gz", hash = "sha256:5f46ae31d36e117be366ad4ae02493c015ac6ba59ebe3b4cd7200075332fc481"}, -] - -[package.dependencies] -cffi = ">=1.10.0" -jinja2 = "*" -packaging = {version = "*", markers = "platform_system == \"Windows\""} -tzlocal = "*" - -[package.extras] -all = ["ipython", "numpy", "pandas (>=1.3.5)", "pytest"] -pandas = ["numpy", "pandas (>=1.3.5)"] -test = ["ipython", "numpy", "pandas (>=1.3.5)", "pytest"] -test-minimal = ["coverage", "pytest", "pytest-cov"] -types = ["mypy", "types-tzlocal"] - -[[package]] -name = "scikit-learn" -version = "1.3.2" -description = "A set of python modules for machine learning and data mining" -optional = false -python-versions = ">=3.8" -files = [ - {file = "scikit-learn-1.3.2.tar.gz", hash = "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05"}, - {file = "scikit_learn-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1"}, - {file = "scikit_learn-1.3.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a"}, - {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c"}, - {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161"}, - {file = "scikit_learn-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c"}, - {file = "scikit_learn-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66"}, - {file = "scikit_learn-1.3.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157"}, - {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb"}, - {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433"}, - {file = "scikit_learn-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b"}, - {file = "scikit_learn-1.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028"}, - {file = "scikit_learn-1.3.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5"}, - {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525"}, - {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c"}, - {file = "scikit_learn-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107"}, - {file = "scikit_learn-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a19f90f95ba93c1a7f7924906d0576a84da7f3b2282ac3bfb7a08a32801add93"}, - {file = "scikit_learn-1.3.2-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:b8692e395a03a60cd927125eef3a8e3424d86dde9b2370d544f0ea35f78a8073"}, - {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15e1e94cc23d04d39da797ee34236ce2375ddea158b10bee3c343647d615581d"}, - {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:785a2213086b7b1abf037aeadbbd6d67159feb3e30263434139c98425e3dcfcf"}, - {file = "scikit_learn-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:64381066f8aa63c2710e6b56edc9f0894cc7bf59bd71b8ce5613a4559b6145e0"}, - {file = "scikit_learn-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6c43290337f7a4b969d207e620658372ba3c1ffb611f8bc2b6f031dc5c6d1d03"}, - {file = "scikit_learn-1.3.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:dc9002fc200bed597d5d34e90c752b74df516d592db162f756cc52836b38fe0e"}, - {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d08ada33e955c54355d909b9c06a4789a729977f165b8bae6f225ff0a60ec4a"}, - {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763f0ae4b79b0ff9cca0bf3716bcc9915bdacff3cebea15ec79652d1cc4fa5c9"}, - {file = "scikit_learn-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:ed932ea780517b00dae7431e031faae6b49b20eb6950918eb83bd043237950e0"}, -] - -[package.dependencies] -joblib = ">=1.1.1" -numpy = ">=1.17.3,<2.0" -scipy = ">=1.5.0" -threadpoolctl = ">=2.0.0" - -[package.extras] -benchmark = ["matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "pandas (>=1.0.5)"] -docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)", "sphinx (>=6.0.0)", "sphinx-copybutton (>=0.5.2)", "sphinx-gallery (>=0.10.1)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] -examples = ["matplotlib (>=3.1.3)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)"] -tests = ["black (>=23.3.0)", "matplotlib (>=3.1.3)", "mypy (>=1.3)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.0.272)", "scikit-image (>=0.16.2)"] - -[[package]] -name = "scipy" -version = "1.9.3" -description = "Fundamental algorithms for scientific computing in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "scipy-1.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1884b66a54887e21addf9c16fb588720a8309a57b2e258ae1c7986d4444d3bc0"}, - {file = "scipy-1.9.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:83b89e9586c62e787f5012e8475fbb12185bafb996a03257e9675cd73d3736dd"}, - {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a72d885fa44247f92743fc20732ae55564ff2a519e8302fb7e18717c5355a8b"}, - {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01e1dd7b15bd2449c8bfc6b7cc67d630700ed655654f0dfcf121600bad205c9"}, - {file = "scipy-1.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:68239b6aa6f9c593da8be1509a05cb7f9efe98b80f43a5861cd24c7557e98523"}, - {file = "scipy-1.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b41bc822679ad1c9a5f023bc93f6d0543129ca0f37c1ce294dd9d386f0a21096"}, - {file = "scipy-1.9.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:90453d2b93ea82a9f434e4e1cba043e779ff67b92f7a0e85d05d286a3625df3c"}, - {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c06e62a390a9167da60bedd4575a14c1f58ca9dfde59830fc42e5197283dab"}, - {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abaf921531b5aeaafced90157db505e10345e45038c39e5d9b6c7922d68085cb"}, - {file = "scipy-1.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:06d2e1b4c491dc7d8eacea139a1b0b295f74e1a1a0f704c375028f8320d16e31"}, - {file = "scipy-1.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a04cd7d0d3eff6ea4719371cbc44df31411862b9646db617c99718ff68d4840"}, - {file = "scipy-1.9.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:545c83ffb518094d8c9d83cce216c0c32f8c04aaf28b92cc8283eda0685162d5"}, - {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d54222d7a3ba6022fdf5773931b5d7c56efe41ede7f7128c7b1637700409108"}, - {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cff3a5295234037e39500d35316a4c5794739433528310e117b8a9a0c76d20fc"}, - {file = "scipy-1.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:2318bef588acc7a574f5bfdff9c172d0b1bf2c8143d9582e05f878e580a3781e"}, - {file = "scipy-1.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d644a64e174c16cb4b2e41dfea6af722053e83d066da7343f333a54dae9bc31c"}, - {file = "scipy-1.9.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:da8245491d73ed0a994ed9c2e380fd058ce2fa8a18da204681f2fe1f57f98f95"}, - {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db5b30849606a95dcf519763dd3ab6fe9bd91df49eba517359e450a7d80ce2e"}, - {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c68db6b290cbd4049012990d7fe71a2abd9ffbe82c0056ebe0f01df8be5436b0"}, - {file = "scipy-1.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:5b88e6d91ad9d59478fafe92a7c757d00c59e3bdc3331be8ada76a4f8d683f58"}, - {file = "scipy-1.9.3.tar.gz", hash = "sha256:fbc5c05c85c1a02be77b1ff591087c83bc44579c6d2bd9fb798bb64ea5e1a027"}, -] - -[package.dependencies] -numpy = ">=1.18.5,<1.26.0" - -[package.extras] -dev = ["flake8", "mypy", "pycodestyle", "typing_extensions"] -doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-panels (>=0.5.2)", "sphinx-tabs"] -test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] - -[[package]] -name = "secretstorage" -version = "3.3.3" -description = "Python bindings to FreeDesktop.org Secret Service API" -optional = false -python-versions = ">=3.6" -files = [ - {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, - {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, -] - -[package.dependencies] -cryptography = ">=2.0" -jeepney = ">=0.6" - -[[package]] -name = "setuptools" -version = "68.2.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, - {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "shellingham" -version = "1.5.4" -description = "Tool to Detect Surrounding Shell" -optional = false -python-versions = ">=3.7" -files = [ - {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, - {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, -] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -optional = false -python-versions = "*" -files = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] - -[[package]] -name = "soupsieve" -version = "2.5" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -files = [ - {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, - {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, -] - -[[package]] -name = "sphinx" -version = "7.2.6" -description = "Python documentation generator" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"}, - {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"}, -] - -[package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=2.9" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.18.1,<0.21" -imagesize = ">=1.3" -Jinja2 = ">=3.0" -packaging = ">=21.0" -Pygments = ">=2.14" -requests = ">=2.25.0" -snowballstemmer = ">=2.0" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = ">=2.0.0" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.9" - -[package.extras] -docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] -test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools (>=67.0)"] - -[[package]] -name = "sphinx-copybutton" -version = "0.5.2" -description = "Add a copy button to each of your code cells." -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, - {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, -] - -[package.dependencies] -sphinx = ">=1.8" - -[package.extras] -code-style = ["pre-commit (==2.12.1)"] -rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] - -[[package]] -name = "sphinx-design" -version = "0.5.0" -description = "A sphinx extension for designing beautiful, view size responsive web components." -optional = false -python-versions = ">=3.8" -files = [ - {file = "sphinx_design-0.5.0-py3-none-any.whl", hash = "sha256:1af1267b4cea2eedd6724614f19dcc88fe2e15aff65d06b2f6252cee9c4f4c1e"}, - {file = "sphinx_design-0.5.0.tar.gz", hash = "sha256:e8e513acea6f92d15c6de3b34e954458f245b8e761b45b63950f65373352ab00"}, -] - -[package.dependencies] -sphinx = ">=5,<8" - -[package.extras] -code-style = ["pre-commit (>=3,<4)"] -rtd = ["myst-parser (>=1,<3)"] -testing = ["myst-parser (>=1,<3)", "pytest (>=7.1,<8.0)", "pytest-cov", "pytest-regressions"] -theme-furo = ["furo (>=2023.7.0,<2023.8.0)"] -theme-pydata = ["pydata-sphinx-theme (>=0.13.0,<0.14.0)"] -theme-rtd = ["sphinx-rtd-theme (>=1.0,<2.0)"] -theme-sbt = ["sphinx-book-theme (>=1.0,<2.0)"] - -[[package]] -name = "sphinx-gallery" -version = "0.14.0" -description = "A `Sphinx `_ extension that builds an HTML gallery of examples from any set of Python scripts." -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinx-gallery-0.14.0.tar.gz", hash = "sha256:2a4a0aaf032955508e1d0f3495199a3c7819ce420e71096bff0bca551a4043c2"}, - {file = "sphinx_gallery-0.14.0-py3-none-any.whl", hash = "sha256:55b3ad1f378abd126232c166192270ac0a3ef615dec10b66c961ed2967be1df6"}, -] - -[package.dependencies] -sphinx = ">=4" - -[[package]] -name = "sphinxcontrib-applehelp" -version = "1.0.7" -description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_applehelp-1.0.7-py3-none-any.whl", hash = "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d"}, - {file = "sphinxcontrib_applehelp-1.0.7.tar.gz", hash = "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-devhelp" -version = "1.0.5" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_devhelp-1.0.5-py3-none-any.whl", hash = "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"}, - {file = "sphinxcontrib_devhelp-1.0.5.tar.gz", hash = "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.0.4" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl", hash = "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"}, - {file = "sphinxcontrib_htmlhelp-2.0.4.tar.gz", hash = "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["html5lib", "pytest"] - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -description = "A sphinx extension which renders display math in HTML via JavaScript" -optional = false -python-versions = ">=3.5" -files = [ - {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, - {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, -] - -[package.extras] -test = ["flake8", "mypy", "pytest"] - -[[package]] -name = "sphinxcontrib-qthelp" -version = "1.0.6" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_qthelp-1.0.6-py3-none-any.whl", hash = "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"}, - {file = "sphinxcontrib_qthelp-1.0.6.tar.gz", hash = "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "1.1.9" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl", hash = "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1"}, - {file = "sphinxcontrib_serializinghtml-1.1.9.tar.gz", hash = "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "statsmodels" -version = "0.14.0" -description = "Statistical computations and models for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "statsmodels-0.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:16bfe0c96a53b20fa19067e3b6bd2f1d39e30d4891ea0d7bc20734a0ae95942d"}, - {file = "statsmodels-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5a6a0a1a06ff79be8aa89c8494b33903442859add133f0dda1daf37c3c71682e"}, - {file = "statsmodels-0.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77b3cd3a5268ef966a0a08582c591bd29c09c88b4566c892a7c087935234f285"}, - {file = "statsmodels-0.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c64ebe9cf376cba0c31aed138e15ed179a1d128612dd241cdf299d159e5e882"}, - {file = "statsmodels-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb471f757fc45102a87e5d86e87dc2c8c78b34ad4f203679a46520f1d863b9da"}, - {file = "statsmodels-0.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:582f9e41092e342aaa04920d17cc3f97240e3ee198672f194719b5a3d08657d6"}, - {file = "statsmodels-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7ebe885ccaa64b4bc5ad49ac781c246e7a594b491f08ab4cfd5aa456c363a6f6"}, - {file = "statsmodels-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b587ee5d23369a0e881da6e37f78371dce4238cf7638a455db4b633a1a1c62d6"}, - {file = "statsmodels-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef7fa4813c7a73b0d8a0c830250f021c102c71c95e9fe0d6877bcfb56d38b8c"}, - {file = "statsmodels-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:a6ad7b8aadccd4e4dd7f315a07bef1bca41d194eeaf4ec600d20dea02d242fce"}, - {file = "statsmodels-0.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3757542c95247e4ab025291a740efa5da91dc11a05990c033d40fce31c450dc9"}, - {file = "statsmodels-0.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:de489e3ed315bdba55c9d1554a2e89faa65d212e365ab81bc323fa52681fc60e"}, - {file = "statsmodels-0.14.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e290f4718177bffa8823a780f3b882d56dd64ad1c18cfb4bc8b5558f3f5757"}, - {file = "statsmodels-0.14.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71054f9dbcead56def14e3c9db6f66f943110fdfb19713caf0eb0f08c1ec03fd"}, - {file = "statsmodels-0.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:d7fda067837df94e0a614d93d3a38fb6868958d37f7f50afe2a534524f2660cb"}, - {file = "statsmodels-0.14.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1c7724ad573af26139a98393ae64bc318d1b19762b13442d96c7a3e793f495c3"}, - {file = "statsmodels-0.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3b0a135f3bfdeec987e36e3b3b4c53e0bb87a8d91464d2fcc4d169d176f46fdb"}, - {file = "statsmodels-0.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce28eb1c397dba437ec39b9ab18f2101806f388c7a0cf9cdfd8f09294ad1c799"}, - {file = "statsmodels-0.14.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68b1c768dd94cc5ba8398121a632b673c625491aa7ed627b82cb4c880a25563f"}, - {file = "statsmodels-0.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:8d1e3e10dfbfcd58119ba5a4d3c7d519182b970a2aebaf0b6f539f55ae16058d"}, - {file = "statsmodels-0.14.0.tar.gz", hash = "sha256:6875c7d689e966d948f15eb816ab5616f4928706b180cf470fd5907ab6f647a4"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.22.3", markers = "python_version == \"3.10\" and platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""}, - {version = ">=1.18", markers = "python_version != \"3.10\" or platform_system != \"Windows\" or platform_python_implementation == \"PyPy\""}, -] -packaging = ">=21.3" -pandas = ">=1.0" -patsy = ">=0.5.2" -scipy = ">=1.4,<1.9.2 || >1.9.2" - -[package.extras] -build = ["cython (>=0.29.26)"] -develop = ["colorama", "cython (>=0.29.26)", "cython (>=0.29.28,<3.0.0)", "flake8", "isort", "joblib", "matplotlib (>=3)", "oldest-supported-numpy (>=2022.4.18)", "pytest (>=7.0.1,<7.1.0)", "pytest-randomly", "pytest-xdist", "pywinpty", "setuptools-scm[toml] (>=7.0.0,<7.1.0)"] -docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "numpydoc", "pandas-datareader", "sphinx"] - -[[package]] -name = "threadpoolctl" -version = "3.2.0" -description = "threadpoolctl" -optional = false -python-versions = ">=3.8" -files = [ - {file = "threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032"}, - {file = "threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355"}, -] - -[[package]] -name = "tinycss2" -version = "1.2.1" -description = "A tiny CSS parser" -optional = false -python-versions = ">=3.7" -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 = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "tomlkit" -version = "0.12.1" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, - {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, -] - -[[package]] -name = "toolz" -version = "0.12.0" -description = "List processing tools and functional utilities" -optional = false -python-versions = ">=3.5" -files = [ - {file = "toolz-0.12.0-py3-none-any.whl", hash = "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f"}, - {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"}, -] - -[[package]] -name = "tornado" -version = "6.3.3" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -optional = false -python-versions = ">= 3.8" -files = [ - {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, - {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, - {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, - {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, - {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, -] - -[[package]] -name = "tqdm" -version = "4.66.1" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, - {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "traitlets" -version = "5.11.2" -description = "Traitlets Python configuration system" -optional = false -python-versions = ">=3.8" -files = [ - {file = "traitlets-5.11.2-py3-none-any.whl", hash = "sha256:98277f247f18b2c5cabaf4af369187754f4fb0e85911d473f72329db8a7f4fae"}, - {file = "traitlets-5.11.2.tar.gz", hash = "sha256:7564b5bf8d38c40fa45498072bf4dc5e8346eb087bbf1e2ae2d8774f6a0f078e"}, -] - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.5.1)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] - -[[package]] -name = "trove-classifiers" -version = "2023.10.18" -description = "Canonical source for classifiers on PyPI (pypi.org)." -optional = false -python-versions = "*" -files = [ - {file = "trove-classifiers-2023.10.18.tar.gz", hash = "sha256:2cdfcc7f31f7ffdd57666a9957296089ac72daad4d11ab5005060e5cd7e29939"}, - {file = "trove_classifiers-2023.10.18-py3-none-any.whl", hash = "sha256:20a3da8e3cb65587cc9f5d5b837bf74edeb480bba9bd8cd4f03ab056d6b06c4c"}, -] - -[[package]] -name = "typing-extensions" -version = "4.8.0" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, -] - -[[package]] -name = "tzdata" -version = "2023.3" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -files = [ - {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, - {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, -] - -[[package]] -name = "tzlocal" -version = "5.2" -description = "tzinfo object for the local timezone" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, - {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"}, -] - -[package.dependencies] -tzdata = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] - -[[package]] -name = "urllib3" -version = "2.0.7" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.7" -files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "virtualenv" -version = "20.24.6" -description = "Virtual Python Environment builder" -optional = false -python-versions = ">=3.7" -files = [ - {file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"}, - {file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"}, -] - -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<4" - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -optional = false -python-versions = "*" -files = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] - -[[package]] -name = "xarray" -version = "2023.10.1" -description = "N-D labeled arrays and datasets in Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "xarray-2023.10.1-py3-none-any.whl", hash = "sha256:71ea549e9be6dfeab19c2736acf659967b861aad2397691a80e5fad0c61db2ad"}, - {file = "xarray-2023.10.1.tar.gz", hash = "sha256:9eeee170c3fc2f3321eb6ba40c17ffe4d8c98d49d55e4a3fba66a75bdc7dd9e5"}, -] - -[package.dependencies] -numpy = ">=1.22" -packaging = ">=21.3" -pandas = ">=1.4" - -[package.extras] -accel = ["bottleneck", "flox", "numbagg", "scipy"] -complete = ["xarray[accel,io,parallel,viz]"] -io = ["cftime", "fsspec", "h5netcdf", "netCDF4", "pooch", "pydap", "scipy", "zarr"] -parallel = ["dask[complete]"] -viz = ["matplotlib", "nc-time-axis", "seaborn"] - -[[package]] -name = "xarray-datatree" -version = "0.0.13" -description = "Hierarchical tree-like data structures for xarray" -optional = false -python-versions = ">=3.9" -files = [ - {file = "xarray-datatree-0.0.13.tar.gz", hash = "sha256:f42bd519cab8754eb8a98749464846893b59560318520c45212e85c46af692c9"}, - {file = "xarray_datatree-0.0.13-py3-none-any.whl", hash = "sha256:b5c92339339e58f029107fd3c50478adb1dfd1316eaa628d1e0e2e8a3e7a079a"}, -] - -[package.dependencies] -packaging = "*" -xarray = ">=2022.6.0" - -[[package]] -name = "xattr" -version = "0.10.1" -description = "Python wrapper for extended filesystem attributes" -optional = false -python-versions = "*" -files = [ - {file = "xattr-0.10.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:16a660a883e703b311d1bbbcafc74fa877585ec081cd96e8dd9302c028408ab1"}, - {file = "xattr-0.10.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1e2973e72faa87ca29d61c23b58c3c89fe102d1b68e091848b0e21a104123503"}, - {file = "xattr-0.10.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:13279fe8f7982e3cdb0e088d5cb340ce9cbe5ef92504b1fd80a0d3591d662f68"}, - {file = "xattr-0.10.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1dc9b9f580ef4b8ac5e2c04c16b4d5086a611889ac14ecb2e7e87170623a0b75"}, - {file = "xattr-0.10.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:485539262c2b1f5acd6b6ea56e0da2bc281a51f74335c351ea609c23d82c9a79"}, - {file = "xattr-0.10.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:295b3ab335fcd06ca0a9114439b34120968732e3f5e9d16f456d5ec4fa47a0a2"}, - {file = "xattr-0.10.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:a126eb38e14a2f273d584a692fe36cff760395bf7fc061ef059224efdb4eb62c"}, - {file = "xattr-0.10.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:b0e919c24f5b74428afa91507b15e7d2ef63aba98e704ad13d33bed1288dca81"}, - {file = "xattr-0.10.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:e31d062cfe1aaeab6ba3db6bd255f012d105271018e647645941d6609376af18"}, - {file = "xattr-0.10.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:209fb84c09b41c2e4cf16dd2f481bb4a6e2e81f659a47a60091b9bcb2e388840"}, - {file = "xattr-0.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c4120090dac33eddffc27e487f9c8f16b29ff3f3f8bcb2251b2c6c3f974ca1e1"}, - {file = "xattr-0.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3e739d624491267ec5bb740f4eada93491de429d38d2fcdfb97b25efe1288eca"}, - {file = "xattr-0.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2677d40b95636f3482bdaf64ed9138fb4d8376fb7933f434614744780e46e42d"}, - {file = "xattr-0.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40039f1532c4456fd0f4c54e9d4e01eb8201248c321c6c6856262d87e9a99593"}, - {file = "xattr-0.10.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:148466e5bb168aba98f80850cf976e931469a3c6eb11e9880d9f6f8b1e66bd06"}, - {file = "xattr-0.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0aedf55b116beb6427e6f7958ccd80a8cbc80e82f87a4cd975ccb61a8d27b2ee"}, - {file = "xattr-0.10.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c3024a9ff157247c8190dd0eb54db4a64277f21361b2f756319d9d3cf20e475f"}, - {file = "xattr-0.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f1be6e733e9698f645dbb98565bb8df9b75e80e15a21eb52787d7d96800e823b"}, - {file = "xattr-0.10.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7880c8a54c18bc091a4ce0adc5c6d81da1c748aec2fe7ac586d204d6ec7eca5b"}, - {file = "xattr-0.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:89c93b42c3ba8aedbc29da759f152731196c2492a2154371c0aae3ef8ba8301b"}, - {file = "xattr-0.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6b905e808df61b677eb972f915f8a751960284358b520d0601c8cbc476ba2df6"}, - {file = "xattr-0.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ef954d0655f93a34d07d0cc7e02765ec779ff0b59dc898ee08c6326ad614d5"}, - {file = "xattr-0.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:199b20301b6acc9022661412346714ce764d322068ef387c4de38062474db76c"}, - {file = "xattr-0.10.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec0956a8ab0f0d3f9011ba480f1e1271b703d11542375ef73eb8695a6bd4b78b"}, - {file = "xattr-0.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffcb57ca1be338d69edad93cf59aac7c6bb4dbb92fd7bf8d456c69ea42f7e6d2"}, - {file = "xattr-0.10.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f0563196ee54756fe2047627d316977dc77d11acd7a07970336e1a711e934db"}, - {file = "xattr-0.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc354f086f926a1c7f04886f97880fed1a26d20e3bc338d0d965fd161dbdb8ab"}, - {file = "xattr-0.10.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c0cd2d02ef2fb45ecf2b0da066a58472d54682c6d4f0452dfe7ae2f3a76a42ea"}, - {file = "xattr-0.10.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49626096ddd72dcc1654aadd84b103577d8424f26524a48d199847b5d55612d0"}, - {file = "xattr-0.10.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ceaa26bef8fcb17eb59d92a7481c2d15d20211e217772fb43c08c859b01afc6a"}, - {file = "xattr-0.10.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8c014c371391f28f8cd27d73ea59f42b30772cd640b5a2538ad4f440fd9190b"}, - {file = "xattr-0.10.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:46c32cd605673606b9388a313b0050ee7877a0640d7561eea243ace4fa2cc5a6"}, - {file = "xattr-0.10.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:772b22c4ff791fe5816a7c2a1c9fcba83f9ab9bea138eb44d4d70f34676232b4"}, - {file = "xattr-0.10.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:183ad611a2d70b5a3f5f7aadef0fcef604ea33dcf508228765fd4ddac2c7321d"}, - {file = "xattr-0.10.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8068df3ebdfa9411e58d5ae4a05d807ec5994645bb01af66ec9f6da718b65c5b"}, - {file = "xattr-0.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bc40570155beb85e963ae45300a530223d9822edfdf09991b880e69625ba38a"}, - {file = "xattr-0.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:436e1aaf23c07e15bed63115f1712d2097e207214fc6bcde147c1efede37e2c5"}, - {file = "xattr-0.10.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7298455ccf3a922d403339781b10299b858bb5ec76435445f2da46fb768e31a5"}, - {file = "xattr-0.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:986c2305c6c1a08f78611eb38ef9f1f47682774ce954efb5a4f3715e8da00d5f"}, - {file = "xattr-0.10.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5dc6099e76e33fa3082a905fe59df766b196534c705cf7a2e3ad9bed2b8a180e"}, - {file = "xattr-0.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:042ad818cda6013162c0bfd3816f6b74b7700e73c908cde6768da824686885f8"}, - {file = "xattr-0.10.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9d4c306828a45b41b76ca17adc26ac3dc00a80e01a5ba85d71df2a3e948828f2"}, - {file = "xattr-0.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a606280b0c9071ef52572434ecd3648407b20df3d27af02c6592e84486b05894"}, - {file = "xattr-0.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5b49d591cf34cda2079fd7a5cb2a7a1519f54dc2e62abe3e0720036f6ed41a85"}, - {file = "xattr-0.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8705ac6791426559c1a5c2b88bb2f0e83dc5616a09b4500899bfff6a929302"}, - {file = "xattr-0.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5ea974930e876bc5c146f54ac0f85bb39b7b5de2b6fc63f90364712ae368ebe"}, - {file = "xattr-0.10.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f55a2dd73a12a1ae5113c5d9cd4b4ab6bf7950f4d76d0a1a0c0c4264d50da61d"}, - {file = "xattr-0.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:475c38da0d3614cc5564467c4efece1e38bd0705a4dbecf8deeb0564a86fb010"}, - {file = "xattr-0.10.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:925284a4a28e369459b2b7481ea22840eed3e0573a4a4c06b6b0614ecd27d0a7"}, - {file = "xattr-0.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa32f1b45fed9122bed911de0fcc654da349e1f04fa4a9c8ef9b53e1cc98b91e"}, - {file = "xattr-0.10.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c5d3d0e728bace64b74c475eb4da6148cd172b2d23021a1dcd055d92f17619ac"}, - {file = "xattr-0.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8faaacf311e2b5cc67c030c999167a78a9906073e6abf08eaa8cf05b0416515c"}, - {file = "xattr-0.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6b8d5ca452674e1a96e246a3d2db5f477aecbc7c945c73f890f56323e75203"}, - {file = "xattr-0.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3725746a6502f40f72ef27e0c7bfc31052a239503ff3eefa807d6b02a249be22"}, - {file = "xattr-0.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:789bd406d1aad6735e97b20c6d6a1701e1c0661136be9be862e6a04564da771f"}, - {file = "xattr-0.10.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9a7a807ab538210ff8532220d8fc5e2d51c212681f63dbd4e7ede32543b070f"}, - {file = "xattr-0.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3e5825b5fc99ecdd493b0cc09ec35391e7a451394fdf623a88b24726011c950d"}, - {file = "xattr-0.10.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80638d1ce7189dc52f26c234cee3522f060fadab6a8bc3562fe0ddcbe11ba5a4"}, - {file = "xattr-0.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3ff0dbe4a6ce2ce065c6de08f415bcb270ecfd7bf1655a633ddeac695ce8b250"}, - {file = "xattr-0.10.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5267e5f9435c840d2674194150b511bef929fa7d3bc942a4a75b9eddef18d8d8"}, - {file = "xattr-0.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b27dfc13b193cb290d5d9e62f806bb9a99b00cd73bb6370d556116ad7bb5dc12"}, - {file = "xattr-0.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:636ebdde0277bce4d12d2ef2550885804834418fee0eb456b69be928e604ecc4"}, - {file = "xattr-0.10.1-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d60c27922ec80310b45574351f71e0dd3a139c5295e8f8b19d19c0010196544f"}, - {file = "xattr-0.10.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b34df5aad035d0343bd740a95ca30db99b776e2630dca9cc1ba8e682c9cc25ea"}, - {file = "xattr-0.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f24a7c04ff666d0fe905dfee0a84bc899d624aeb6dccd1ea86b5c347f15c20c1"}, - {file = "xattr-0.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3878e1aff8eca64badad8f6d896cb98c52984b1e9cd9668a3ab70294d1ef92d"}, - {file = "xattr-0.10.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4abef557028c551d59cf2fb3bf63f2a0c89f00d77e54c1c15282ecdd56943496"}, - {file = "xattr-0.10.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0e14bd5965d3db173d6983abdc1241c22219385c22df8b0eb8f1846c15ce1fee"}, - {file = "xattr-0.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f9be588a4b6043b03777d50654c6079af3da60cc37527dbb80d36ec98842b1e"}, - {file = "xattr-0.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bc4ae264aa679aacf964abf3ea88e147eb4a22aea6af8c6d03ebdebd64cfd6"}, - {file = "xattr-0.10.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:827b5a97673b9997067fde383a7f7dc67342403093b94ea3c24ae0f4f1fec649"}, - {file = "xattr-0.10.1.tar.gz", hash = "sha256:c12e7d81ffaa0605b3ac8c22c2994a8e18a9cf1c59287a1b7722a2289c952ec5"}, -] - -[package.dependencies] -cffi = ">=1.0" - -[[package]] -name = "zarr" -version = "2.16.1" -description = "An implementation of chunked, compressed, N-dimensional arrays for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "zarr-2.16.1-py3-none-any.whl", hash = "sha256:de4882433ccb5b42cc1ec9872b95e64ca3a13581424666b28ed265ad76c7056f"}, - {file = "zarr-2.16.1.tar.gz", hash = "sha256:4276cf4b4a653431042cd53ff2282bc4d292a6842411e88529964504fb073286"}, -] - -[package.dependencies] -asciitree = "*" -fasteners = "*" -numcodecs = ">=0.10.0" -numpy = ">=1.20,<1.21.0 || >1.21.0" - -[package.extras] -docs = ["numcodecs[msgpack]", "numpydoc", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx-issues", "sphinx-rtd-theme"] -jupyter = ["ipytree (>=0.2.2)", "ipywidgets (>=8.0.0)", "notebook"] - -[[package]] -name = "zipp" -version = "3.17.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.8" -files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[metadata] -lock-version = "2.0" -python-versions = ">=3.10,<3.12" -content-hash = "b484f975356afb641449626a4e6fd1dcd7f2a10f5aa3573b321d0d4334e52fdd" diff --git a/pyproject.toml b/pyproject.toml index 6e9484ed..c178b96b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,63 +1,78 @@ -[tool.poetry] +[project] name = "xeofs" -version = "2.2.2" +version = "2.3.2" description = "Comprehensive EOF analysis in Python with xarray: A versatile, multidimensional, and scalable tool for advanced climate data analysis" -authors = ["Niclas Rieger "] -license = "MIT" +authors = [ + {name = "Niclas Rieger", email = "niclasrieger@gmail.com"}, + {name = "Samuel J. Levang", email = "slevang@gmail.com"}, +] +license = {text = "MIT"} readme = "README.md" -homepage = "https://github.com/nicrie/xeofs" -repository = "https://github.com/nicrie/xeofs" -documentation = "https://xeofs.readthedocs.io/en/latest/" - -[tool.poetry.dependencies] -python = ">=3.10,<3.12" -poetry = "^1.6" -numpy = "~1.24" -pandas = ">=1.4.1" -xarray = ">=0.21.1" -scikit-learn = ">=1.0.2" -pooch = "^1.6.0" -tqdm = "^4.64.0" -dask = ">=2023.0.1" -statsmodels = ">=0.14.0" -netCDF4 = "^1.5.7" -numba = "^0.57" -typing-extensions = "^4.8.0" -zarr = ">=2.0.0" -xarray-datatree = ">=0.0.5" +requires-python = ">=3.10" -[tool.poetry.group.dev] -optional = true - -[tool.poetry.group.dev.dependencies] -flake8 = "^4.0" -pytest = "^7.0" -coverage = "^6.3" -black = "~23.7.0" -pre-commit = "^3.3" +dependencies = [ + "numpy>=1.24", + "pandas>=2", + "xarray>=2023.04.0", + "scikit-learn>=1.0.2", + "tqdm>=4.64.0", + "dask>=2023.0.1", + "statsmodels>=0.14.0", + "netCDF4>=1.5.8", + "numba>=0.57", + "typing-extensions>=4.8.0", + "zarr>=2.14.0", + "xarray-datatree>=0.0.12", +] -[tool.poetry.group.docs] -optional = true +[project.optional-dependencies] +dev = [ + "build>=1.0.0", + "ruff>=0.3", + "pytest>=7", + "pytest-xdist>=3", + "coverage>=6", + "pre-commit>=3", + "nbstripout>=0.6", + "pooch>=1.6.0", +] +docs = [ + "rpy2>=3.5", + "sphinx-gallery>=0.14", + "sphinx-design>=0.5", + "sphinx-copybutton>=0.5", + "nbsphinx>=0.9", + "pydata-sphinx-theme>=0.14", + "sphinx>=7.2", + "nbconvert>=7.9", + "matplotlib>=3.4", + "seaborn>=0.11", + "cartopy>=0.22", + "pooch>=1.6.0", + "ipython>=8.14", + "ipykernel>=6.23", +] -[tool.poetry.group.docs.dependencies] -rpy2 = ">=3.5" -sphinx-gallery = "^0.14" -sphinx-design = "^0.5" -sphinx-copybutton = "^0.5" -nbsphinx = "^0.9" -pydata-sphinx-theme = "^0.14" -sphinx = "^7.2" -nbconvert = "^7.9" +[project.urls] +homepage = "https://github.com/xarray-contrib/xeofs" +repository = "https://github.com/xarray-contrib/xeofs" +documentation = "https://xeofs.readthedocs.io/en/latest/" [build-system] -requires = ["setuptools", "poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" +build-backend = "setuptools.build_meta" +requires = [ + "setuptools>=42", + "setuptools-scm>=7", +] + +[tool.ruff] +target-version = "py311" [tool.semantic_release] -version_toml = [ "pyproject.toml:tool.poetry.version" ] +version_toml = [ "pyproject.toml:project.version" ] version_source = "tag" commit_message = "chore(release): v{version}" -build_command = "pip install poetry && poetry build" +build_command = "python -m build" branch = "main" [tool.semantic_release.commit_parser_options] @@ -75,4 +90,3 @@ allowed_tags = [ ] minor_tags = ["feat"] patch_tags = ["fix", "perf"] - diff --git a/tests/conftest.py b/tests/conftest.py index 79270837..7aa11922 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,3 @@ -from typing import Dict, Optional - import numpy as np import pytest import warnings @@ -284,6 +282,31 @@ def mock_dask_data_array(mock_data_array): return mock_data_array.chunk({"lon": 2, "lat": 2, "time": -1}) +@pytest.fixture +def mock_complex_data_array(): + def f1(x, t): + return xr.DataArray( + 1.0 / np.cosh(x[np.newaxis, :] + 3) * np.exp(2.3j * t[:, np.newaxis]), + coords=[("time", t), ("x", x)], + ) + + def f2(x, t): + return xr.DataArray( + 2.0 + / np.cosh(x[np.newaxis, :]) + * np.tanh(x) + * np.exp(2.8j * t[:, np.newaxis]), + coords=[("time", t), ("x", x)], + ) + + x = np.linspace(-5, 5, 128) + t = np.linspace(0, 4 * np.pi, 256) + + X1 = f1(x, t) + X2 = f2(x, t) + return X1 + X2 + + # ============================================================================= # Intermediate data # ============================================================================= diff --git a/tests/models/test_cca.py b/tests/models/test_cca.py index 620e0a0e..ea77c2af 100644 --- a/tests/models/test_cca.py +++ b/tests/models/test_cca.py @@ -1,9 +1,4 @@ -import numpy as np -import xarray as xr import pytest -import dask.array as da -from numpy.testing import assert_allclose -from ..conftest import generate_list_of_synthetic_dataarrays from xeofs.models.cca import CCA diff --git a/tests/models/test_complex_eof.py b/tests/models/test_complex_eof.py index c55912cf..812b8966 100644 --- a/tests/models/test_complex_eof.py +++ b/tests/models/test_complex_eof.py @@ -1,11 +1,8 @@ import numpy as np -import xarray as xr import pytest -import dask.array as da import warnings -from numpy.testing import assert_allclose -from xeofs.models import EOF, ComplexEOF +from xeofs.models import ComplexEOF warnings.filterwarnings("ignore", message="numpy.dtype size changed") warnings.filterwarnings("ignore", message="numpy.ufunc size changed") @@ -99,7 +96,9 @@ def test_scores_phase(mock_data_array, dim): scores_phase = ceof.scores_phase() assert scores_phase is not None - assert ((-np.pi <= scores_phase.fillna(0)) & (scores_phase.fillna(0) <= np.pi)).all() # type: ignore + assert ( + (-np.pi <= scores_phase.fillna(0)) & (scores_phase.fillna(0) <= np.pi) + ).all() # type: ignore @pytest.mark.parametrize( diff --git a/tests/models/test_complex_eof_rotator.py b/tests/models/test_complex_eof_rotator.py index 2e9e4542..8e195dca 100644 --- a/tests/models/test_complex_eof_rotator.py +++ b/tests/models/test_complex_eof_rotator.py @@ -1,7 +1,5 @@ import pytest -import numpy as np import xarray as xr -from dask.array import Array as DaskArray # type: ignore from xeofs.models import ComplexEOF, ComplexEOFRotator from xeofs.data_container import DataContainer diff --git a/tests/models/test_complex_mca.py b/tests/models/test_complex_mca.py index bfe348b5..6d40c256 100644 --- a/tests/models/test_complex_mca.py +++ b/tests/models/test_complex_mca.py @@ -1,8 +1,5 @@ import pytest -import numpy as np import xarray as xr -import dask.array as da -from numpy.testing import assert_allclose from xeofs.models import ComplexMCA @@ -213,7 +210,7 @@ def test_fit_empty_data(dim): @pytest.mark.parametrize( "dim", [ - (("invalid_dim")), + ("invalid_dim"), ], ) def test_fit_invalid_dims(mca_model, mock_data_array, dim): diff --git a/tests/models/test_complex_mca_rotator.py b/tests/models/test_complex_mca_rotator.py index 14e6ca29..ad852577 100644 --- a/tests/models/test_complex_mca_rotator.py +++ b/tests/models/test_complex_mca_rotator.py @@ -1,7 +1,6 @@ import pytest import numpy as np import xarray as xr -from dask.array import Array as DaskArray # type: ignore # Import the classes from your modules from xeofs.models import ComplexMCA, ComplexMCARotator @@ -27,7 +26,7 @@ def test_init(): assert mca_rotator._params["power"] == 1 assert mca_rotator._params["max_iter"] == 1000 assert mca_rotator._params["rtol"] == 1e-8 - assert mca_rotator._params["squared_loadings"] == False + assert mca_rotator._params["squared_loadings"] is False @pytest.mark.parametrize( @@ -59,9 +58,7 @@ def test_transform(mca_model, mock_data_array): mca_rotator.fit(mca_model) with pytest.raises(NotImplementedError): - projections = mca_rotator.transform( - data1=mock_data_array, data2=mock_data_array - ) + mca_rotator.transform(data1=mock_data_array, data2=mock_data_array) @pytest.mark.parametrize( diff --git a/tests/models/test_decomposer.py b/tests/models/test_decomposer.py index bb19a99a..c1dcef9e 100644 --- a/tests/models/test_decomposer.py +++ b/tests/models/test_decomposer.py @@ -1,10 +1,6 @@ import numpy as np -import xarray as xr import pytest from dask.array import Array as DaskArray # type: ignore -from sklearn.utils.extmath import randomized_svd as svd -from scipy.sparse.linalg import svds as complex_svd # type: ignore -from dask.array.linalg import svd_compressed as dask_svd from xeofs.models.decomposer import Decomposer from ..utilities import data_is_dask diff --git a/tests/models/test_eeof.py b/tests/models/test_eeof.py index ee2c20dd..1c150a2c 100644 --- a/tests/models/test_eeof.py +++ b/tests/models/test_eeof.py @@ -1,8 +1,6 @@ import numpy as np import xarray as xr import pytest -import dask.array as da -from numpy.testing import assert_allclose from xeofs.models.eeof import ExtendedEOF @@ -377,13 +375,13 @@ def test_transform(dim, mock_data_array): # Create a xarray DataArray with random data model = ExtendedEOF(n_modes=5, tau=2, embedding=2, solver="full") model.fit(mock_data_array, dim) - scores = model.scores() + model.scores() # Create a new xarray DataArray with random data new_data = mock_data_array with pytest.raises(NotImplementedError): - projections = model.transform(new_data) + model.transform(new_data) # # Check that the projection has the right dimensions # assert projections.dims == scores.dims, "Projection has wrong dimensions" # type: ignore diff --git a/tests/models/test_eof.py b/tests/models/test_eof.py index 834730c3..d1403e80 100644 --- a/tests/models/test_eof.py +++ b/tests/models/test_eof.py @@ -1,8 +1,6 @@ import numpy as np import xarray as xr import pytest -from dask.array import Array as DaskArray # type: ignore -from numpy.testing import assert_allclose from xeofs.models.eof import EOF @@ -442,34 +440,50 @@ def test_transform_nan_feature(dim, mock_data_array): @pytest.mark.parametrize( - "dim", + "dim, normalized", [ - (("time",)), - (("lat", "lon")), - (("lon", "lat")), + (("time",), True), + (("lat", "lon"), True), + (("lon", "lat"), True), + (("time",), False), + (("lat", "lon"), False), + (("lon", "lat"), False), ], ) -def test_inverse_transform(dim, mock_data_array): +def test_inverse_transform(dim, mock_data_array, normalized): """Test inverse_transform method in EOF class.""" # instantiate the EOF class with necessary parameters - eof = EOF(n_modes=3, standardize=True) + eof = EOF(n_modes=20, standardize=True) # fit the EOF model eof.fit(mock_data_array, dim=dim) + scores = eof.scores(normalized=normalized) # Test with single mode - scores = eof.data["scores"].sel(mode=1) - reconstructed_data = eof.inverse_transform(scores) - assert isinstance(reconstructed_data, xr.DataArray) + scores_selection = scores.sel(mode=1) + X_rec_1 = eof.inverse_transform(scores_selection) + assert isinstance(X_rec_1, xr.DataArray) + + # Test with single mode as list + scores_selection = scores.sel(mode=[1]) + X_rec_1_list = eof.inverse_transform(scores_selection) + assert isinstance(X_rec_1_list, xr.DataArray) + + # Single mode and list should be equal + xr.testing.assert_allclose(X_rec_1, X_rec_1_list) # Test with all modes - scores = eof.data["scores"] - reconstructed_data = eof.inverse_transform(scores) - assert isinstance(reconstructed_data, xr.DataArray) + X_rec = eof.inverse_transform(scores, normalized=normalized) + assert isinstance(X_rec, xr.DataArray) # Check that the reconstructed data has the same dimensions as the original data - assert set(reconstructed_data.dims) == set(mock_data_array.dims) + assert set(X_rec.dims) == set(mock_data_array.dims) + + # Reconstructed data should be close to the original data + orig_dim_order = mock_data_array.dims + X_rec = X_rec.transpose(*orig_dim_order) + xr.testing.assert_allclose(mock_data_array, X_rec) @pytest.mark.parametrize( @@ -518,3 +532,57 @@ def test_save_load(dim, mock_data_array, tmp_path, engine): original.inverse_transform(original.scores()), loaded.inverse_transform(loaded.scores()), ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataarray(dim, mock_data_array): + """Test roundtrip serialization when the model is fit on a DataArray.""" + model = EOF() + model.fit(mock_data_array, dim) + dt = model.serialize() + rebuilt_model = EOF.deserialize(dt) + assert np.allclose( + model.transform(mock_data_array), rebuilt_model.transform(mock_data_array) + ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataset(dim, mock_dataset): + """Test roundtrip serialization when the model is fit on a Dataset.""" + model = EOF() + model.fit(mock_dataset, dim) + dt = model.serialize() + rebuilt_model = EOF.deserialize(dt) + assert np.allclose( + model.transform(mock_dataset), rebuilt_model.transform(mock_dataset) + ) + + +def test_complex_input_inverse_transform(mock_complex_data_array): + """Test that the EOF model can handle complex input data.""" + + model = EOF(n_modes=128) + model.fit(mock_complex_data_array, dim="time") + scores = model.scores() + + # Test the inverse_transform method + X_rec = model.inverse_transform(scores) + assert isinstance(X_rec, xr.DataArray) + # Check that the reconstructed data has the same dimensions as the original data + assert set(X_rec.dims) == set(mock_complex_data_array.dims) + # Reconstructed data should be close to the original data + xr.testing.assert_allclose(mock_complex_data_array, X_rec) diff --git a/tests/models/test_eof_rotator.py b/tests/models/test_eof_rotator.py index 64557ef5..b95589ff 100644 --- a/tests/models/test_eof_rotator.py +++ b/tests/models/test_eof_rotator.py @@ -1,7 +1,6 @@ import pytest import numpy as np import xarray as xr -from dask.array import Array as DaskArray # type: ignore from xeofs.models import EOF, EOFRotator from xeofs.data_container import DataContainer @@ -244,3 +243,45 @@ def test_save_load(dim, mock_data_array, tmp_path, engine): original.inverse_transform(original.scores()), loaded.inverse_transform(loaded.scores()), ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataarray(dim, mock_data_array): + """Test roundtrip serialization when the model is fit on a DataArray.""" + model = EOF() + model.fit(mock_data_array, dim) + rotator = EOFRotator() + rotator.fit(model) + dt = rotator.serialize() + rebuilt_rotator = EOFRotator.deserialize(dt) + assert np.allclose( + rotator.transform(mock_data_array), rebuilt_rotator.transform(mock_data_array) + ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataset(dim, mock_dataset): + """Test roundtrip serialization when the model is fit on a Dataset.""" + model = EOF() + model.fit(mock_dataset, dim) + rotator = EOFRotator() + rotator.fit(model) + dt = rotator.serialize() + rebuilt_rotator = EOFRotator.deserialize(dt) + assert np.allclose( + rotator.transform(mock_dataset), rebuilt_rotator.transform(mock_dataset) + ) diff --git a/tests/models/test_gwpca.py b/tests/models/test_gwpca.py index c3e87d5c..8b3fc353 100644 --- a/tests/models/test_gwpca.py +++ b/tests/models/test_gwpca.py @@ -1,7 +1,6 @@ import pytest import xeofs as xe -from ..utilities import assert_expected_dims, data_is_dask, data_has_multiindex # ============================================================================= # GENERALLY VALID TEST CASES @@ -36,8 +35,8 @@ def test_fit(mock_data_array, kernel): n_modes=2, metric="haversine", kernel=kernel, bandwidth=5000 ) gwpca.fit(mock_data_array, dim=("lat", "lon")) - comps = gwpca.components() - llwc = gwpca.largest_locally_weighted_components() + gwpca.components() + gwpca.largest_locally_weighted_components() @pytest.mark.parametrize( @@ -50,6 +49,4 @@ def test_fit(mock_data_array, kernel): ) def test_fit_invalid(mock_data_array, metric, kernel, bandwidth): with pytest.raises(ValueError): - gwpca = xe.models.GWPCA( - n_modes=2, metric=metric, kernel=kernel, bandwidth=bandwidth - ) + xe.models.GWPCA(n_modes=2, metric=metric, kernel=kernel, bandwidth=bandwidth) diff --git a/tests/models/test_mca.py b/tests/models/test_mca.py index b6ffe0c8..09aba4d7 100644 --- a/tests/models/test_mca.py +++ b/tests/models/test_mca.py @@ -1,8 +1,6 @@ import pytest import numpy as np import xarray as xr -from dask.array import Array as DaskArray # type: ignore -from numpy.testing import assert_allclose from xeofs.models.mca import MCA from ..utilities import data_is_dask @@ -106,6 +104,20 @@ def test_transform(mca_model, mock_data_array, dim): assert isinstance(result[0], xr.DataArray) +@pytest.mark.parametrize("dim", [(("time",))]) +def test_transform_unseen_data(mca_model, mock_data_array, dim): + data = mock_data_array.isel(time=slice(0, 20)) + data_unseen = mock_data_array.isel(time=slice(21, None)) + + mca_model.fit(data, data, dim) + result = mca_model.transform(data1=data_unseen, data2=data_unseen) + assert isinstance(result, list) + assert isinstance(result[0], xr.DataArray) + # Check that unseen data can be transformed + assert result[0].notnull().all() + assert result[1].notnull().all() + + @pytest.mark.parametrize( "dim", [ @@ -432,3 +444,41 @@ def test_save_load(dim, mock_data_array, tmp_path, engine): original.inverse_transform(*original.scores()), loaded.inverse_transform(*loaded.scores()), ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataarray(dim, mock_data_array): + """Test roundtrip serialization when the model is fit on a DataArray.""" + model = MCA() + model.fit(mock_data_array, mock_data_array, dim) + dt = model.serialize() + rebuilt_model = MCA.deserialize(dt) + assert np.allclose( + model.transform(mock_data_array), rebuilt_model.transform(mock_data_array) + ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataset(dim, mock_dataset): + """Test roundtrip serialization when the model is fit on a Dataset.""" + model = MCA() + model.fit(mock_dataset, mock_dataset, dim) + dt = model.serialize() + rebuilt_model = MCA.deserialize(dt) + assert np.allclose( + model.transform(mock_dataset), rebuilt_model.transform(mock_dataset) + ) diff --git a/tests/models/test_mca_rotator.py b/tests/models/test_mca_rotator.py index 555540ad..61198549 100644 --- a/tests/models/test_mca_rotator.py +++ b/tests/models/test_mca_rotator.py @@ -1,7 +1,6 @@ import pytest import numpy as np import xarray as xr -from dask.array import Array as DaskArray # type: ignore # Import the classes from your modules from xeofs.models import MCA, MCARotator @@ -28,7 +27,7 @@ def test_init(): assert mca_rotator._params["power"] == 1 assert mca_rotator._params["max_iter"] == 1000 assert mca_rotator._params["rtol"] == 1e-8 - assert mca_rotator._params["squared_loadings"] == False + assert mca_rotator._params["squared_loadings"] is False @pytest.mark.parametrize( @@ -304,3 +303,45 @@ def test_save_load(dim, mock_data_array, tmp_path, engine): original.inverse_transform(*original.scores()), loaded.inverse_transform(*loaded.scores()), ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataarray(dim, mock_data_array): + """Test roundtrip serialization when the model is fit on a DataArray.""" + model = MCA() + model.fit(mock_data_array, mock_data_array, dim) + rotator = MCARotator() + rotator.fit(model) + dt = rotator.serialize() + rebuilt_rotator = MCARotator.deserialize(dt) + assert np.allclose( + rotator.transform(mock_data_array), rebuilt_rotator.transform(mock_data_array) + ) + + +@pytest.mark.parametrize( + "dim", + [ + (("time",)), + (("lat", "lon")), + (("lon", "lat")), + ], +) +def test_serialize_deserialize_dataset(dim, mock_dataset): + """Test roundtrip serialization when the model is fit on a Dataset.""" + model = MCA() + model.fit(mock_dataset, mock_dataset, dim) + rotator = MCARotator() + rotator.fit(model) + dt = rotator.serialize() + rebuilt_rotator = MCARotator.deserialize(dt) + assert np.allclose( + rotator.transform(mock_dataset), rebuilt_rotator.transform(mock_dataset) + ) diff --git a/tests/models/test_opa.py b/tests/models/test_opa.py index d587c783..57991bbb 100644 --- a/tests/models/test_opa.py +++ b/tests/models/test_opa.py @@ -1,8 +1,6 @@ import numpy as np import xarray as xr import pytest -import dask.array as da -from numpy.testing import assert_allclose from xeofs.models import OPA @@ -278,9 +276,10 @@ def test_inverse_transform(dim, mock_data_array, opa_model): # fit the EOF model opa_model.fit(mock_data_array, dim=dim) + scores = opa_model.scores() with pytest.raises(NotImplementedError): - opa_model.inverse_transform(1) + opa_model.inverse_transform(scores) # # Test with scalar # mode = 1 diff --git a/tests/models/test_orthogonality.py b/tests/models/test_orthogonality.py index 75ae56e5..e1d25e88 100644 --- a/tests/models/test_orthogonality.py +++ b/tests/models/test_orthogonality.py @@ -1,8 +1,5 @@ import numpy as np -import xarray as xr import pytest -import dask.array as da -from numpy.testing import assert_allclose from xeofs.models import EOF, ComplexEOF, EOFRotator, ComplexEOFRotator from xeofs.models import MCA, ComplexMCA, MCARotator, ComplexMCARotator @@ -486,9 +483,9 @@ def test_ceof_transform(dim, use_coslat, mock_data_array, normalized): """Not implemented yet""" model = ComplexEOF(n_modes=5, standardize=True, use_coslat=use_coslat) model.fit(mock_data_array, dim=dim) - scores = model.scores(normalized=normalized) + model.scores(normalized=normalized) with pytest.raises(NotImplementedError): - pseudo_scores = model.transform(mock_data_array, normalized=normalized) + model.transform(mock_data_array, normalized=normalized) # Rotated EOF @@ -539,9 +536,9 @@ def test_creof_transform(dim, use_coslat, power, mock_data_array, normalized): model.fit(mock_data_array, dim=dim) rot = ComplexEOFRotator(n_modes=5, power=power) rot.fit(model) - scores = rot.scores(normalized=normalized) + rot.scores(normalized=normalized) with pytest.raises(NotImplementedError): - pseudo_scores = rot.transform(mock_data_array, normalized=normalized) + rot.transform(mock_data_array, normalized=normalized) # MCA diff --git a/tests/models/test_rotator.py b/tests/models/test_rotator.py index fe5806a9..3f2d71a2 100644 --- a/tests/models/test_rotator.py +++ b/tests/models/test_rotator.py @@ -1,5 +1,4 @@ import pytest -from unittest.mock import Mock from xeofs.models import EOF, ComplexEOF, MCA, ComplexMCA from xeofs.models import EOFRotator, ComplexEOFRotator, MCARotator, ComplexMCARotator diff --git a/tests/preprocessing/test_dataarray_multiindex_converter.py b/tests/preprocessing/test_dataarray_multiindex_converter.py index 876ec5f9..d939a642 100644 --- a/tests/preprocessing/test_dataarray_multiindex_converter.py +++ b/tests/preprocessing/test_dataarray_multiindex_converter.py @@ -1,12 +1,9 @@ import pytest -import pandas as pd from xeofs.preprocessing.multi_index_converter import ( MultiIndexConverter, ) -from ..conftest import generate_synthetic_dataarray -from xeofs.utils.data_types import DataArray -from ..utilities import assert_expected_dims, data_is_dask, data_has_multiindex +from ..utilities import data_is_dask, data_has_multiindex # ============================================================================= # GENERALLY VALID TEST CASES diff --git a/tests/preprocessing/test_dataarray_sanitizer.py b/tests/preprocessing/test_dataarray_sanitizer.py index b3388651..3972b8f5 100644 --- a/tests/preprocessing/test_dataarray_sanitizer.py +++ b/tests/preprocessing/test_dataarray_sanitizer.py @@ -1,6 +1,5 @@ import pytest import numpy as np -import xarray as xr from xeofs.preprocessing.sanitizer import Sanitizer from xeofs.utils.data_types import DataArray diff --git a/tests/preprocessing/test_dataarray_stacker.py b/tests/preprocessing/test_dataarray_stacker.py index 1eb531ee..10f3f4bd 100644 --- a/tests/preprocessing/test_dataarray_stacker.py +++ b/tests/preprocessing/test_dataarray_stacker.py @@ -1,6 +1,4 @@ import pytest -import numpy as np -import xarray as xr from xeofs.preprocessing import Stacker from xeofs.utils.data_types import DataArray diff --git a/tests/preprocessing/test_dataset_multiindex_converter.py b/tests/preprocessing/test_dataset_multiindex_converter.py index b93e75b0..d7057652 100644 --- a/tests/preprocessing/test_dataset_multiindex_converter.py +++ b/tests/preprocessing/test_dataset_multiindex_converter.py @@ -1,11 +1,8 @@ import pytest -import pandas as pd from xeofs.preprocessing.multi_index_converter import ( MultiIndexConverter, ) -from ..conftest import generate_synthetic_dataset -from xeofs.utils.data_types import DataArray from ..utilities import assert_expected_dims, data_is_dask, data_has_multiindex # ============================================================================= diff --git a/tests/preprocessing/test_dataset_stacker.py b/tests/preprocessing/test_dataset_stacker.py index 5eed6c23..44d61b16 100644 --- a/tests/preprocessing/test_dataset_stacker.py +++ b/tests/preprocessing/test_dataset_stacker.py @@ -1,9 +1,7 @@ import pytest -import xarray as xr -import numpy as np from xeofs.preprocessing import Stacker -from xeofs.utils.data_types import DataSet, DataArray +from xeofs.utils.data_types import DataArray from ..conftest import generate_synthetic_dataset from ..utilities import ( get_dims_from_data, diff --git a/tests/preprocessing/test_preprocessor_dataarray.py b/tests/preprocessing/test_preprocessor_dataarray.py index 2873423c..9db17c72 100644 --- a/tests/preprocessing/test_preprocessor_dataarray.py +++ b/tests/preprocessing/test_preprocessor_dataarray.py @@ -1,6 +1,5 @@ import pytest import numpy as np -import xarray as xr from xeofs.preprocessing.preprocessor import Preprocessor from ..conftest import generate_synthetic_dataarray diff --git a/tests/preprocessing/test_preprocessor_datalist.py b/tests/preprocessing/test_preprocessor_datalist.py index 8602d08b..7be277d2 100644 --- a/tests/preprocessing/test_preprocessor_datalist.py +++ b/tests/preprocessing/test_preprocessor_datalist.py @@ -64,7 +64,7 @@ def test_fit_transform_scalings( ): prep = Preprocessor(with_std=with_std, with_coslat=with_coslat) - n_data = len(mock_data_array_list) + len(mock_data_array_list) sample_dims = ("time",) weights = None if with_weights: diff --git a/tests/preprocessing/test_preprocessor_dataset.py b/tests/preprocessing/test_preprocessor_dataset.py index 9c047f3b..930bdd6d 100644 --- a/tests/preprocessing/test_preprocessor_dataset.py +++ b/tests/preprocessing/test_preprocessor_dataset.py @@ -1,6 +1,5 @@ import pytest import numpy as np -import xarray as xr from xeofs.preprocessing.preprocessor import Preprocessor from ..conftest import generate_synthetic_dataset @@ -66,7 +65,7 @@ def test_fit_transform_scalings(with_std, with_coslat, with_weights, mock_datase weights = None if with_weights: weights = mock_dataset.mean("time").copy() - weights = weights.where(weights == True, 0.5) + weights = weights.where(weights is True, 0.5) data_trans = prep.fit_transform(mock_dataset, "time", weights) diff --git a/tests/utilities.py b/tests/utilities.py index b69380fa..1243cc56 100644 --- a/tests/utilities.py +++ b/tests/utilities.py @@ -1,18 +1,15 @@ -from typing import Tuple, List, Hashable import numpy as np import pandas as pd -import xarray as xr from xeofs.utils.data_types import ( DataArray, DataSet, DataList, - DaskArray, Dims, DimsList, DimsTuple, DimsListTuple, ) -from xeofs.utils.xarray_utils import data_is_dask +from xeofs.utils.xarray_utils import data_is_dask # noqa: F401 def is_xdata(data): diff --git a/tests/utils/test_dimension_renamer.py b/tests/utils/test_dimension_renamer.py index 4ce1ca42..f61b0c1e 100644 --- a/tests/utils/test_dimension_renamer.py +++ b/tests/utils/test_dimension_renamer.py @@ -3,9 +3,7 @@ from xeofs.utils.dimension_renamer import DimensionRenamer -import xarray as xr import pandas as pd -import pytest @pytest.fixture diff --git a/tests/utils/test_total_variance.py b/tests/utils/test_total_variance.py index f0e7232e..0aa44d7f 100644 --- a/tests/utils/test_total_variance.py +++ b/tests/utils/test_total_variance.py @@ -1,4 +1,3 @@ -import pytest import numpy as np import xarray as xr diff --git a/tests/validation/test_eof_bootstrapper.py b/tests/validation/test_eof_bootstrapper.py index e78ef126..c4501c03 100644 --- a/tests/validation/test_eof_bootstrapper.py +++ b/tests/validation/test_eof_bootstrapper.py @@ -2,7 +2,7 @@ import xarray as xr import numpy as np -from xeofs.models import EOF, ComplexEOF +from xeofs.models import EOF from xeofs.validation import EOFBootstrapper @@ -307,7 +307,7 @@ def test_scores(eof_model): bootstrapper.fit(eof_model) scores = bootstrapper.scores() - assert isinstance(scores, xr.DataArray), f"scores is not a xr.DataArray" + assert isinstance(scores, xr.DataArray), "scores is not a xr.DataArray" # check for expected dimensions ref = eof_model.scores() diff --git a/xeofs/__init__.py b/xeofs/__init__.py index 867b6054..ac3e5d18 100644 --- a/xeofs/__init__.py +++ b/xeofs/__init__.py @@ -1,2 +1,4 @@ from xeofs import models, validation from xeofs._version import __version__ + +__all__ = ["models", "validation", "__version__"] diff --git a/xeofs/data_container/__init__.py b/xeofs/data_container/__init__.py index 3a8fcd5c..a375973e 100644 --- a/xeofs/data_container/__init__.py +++ b/xeofs/data_container/__init__.py @@ -1 +1,3 @@ from .data_container import DataContainer + +__all__ = ["DataContainer"] diff --git a/xeofs/data_container/data_container.py b/xeofs/data_container/data_container.py index b45f70c4..2c30d4f4 100644 --- a/xeofs/data_container/data_container.py +++ b/xeofs/data_container/data_container.py @@ -2,7 +2,6 @@ from typing_extensions import Self import dask -import xarray as xr from dask.diagnostics.progress import ProgressBar from datatree import DataTree diff --git a/xeofs/models/_base_cross_model.py b/xeofs/models/_base_cross_model.py index 4989cdc9..a8fa74c8 100644 --- a/xeofs/models/_base_cross_model.py +++ b/xeofs/models/_base_cross_model.py @@ -1,10 +1,9 @@ -from typing import Tuple, Hashable, Sequence, Dict, Optional, List, Literal +from typing import Tuple, Hashable, Sequence, Dict, Optional, Literal from typing_extensions import Self from abc import ABC, abstractmethod from datetime import datetime import dask -import numpy as np import xarray as xr from datatree import DataTree from dask.diagnostics.progress import ProgressBar @@ -12,7 +11,7 @@ from .eof import EOF from ..preprocessing.preprocessor import Preprocessor from ..data_container import DataContainer -from ..utils.data_types import DataObject, DataArray, DataSet +from ..utils.data_types import DataObject, DataArray from ..utils.io import insert_placeholders, open_model_tree, write_model_tree from ..utils.xarray_utils import convert_to_dim_type, data_is_dask from ..utils.sanity_checks import validate_input_type @@ -214,7 +213,53 @@ def transform( # Preprocess data2 data2 = self.preprocessor2.transform(data2) - return self._transform_algorithm(data1, data2) + data = self._transform_algorithm(data1, data2) + data_list = [] + if data1 is not None: + data1 = self.preprocessor1.inverse_transform_scores_unseen(data["data1"]) + data_list.append(data1) + if data2 is not None: + data2 = self.preprocessor2.inverse_transform_scores_unseen(data["data2"]) + data_list.append(data2) + return data_list + + def inverse_transform( + self, scores1: DataArray, scores2: DataArray + ) -> Tuple[DataObject, DataObject]: + """Reconstruct the original data from transformed data. + + Parameters + ---------- + scores1: DataObject + Transformed left field data to be reconstructed. This could be + a subset of the `scores` data of a fitted model, or unseen data. + Must have a 'mode' dimension. + scores2: DataObject + Transformed right field data to be reconstructed. This could be + a subset of the `scores` data of a fitted model, or unseen data. + Must have a 'mode' dimension. + + Returns + ------- + Xrec1: DataArray | Dataset | List[DataArray] + Reconstructed data of left field. + Xrec2: DataArray | Dataset | List[DataArray] + Reconstructed data of right field. + + """ + # Handle scalar mode in xr.dot + if "mode" not in scores1.dims: + scores1 = scores1.expand_dims("mode") + if "mode" not in scores2.dims: + scores2 = scores2.expand_dims("mode") + + data1, data2 = self._inverse_transform_algorithm(scores1, scores2) + + # Unstack and rescale the data + data1 = self.preprocessor1.inverse_transform_data(data1) + data2 = self.preprocessor2.inverse_transform_data(data2) + + return data1, data2 @abstractmethod def _fit_algorithm(self, data1: DataArray, data2: DataArray) -> Self: @@ -233,7 +278,7 @@ def _fit_algorithm(self, data1: DataArray, data2: DataArray) -> Self: @abstractmethod def _transform_algorithm( self, data1: Optional[DataArray] = None, data2: Optional[DataArray] = None - ) -> Sequence[DataArray]: + ) -> Dict[str, DataArray]: """ Transform the preprocessed data. This method needs to be implemented in the respective subclass. @@ -247,9 +292,32 @@ def _transform_algorithm( raise NotImplementedError @abstractmethod - def inverse_transform( - self, scores1: DataObject, scores2: DataObject - ) -> Tuple[DataObject, DataObject]: + def _inverse_transform_algorithm( + self, scores1: DataArray, scores2: DataArray + ) -> Tuple[DataArray, DataArray]: + """ + Reconstruct the original data from transformed data. This method needs to be implemented in the respective + subclass. + + Parameters + ---------- + scores1: DataArray + Transformed left field data to be reconstructed. This could be + a subset of the `scores` data of a fitted model, or unseen data. + Must have a 'mode' dimension. + scores2: DataArray + Transformed right field data to be reconstructed. This could be + a subset of the `scores` data of a fitted model, or unseen data. + Must have a 'mode' dimension. + + Returns + ------- + Xrec1: DataArray + Reconstructed data of left field. + Xrec2: DataArray + Reconstructed data of right field. + + """ raise NotImplementedError def components(self) -> Tuple[DataObject, DataObject]: diff --git a/xeofs/models/_base_model.py b/xeofs/models/_base_model.py index 1144ff57..424c8bd1 100644 --- a/xeofs/models/_base_model.py +++ b/xeofs/models/_base_model.py @@ -7,31 +7,23 @@ Any, List, Literal, - TypeVar, - Tuple, ) from typing_extensions import Self from abc import ABC, abstractmethod from datetime import datetime import dask -import numpy as np import xarray as xr from datatree import DataTree from dask.diagnostics.progress import ProgressBar from ..preprocessing.preprocessor import Preprocessor from ..data_container import DataContainer -from ..utils.data_types import DataObject, Data, DataArray, DataSet, DataList, Dims +from ..utils.data_types import DataObject, Data, DataArray from ..utils.io import insert_placeholders, open_model_tree, write_model_tree from ..utils.sanity_checks import validate_input_type from ..utils.xarray_utils import ( convert_to_dim_type, - get_dims, - feature_ones_like, - convert_to_list, - process_parameter, - _check_parameter_number, data_is_dask, ) from .._version import __version__ @@ -283,13 +275,13 @@ def fit_transform( return self.fit(data, dim, weights).transform(data, **kwargs) def inverse_transform( - self, scores: DataObject, normalized: bool = True + self, scores: DataArray, normalized: bool = True ) -> DataObject: """Reconstruct the original data from transformed data. Parameters ---------- - scores: DataObject + scores: DataArray Transformed data to be reconstructed. This could be a subset of the `scores` data of a fitted model, or unseen data. Must have a 'mode' dimension. @@ -303,8 +295,20 @@ def inverse_transform( """ if normalized: - scores = scores * self.data["norms"] + norms = self.data["norms"].sel(mode=scores.mode) + scores = scores * norms + + # Handle scalar mode in xr.dot + if "mode" not in scores.dims: + scores = scores.expand_dims("mode") + data_reconstructed = self._inverse_transform_algorithm(scores) + + # Reconstructing the data using a single mode introduces a + # redundant "mode" coordinate + if "mode" in data_reconstructed.coords: + data_reconstructed = data_reconstructed.drop_vars("mode") + return self.preprocessor.inverse_transform_data(data_reconstructed) @abstractmethod diff --git a/xeofs/models/cca.py b/xeofs/models/cca.py index 9efd7bbc..d50ec436 100644 --- a/xeofs/models/cca.py +++ b/xeofs/models/cca.py @@ -4,13 +4,12 @@ The original code is licensed under the MIT License. -Copyright (c) 2020-2023 James Chapman +Copyright (c) 2020 onward James Chapman """ from abc import abstractmethod from datetime import datetime -from typing import Sequence, List, Hashable -from typing_extensions import Self +from typing import Hashable, List, Sequence import dask.array as da import numpy as np @@ -18,11 +17,14 @@ from scipy.linalg import eigh from sklearn.base import BaseEstimator from sklearn.utils.validation import FLOAT_DTYPES +from typing_extensions import Self + from xeofs.models import EOF from .._version import __version__ from ..preprocessing.preprocessor import Preprocessor -from ..utils.data_types import DataObject, DataArray, DataList +from ..utils.data_types import DataArray, DataList, DataObject +from ..utils.sanity_checks import assert_not_complex def _check_parameter_number(parameter_name: str, parameter, n_views: int): @@ -171,6 +173,7 @@ def _apply_pca(self, views: DataList): view_transformed = [] for i, view in enumerate(views): + # NOTE: coslat weighting already happens in Preprocessor class pca = EOF(n_modes=n_pca_modes[i], compute=self.compute) pca.fit(view, dim=self.sample_name) if self.compute: @@ -196,20 +199,18 @@ def _apply_pca(self, views: DataList): cum_exp_var_ratio.isel(mode=-1).item() ) ) - n_modes_keep = cum_exp_var_ratio.where( - cum_exp_var_ratio <= self.variance_fraction, drop=True - ).size - if n_modes_keep == 0: - n_modes_keep += 1 - - # TODO: it's more convinient to work the common scaling of sklearn; provide additional parameter - # provide this parameter to transform method as well - scores = pca.scores().isel(mode=slice(0, n_modes_keep)) - svals = pca.singular_values().isel(mode=slice(0, n_modes_keep)) - scores = ( - (scores * svals) - .rename({"mode": self.feature_name}) - .transpose(self.sample_name, self.feature_name) + n_modes_keep = ( + cum_exp_var_ratio.where( + cum_exp_var_ratio <= self.variance_fraction, drop=True + ).size + + 1 + ) + # Take at least 2 modes + n_modes_keep = max(n_modes_keep, 2) + + scores = pca.scores(normalized=False).isel(mode=slice(0, n_modes_keep)) + scores = scores.rename({"mode": self.feature_name}).transpose( + self.sample_name, self.feature_name ) view_transformed.append(scores) return view_transformed @@ -305,6 +306,9 @@ def __init__( self.eps = eps def _fit_algorithm(self, views: List[DataArray]) -> Self: + # Check input data + [assert_not_complex(view) for view in views] + self.c = _process_parameter("c", self.c, 0, self.n_views_) eigvals, eigvecs = self._solve_gevp(views) self.eigvals = eigvals @@ -328,7 +332,7 @@ def _fit_algorithm(self, views: List[DataArray]) -> Self: # Transform the views using the loadings transformed_views = [ xr.dot(view, loading, dims=self.feature_name) - for view, loading in zip(views, self.data["loadings"]) + for view, loading in zip(self.data["input_data"], self.data["loadings"]) ] # Calculate the variance of each latent dimension in the transformed views self.data["explained_variance"] = [ @@ -337,7 +341,7 @@ def _fit_algorithm(self, views: List[DataArray]) -> Self: # Explained variance ratio self.data["total_variance"] = [ - view.var(self.sample_name).sum() for view in views + view.var(self.sample_name, ddof=1).sum() for view in views ] # Calculate the explained variance ratio for each latent dimension for each view diff --git a/xeofs/models/decomposer.py b/xeofs/models/decomposer.py index 1cccc0fe..42da537e 100644 --- a/xeofs/models/decomposer.py +++ b/xeofs/models/decomposer.py @@ -3,7 +3,6 @@ import dask from dask.array import Array as DaskArray # type: ignore from dask.diagnostics.progress import ProgressBar -from numpy.linalg import svd from sklearn.utils.extmath import randomized_svd from scipy.sparse.linalg import svds as complex_svd # type: ignore from dask.array.linalg import svd_compressed as dask_svd @@ -209,7 +208,7 @@ def _svd(self, X, dims, func, kwargs): raise np.linalg.LinAlgError( "SVD failed. This may be due to isolated NaN values in the data. Please consider the following steps:\n" "1. Check for and remove any isolated NaNs in your dataset.\n" - "2. If the error persists, please raise an issue at https://github.com/nicrie/xeofs/issues." + "2. If the error persists, please raise an issue at https://github.com/xarray-contrib/xeofs/issues." ) def _compute_svd_result(self, U, s, VT): diff --git a/xeofs/models/eeof.py b/xeofs/models/eeof.py index bc6c1604..77e6859e 100644 --- a/xeofs/models/eeof.py +++ b/xeofs/models/eeof.py @@ -4,12 +4,9 @@ import numpy as np import xarray as xr -from ._base_model import _BaseModel from .eof import EOF -from .decomposer import Decomposer -from ..utils.data_types import DataArray, Data, Dims +from ..utils.data_types import DataArray from ..data_container import DataContainer -from ..utils.xarray_utils import total_variance as compute_total_variance class ExtendedEOF(EOF): @@ -78,7 +75,7 @@ def __init__( solver: str = "auto", random_state: Optional[int] = None, solver_kwargs: dict = {}, - **kwargs + **kwargs, ): super().__init__( n_modes=n_modes, @@ -92,7 +89,7 @@ def __init__( solver=solver, random_state=random_state, solver_kwargs=solver_kwargs, - **kwargs + **kwargs, ) self.attrs.update({"model": "Extended EOF Analysis"}) self._params.update( diff --git a/xeofs/models/eof.py b/xeofs/models/eof.py index 2e2d0ea9..3ab4cfb0 100644 --- a/xeofs/models/eof.py +++ b/xeofs/models/eof.py @@ -5,9 +5,10 @@ from ._base_model import _BaseModel from .decomposer import Decomposer -from ..utils.data_types import DataObject, DataArray, Dims +from ..utils.data_types import DataObject, DataArray from ..utils.hilbert_transform import hilbert_transform from ..utils.xarray_utils import total_variance as compute_total_variance +from ..utils.sanity_checks import assert_not_complex class EOF(_BaseModel): @@ -128,12 +129,12 @@ def _transform_algorithm(self, data: DataObject) -> DataArray: return projections - def _inverse_transform_algorithm(self, scores: DataObject) -> DataArray: + def _inverse_transform_algorithm(self, scores: DataArray) -> DataArray: """Reconstruct the original data from transformed data. Parameters ---------- - scores: DataObject + scores: DataArray Transformed data to be reconstructed. This could be a subset of the `scores` data of a fitted model, or unseen data. Must have a 'mode' dimension. @@ -147,12 +148,9 @@ def _inverse_transform_algorithm(self, scores: DataObject) -> DataArray: # Reconstruct the data comps = self.data["components"].sel(mode=scores.mode) - reconstructed_data = xr.dot(comps.conj(), scores) + reconstructed_data = xr.dot(comps.conj(), scores, dims="mode") reconstructed_data.name = "reconstructed_data" - # Enforce real output - reconstructed_data = reconstructed_data.real - return reconstructed_data def components(self) -> DataObject: @@ -343,6 +341,8 @@ def __init__( self._params.update({"padding": padding, "decay_factor": decay_factor}) def _fit_algorithm(self, data: DataArray) -> Self: + assert_not_complex(data) + sample_name = self.sample_name feature_name = self.feature_name @@ -387,6 +387,11 @@ def _fit_algorithm(self, data: DataArray) -> Self: def _transform_algorithm(self, data: DataArray) -> DataArray: raise NotImplementedError("Complex EOF does not support transform method.") + def _inverse_transform_algorithm(self, scores: DataArray) -> DataArray: + Xrec = super()._inverse_transform_algorithm(scores) + # Enforce real output + return Xrec.real + def components_amplitude(self) -> DataObject: """Return the amplitude of the (EOF) components. diff --git a/xeofs/models/eof_rotator.py b/xeofs/models/eof_rotator.py index ffb6e5af..eb3e555e 100644 --- a/xeofs/models/eof_rotator.py +++ b/xeofs/models/eof_rotator.py @@ -140,7 +140,7 @@ def _fit_algorithm(self, model) -> Self: loadings, feature_dim=self.feature_name, compute=self._params["compute"], - **promax_kwargs + **promax_kwargs, ) # Assign coordinates to the rotation/correlation matrices diff --git a/xeofs/models/gwpca.py b/xeofs/models/gwpca.py index 9f014077..f9813ce3 100644 --- a/xeofs/models/gwpca.py +++ b/xeofs/models/gwpca.py @@ -1,20 +1,15 @@ -from typing import Sequence, Hashable, Optional, Callable from typing_extensions import Self -from sklearn.utils.extmath import randomized_svd from xeofs.utils.data_types import DataArray -from xeofs.utils.data_types import Data from ._base_model import _BaseModel -from ..utils.sanity_checks import validate_input_type -from ..utils.xarray_utils import convert_to_dim_type +from ..utils.sanity_checks import assert_not_complex from ..utils.constants import ( VALID_CARTESIAN_X_NAMES, VALID_CARTESIAN_Y_NAMES, VALID_LATITUDE_NAMES, VALID_LONGITUDE_NAMES, ) -from .eof import EOF import numpy as np import xarray as xr @@ -115,12 +110,12 @@ def __init__( self.attrs.update({"model": "GWPCA"}) - if not kernel in VALID_KERNELS: + if kernel not in VALID_KERNELS: raise ValueError( f"Invalid kernel: {kernel}. Must be one of {VALID_KERNELS}." ) - if not metric in VALID_METRICS: + if metric not in VALID_METRICS: raise ValueError( f"Invalid metric: {metric}. Must be one of {VALID_METRICS}." ) @@ -136,6 +131,9 @@ def _fit_algorithm(self, X: DataArray) -> Self: # Hide numba imports here to greatly speed up module import time from ..utils.numba_utils import _local_pcas + # Check input type + assert_not_complex(X) + # Convert Dask arrays if not isinstance(X.data, np.ndarray): print( diff --git a/xeofs/models/mca.py b/xeofs/models/mca.py index bd155b93..a00b5efb 100644 --- a/xeofs/models/mca.py +++ b/xeofs/models/mca.py @@ -12,6 +12,7 @@ from ..utils.hilbert_transform import hilbert_transform from ..utils.dimension_renamer import DimensionRenamer from ..utils.xarray_utils import argsort_dask +from ..utils.sanity_checks import assert_not_complex class MCA(_BaseCrossModel): @@ -236,47 +237,45 @@ def transform( def _transform_algorithm( self, data1: Optional[DataArray] = None, data2: Optional[DataArray] = None - ) -> Sequence[DataArray]: - results = [] + ) -> Dict[str, DataArray]: + results = {} if data1 is not None: # Project data onto singular vectors comps1 = self.data["components1"] norm1 = self.data["norm1"] scores1 = xr.dot(data1, comps1) / norm1 - # Inverse transform scores - scores1 = self.preprocessor1.inverse_transform_scores(scores1) - results.append(scores1) + results["data1"] = scores1 if data2 is not None: # Project data onto singular vectors comps2 = self.data["components2"] norm2 = self.data["norm2"] scores2 = xr.dot(data2, comps2) / norm2 - # Inverse transform scores - scores2 = self.preprocessor2.inverse_transform_scores(scores2) - results.append(scores2) + results["data2"] = scores2 return results - def inverse_transform(self, scores1: DataObject, scores2: DataObject): + def _inverse_transform_algorithm( + self, scores1: DataArray, scores2: DataArray + ) -> Tuple[DataArray, DataArray]: """Reconstruct the original data from transformed data. Parameters ---------- - scores1: DataObject + scores1: DataArray Transformed left field data to be reconstructed. This could be a subset of the `scores` data of a fitted model, or unseen data. Must have a 'mode' dimension. - scores2: DataObject + scores2: DataArray Transformed right field data to be reconstructed. This could be a subset of the `scores` data of a fitted model, or unseen data. Must have a 'mode' dimension. Returns ------- - Xrec1: DataArray | Dataset | List[DataArray] + Xrec1: DataArray Reconstructed data of left field. - Xrec2: DataArray | Dataset | List[DataArray] + Xrec2: DataArray Reconstructed data of right field. """ @@ -292,14 +291,6 @@ def inverse_transform(self, scores1: DataObject, scores2: DataObject): data1 = xr.dot(scores1, comps1.conj() * norm1, dims="mode") data2 = xr.dot(scores2, comps2.conj() * norm2, dims="mode") - # Enforce real output - data1 = data1.real - data2 = data2.real - - # Unstack and rescale the data - data1 = self.preprocessor1.inverse_transform_data(data1) - data2 = self.preprocessor2.inverse_transform_data(data2) - return data1, data2 def squared_covariance(self): @@ -380,7 +371,7 @@ def covariance_fraction(self): change_in_cf_in_last_mode = change_per_mode.isel(mode=-1) if change_in_cf_in_last_mode > 0.001: print( - f"Warning: CF is sensitive to the number of modes retained. Please increase `n_modes` for a better estimate." + "Warning: CF is sensitive to the number of modes retained. Please increase `n_modes` for a better estimate." ) cov_frac = svals / tot_var cov_frac.name = "covariance_fraction" @@ -679,6 +670,9 @@ def __init__( self._params.update({"padding": padding, "decay_factor": decay_factor}) def _fit_algorithm(self, data1: DataArray, data2: DataArray) -> Self: + assert_not_complex(data1) + assert_not_complex(data2) + sample_name = self.sample_name feature_name = self.feature_name @@ -908,6 +902,12 @@ def scores_phase(self) -> Tuple[DataArray, DataArray]: def transform(self, data1: DataObject, data2: DataObject): raise NotImplementedError("Complex MCA does not support transform method.") + def _inverse_transform_algorithm(self, scores1: DataArray, scores2: DataArray): + data1, data2 = super()._inverse_transform_algorithm(scores1, scores2) + + # Enforce real output + return data1.real, data2.real + def homogeneous_patterns(self, correction=None, alpha=0.05): raise NotImplementedError( "Complex MCA does not support homogeneous_patterns method." diff --git a/xeofs/models/mca_rotator.py b/xeofs/models/mca_rotator.py index 4c15fae1..6215ff88 100644 --- a/xeofs/models/mca_rotator.py +++ b/xeofs/models/mca_rotator.py @@ -195,7 +195,7 @@ def _fit_algorithm(self, model) -> Self: loadings=loadings, feature_dim=self.feature_name, compute=self._params["compute"], - **promax_kwargs + **promax_kwargs, ) # Assign coordinates to the rotation/correlation matrices diff --git a/xeofs/models/opa.py b/xeofs/models/opa.py index f26924f6..08a4b539 100644 --- a/xeofs/models/opa.py +++ b/xeofs/models/opa.py @@ -8,6 +8,7 @@ from .eof import EOF from .decomposer import Decomposer from ..utils.data_types import DataObject, DataArray +from ..utils.sanity_checks import assert_not_complex class OPA(_BaseModel): @@ -127,6 +128,8 @@ def _compute_matrix_inverse(X, dims): ) def _fit_algorithm(self, data: DataArray) -> Self: + assert_not_complex(data) + sample_name = self.sample_name feature_name = self.feature_name diff --git a/xeofs/preprocessing/concatenator.py b/xeofs/preprocessing/concatenator.py index 0c6f514d..e8e25c69 100644 --- a/xeofs/preprocessing/concatenator.py +++ b/xeofs/preprocessing/concatenator.py @@ -1,7 +1,6 @@ from typing import List, Optional, Dict from typing_extensions import Self -import pandas as pd import numpy as np import xarray as xr @@ -10,13 +9,6 @@ Dims, DimsList, DataArray, - DataSet, - Data, - DataVar, - DataList, - DataArrayList, - DataSetList, - DataVarList, ) diff --git a/xeofs/preprocessing/dimension_renamer.py b/xeofs/preprocessing/dimension_renamer.py index 7ef729d3..537c5815 100644 --- a/xeofs/preprocessing/dimension_renamer.py +++ b/xeofs/preprocessing/dimension_renamer.py @@ -2,7 +2,7 @@ from typing_extensions import Self from .transformer import Transformer -from ..utils.data_types import Dims, DataArray, DataSet, Data, DataVar, DataVarBound +from ..utils.data_types import Dims, DataArray, Data, DataVarBound class DimensionRenamer(Transformer): diff --git a/xeofs/preprocessing/list_processor.py b/xeofs/preprocessing/list_processor.py index 0dd12e93..45fed8b3 100644 --- a/xeofs/preprocessing/list_processor.py +++ b/xeofs/preprocessing/list_processor.py @@ -9,9 +9,7 @@ from ..utils.data_types import ( Data, DataVar, - DataVarBound, DataArray, - DataSet, Dims, DimsList, ) diff --git a/xeofs/preprocessing/multi_index_converter.py b/xeofs/preprocessing/multi_index_converter.py index b27817a1..65c01db4 100644 --- a/xeofs/preprocessing/multi_index_converter.py +++ b/xeofs/preprocessing/multi_index_converter.py @@ -1,9 +1,9 @@ -from typing import List, Optional, Dict +from typing import Optional, Dict from typing_extensions import Self import pandas as pd from .transformer import Transformer -from ..utils.data_types import Dims, DataArray, DataSet, Data, DataVar, DataVarBound +from ..utils.data_types import Dims, DataArray, Data, DataVar, DataVarBound class MultiIndexConverter(Transformer): diff --git a/xeofs/preprocessing/preprocessor.py b/xeofs/preprocessing/preprocessor.py index 9ee57539..22fc2cf7 100644 --- a/xeofs/preprocessing/preprocessor.py +++ b/xeofs/preprocessing/preprocessor.py @@ -2,7 +2,6 @@ from typing_extensions import Self import numpy as np -import xarray as xr from datatree import DataTree from .list_processor import GenericListTransformer diff --git a/xeofs/preprocessing/sanitizer.py b/xeofs/preprocessing/sanitizer.py index 08bccc27..71e5a40e 100644 --- a/xeofs/preprocessing/sanitizer.py +++ b/xeofs/preprocessing/sanitizer.py @@ -5,7 +5,7 @@ import xarray as xr from .transformer import Transformer -from ..utils.data_types import Dims, DataArray, DataSet, Data, DataVar +from ..utils.data_types import Dims, DataArray, Data class Sanitizer(Transformer): @@ -65,7 +65,7 @@ def fit( X: Data, sample_dims: Optional[Dims] = None, feature_dims: Optional[Dims] = None, - **kwargs + **kwargs, ) -> Self: # Check if input is a DataArray self._check_input_type(X) diff --git a/xeofs/preprocessing/scaler.py b/xeofs/preprocessing/scaler.py index 8da97e64..c2d4284d 100644 --- a/xeofs/preprocessing/scaler.py +++ b/xeofs/preprocessing/scaler.py @@ -6,7 +6,7 @@ import xarray as xr from .transformer import Transformer -from ..utils.data_types import Dims, DataArray, DataSet, Data, DataVar, DataVarBound +from ..utils.data_types import Dims, DataArray, DataVar, DataVarBound from ..utils.xarray_utils import compute_sqrt_cos_lat_weights, feature_ones_like diff --git a/xeofs/preprocessing/stacker.py b/xeofs/preprocessing/stacker.py index f2a57b04..76838bae 100644 --- a/xeofs/preprocessing/stacker.py +++ b/xeofs/preprocessing/stacker.py @@ -98,13 +98,13 @@ def _validate_dims(self, X: Data, sample_dims, feature_dims): invalid_feature_dims = True if len(feature_dims) < 1 else False if invalid_sample_dims: - raise ValueError(f"Sample dimension must not be empty.") + raise ValueError("Sample dimension must not be empty.") if invalid_feature_dims: match X: case xr.DataArray(): - raise ValueError(f"Feature dimension must not be empty.") + raise ValueError("Feature dimension must not be empty.") case xr.Dataset(): - err_msg = f"Dataset without feature dimension is currently not supported. Please convert your Dataset to a DataArray first, e.g. by using `to_array()`." + err_msg = "Dataset without feature dimension is currently not supported. Please convert your Dataset to a DataArray first, e.g. by using `to_array()`." raise ValueError(err_msg) case _: raise TypeError(f"Invalid data type {type(X)}.") @@ -112,7 +112,7 @@ def _validate_dims(self, X: Data, sample_dims, feature_dims): def _validate_indices(self, X: Data): """Check that the indices of the data are no MultiIndex""" if any([isinstance(index, pd.MultiIndex) for index in X.indexes.values()]): - raise ValueError(f"Cannot stack data containing a MultiIndex.") + raise ValueError("Cannot stack data containing a MultiIndex.") def _sanity_check(self, X: Data, sample_dims, feature_dims): self._validate_dims(X, sample_dims, feature_dims) @@ -186,7 +186,7 @@ def _stack(self, X: Data, sample_dims: Dims, feature_dims: Dims) -> DataArray: # There's only one sample dimension and it's already named correctly pass else: - raise ValueError(f"Sample dimension must not be empty.") + raise ValueError("Sample dimension must not be empty.") # Stack FEATURE dimension match X: @@ -200,7 +200,7 @@ def _stack(self, X: Data, sample_dims: Dims, feature_dims: Dims) -> DataArray: # There's only one feature dimension and it's already named correctly pass else: - raise ValueError(f"Feature dimension must not be empty.") + raise ValueError("Feature dimension must not be empty.") case xr.Dataset(): X = X.to_stacked_array( diff --git a/xeofs/preprocessing/transformer.py b/xeofs/preprocessing/transformer.py index fe47cc66..354ad1bd 100644 --- a/xeofs/preprocessing/transformer.py +++ b/xeofs/preprocessing/transformer.py @@ -8,7 +8,7 @@ from datatree import DataTree from sklearn.base import BaseEstimator, TransformerMixin -from ..utils.data_types import Dims, DataVar, DataArray, DataSet, Data, DataVarBound +from ..utils.data_types import Dims, DataArray, DataSet, Data class Transformer(BaseEstimator, TransformerMixin, ABC): @@ -88,25 +88,33 @@ def inverse_transform_scores(self, X: DataArray) -> DataArray: def inverse_transform_scores_unseen(self, X: DataArray) -> DataArray: return X - def _serialize_data(self, key: str, data: DataArray) -> DataSet: - # Make sure the DataArray has some name so we can create a string mapping - if data.name is None: - data.name = key - + def _serialize_data(self, key: str, data: Data) -> DataSet: multiindexes = {} - if data.name in data.coords: - # Create coords-based datasets and note multiindexes - if isinstance(data.to_index(), pd.MultiIndex): - multiindexes[data.name] = [n for n in data.to_index().names] - ds = xr.Dataset(coords={data.name: data}) + name_map = None + if isinstance(data, xr.Dataset): + # Keep Dataset as is + ds = data else: - # Create data-based datasets - ds = xr.Dataset(data_vars={data.name: data}) + # Convert DataArray to Dataset + coords = {} + data_vars = {} + if data.name in data.coords: + # Convert a coord-like DataArray to Dataset and note multiindexes + if isinstance(data.to_index(), pd.MultiIndex): + multiindexes[data.name] = [n for n in data.to_index().names] + coords[data.name] = data + else: + # Make sure the DataArray has some name so we can create a string mapping + if data.name is None: + data.name = key + data_vars[data.name] = data + ds = xr.Dataset(data_vars=data_vars, coords=coords) + name_map = data.name # Drop multiindexes and record for later ds = ds.reset_index(list(multiindexes.keys())) ds.attrs["multiindexes"] = multiindexes - ds.attrs["name_map"] = {key: data.name} + ds.attrs["name_map"] = {key: name_map} return ds @@ -127,7 +135,7 @@ def _serialize(self) -> DataTree: # Serialize each transformer attribute for key, attr in attrs.items(): - if isinstance(attr, xr.DataArray): + if isinstance(attr, (xr.DataArray, xr.Dataset)): # attach data to data_vars or coords ds = self._serialize_data(key, attr) dt[key] = DataTree(name=key, data=ds) @@ -148,13 +156,15 @@ def _serialize(self) -> DataTree: return dt - def _deserialize_data_node(self, key: str, ds: xr.Dataset) -> DataArray: + def _deserialize_data_node(self, key: str, dt: DataTree) -> DataArray: # Rebuild multiindexes - ds = ds.set_index(ds.attrs.get("multiindexes", {})) + dt = dt.set_index(dt.attrs.get("multiindexes", {})) # Extract the DataArray or coord from the Dataset - data_key = ds.attrs["name_map"][key] - data = ds[data_key] - return data + data_key = dt.attrs["name_map"][key] + if data_key is not None: + return dt[data_key] + else: + return dt.ds @classmethod def deserialize(cls, dt: DataTree) -> Self: diff --git a/xeofs/utils/data_types.py b/xeofs/utils/data_types.py index 4e77a82a..175eb10a 100644 --- a/xeofs/utils/data_types.py +++ b/xeofs/utils/data_types.py @@ -8,7 +8,6 @@ ) import dask.array as da -import xarray as xr from xarray.core import dataarray as xr_dataarray from xarray.core import dataset as xr_dataset diff --git a/xeofs/utils/numba_utils.py b/xeofs/utils/numba_utils.py index bbac0e18..4902545a 100644 --- a/xeofs/utils/numba_utils.py +++ b/xeofs/utils/numba_utils.py @@ -184,4 +184,4 @@ def local_pca_vectorized( for i in range(n_out.shape[0]): expvar[i] = lbda[i] comps[:, i] = Vt[i, :] - totvar = lbda.sum() + lbda.sum() diff --git a/xeofs/utils/sanity_checks.py b/xeofs/utils/sanity_checks.py index ddc5bb90..0cdd2bff 100644 --- a/xeofs/utils/sanity_checks.py +++ b/xeofs/utils/sanity_checks.py @@ -1,4 +1,4 @@ -from typing import Sequence, Hashable, Tuple, Any +from typing import Any import xarray as xr @@ -93,3 +93,10 @@ def validate_input_type(X) -> None: raise TypeError(err_msg) else: raise TypeError(err_msg) + + +def assert_not_complex(da: xr.DataArray) -> None: + if da.dtype == "complex": + raise TypeError( + "Invalid input type. This method does not support complex data types." + ) diff --git a/xeofs/utils/statistics.py b/xeofs/utils/statistics.py index adeb035c..1ac6eca2 100644 --- a/xeofs/utils/statistics.py +++ b/xeofs/utils/statistics.py @@ -1,5 +1,3 @@ -from typing import Tuple - import xarray as xr import scipy as sc from statsmodels.stats.multitest import multipletests as statsmodels_multipletests diff --git a/xeofs/utils/xarray_utils.py b/xeofs/utils/xarray_utils.py index d2dfbc84..8b169e03 100644 --- a/xeofs/utils/xarray_utils.py +++ b/xeofs/utils/xarray_utils.py @@ -188,7 +188,7 @@ def get_dims( return sample_dims, feature_dims else: err_message = f"Invalid input type: {type(data).__name__}. Expected one of " - err_message += f"of the following: list of DataArrays or Datasets." + err_message += "of the following: list of DataArrays or Datasets." raise TypeError(err_message) diff --git a/xeofs/validation/__init__.py b/xeofs/validation/__init__.py index 1b7f1ab9..ffcd0c8e 100644 --- a/xeofs/validation/__init__.py +++ b/xeofs/validation/__init__.py @@ -1 +1,3 @@ from .bootstrapper import EOFBootstrapper + +__all__ = ["EOFBootstrapper"] diff --git a/xeofs/validation/bootstrapper.py b/xeofs/validation/bootstrapper.py index a5c2111c..8a1c78a4 100644 --- a/xeofs/validation/bootstrapper.py +++ b/xeofs/validation/bootstrapper.py @@ -57,7 +57,6 @@ def fit(self, model: EOF): self.model = model self.preprocessor = model.preprocessor sample_name = model.sample_name - feature_name = model.feature_name input_data = model.data["input_data"] n_samples = input_data.sample.size