diff --git a/.all-contributorsrc b/.all-contributorsrc index c9e690f0e..bfdbf3cc6 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -470,6 +470,41 @@ "contributions": [ "ideas" ] + }, + { + "login": "cclauss", + "name": "Christian Clauss", + "avatar_url": "https://avatars.githubusercontent.com/u/3709715?v=4", + "profile": "https://github.com/cclauss", + "contributions": [ + "maintenance", + "review", + "tool" + ] + }, + { + "login": "jrenrut", + "name": "Jeremy Turner", + "avatar_url": "https://avatars.githubusercontent.com/u/42989238?v=4", + "profile": "https://github.com/jrenrut", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "mfisher87", + "name": "Matt Fisher", + "avatar_url": "https://avatars.githubusercontent.com/u/3608264?v=4", + "profile": "https://mfisher87.github.io/", + "contributions": [ + "bug", + "code", + "doc", + "maintenance", + "test", + "infra" + ] } ], "contributorsPerLine": 7, diff --git a/.github/actions/install-icepyx/action.yml b/.github/actions/install-icepyx/action.yml new file mode 100644 index 000000000..fb738d7cd --- /dev/null +++ b/.github/actions/install-icepyx/action.yml @@ -0,0 +1,19 @@ +name: 'Install icepyx' +description: 'Install icepyx and dev dependencies' + +inputs: + python-version: + required: true + +runs: + using: "composite" + steps: + - uses: "actions/setup-python@v5" + with: + python-version: "${{ inputs.python-version }}" + + - name: "Install package and test dependencies" + shell: "bash" + run: | + python -m pip install . + python -m pip install -r requirements-dev.txt diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..0b84a2431 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +# Keep GitHub Actions up to date with GitHub's Dependabot... +# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + groups: + github-actions: + patterns: + - "*" # Group all Actions updates into a single larger pull request + schedule: + interval: monthly diff --git a/.github/workflows/get_pypi_stats.yml b/.github/workflows/get_pypi_stats.yml index 3461ef953..3ff8d14ea 100644 --- a/.github/workflows/get_pypi_stats.yml +++ b/.github/workflows/get_pypi_stats.yml @@ -16,7 +16,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "traffic" diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml new file mode 100644 index 000000000..4bc27655e --- /dev/null +++ b/.github/workflows/integration_test.yml @@ -0,0 +1,49 @@ +name: "Integration test" +# NOTE: We're just running the tests that require earthdata login here; we +# don't distinguish between unit and integration tests yet. + +on: + push: + branches: + - "main" # Releases + - "development" # Feature PR merges + pull_request: + branches: + - "main" # Release PRs + workflow_dispatch: + inputs: + ref: + description: "The ref to test" + type: "string" + + +jobs: + test: + name: "Integration test" + # Do not run on PRs from forks: + if: "${{ !github.event.pull_request.head.repo.fork }}" + runs-on: "ubuntu-latest" + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + ref: "${{ inputs.ref }}" + + - uses: "./.github/actions/install-icepyx" + with: + python-version: "3.12" + + - name: "Run tests" + env: + EARTHDATA_PASSWORD: "${{ secrets.EARTHDATA_PASSWORD }}" + NSIDC_LOGIN: "${{ secrets.EARTHDATA_PASSWORD }}" + run: | + pytest icepyx/ --verbose --cov app \ + icepyx/tests/test_behind_NSIDC_API_login.py \ + icepyx/tests/test_auth.py + + - name: "Upload coverage report" + uses: "codecov/codecov-action@v4.5.0" + with: + token: "${{ secrets.CODECOV_TOKEN }}" diff --git a/.github/workflows/publish_to_pypi.yml b/.github/workflows/publish_to_pypi.yml index e7fadd774..bd633e877 100644 --- a/.github/workflows/publish_to_pypi.yml +++ b/.github/workflows/publish_to_pypi.yml @@ -22,13 +22,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # fetch all history so that setuptools-scm works fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 diff --git a/.github/workflows/traffic_action.yml b/.github/workflows/traffic_action.yml index 97705285f..15f153bed 100644 --- a/.github/workflows/traffic_action.yml +++ b/.github/workflows/traffic_action.yml @@ -17,13 +17,13 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "traffic" # Calculates traffic and clones and stores in CSV file - name: GitHub traffic - uses: sangonzal/repository-traffic-action@v0.1.4 + uses: sangonzal/repository-traffic-action@v.0.1.6 env: TRAFFIC_ACTION_TOKEN: ${{ secrets.TRAFFIC_ACTION_TOKEN }} diff --git a/.github/workflows/uml_action.yml b/.github/workflows/uml_action.yml index b85885023..60c4e0cf0 100644 --- a/.github/workflows/uml_action.yml +++ b/.github/workflows/uml_action.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.ref }} - name: set up environment diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml new file mode 100644 index 000000000..989c7e298 --- /dev/null +++ b/.github/workflows/unit_test.yml @@ -0,0 +1,40 @@ +name: "Unit test" +# NOTE: We're just skipping the tests requiring earthdata login here; we don't +# distinguish yet between unit and integration tests. + +on: + pull_request: + push: + branches: + - "main" + - "development" + + +jobs: + test: + name: "Unit test (Python ${{ matrix.python-version }})" + runs-on: "ubuntu-latest" + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.12"] #NOTE: min and max Python versions supported by icepyx + + steps: + - uses: "actions/checkout@v4" + with: + fetch-depth: 0 + + - uses: "./.github/actions/install-icepyx" + with: + python-version: "${{ matrix.python-version }}" + + - name: "Run tests" + run: | + pytest icepyx/ --verbose --cov app \ + --ignore=icepyx/tests/test_behind_NSIDC_API_login.py \ + --ignore=icepyx/tests/test_auth.py + + - name: "Upload coverage report" + uses: "codecov/codecov-action@v4.5.0" + with: + token: "${{ secrets.CODECOV_TOKEN }}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 62fe68370..cbb4ad81d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,17 +6,37 @@ repos: - id: check-yaml - id: check-added-large-files args: ["--maxkb=5000"] + - id: check-case-conflict + - id: check-merge-conflict + - id: check-symlinks + - id: debug-statements + - id: name-tests-test + args: ["--pytest-test-first"] - id: end-of-file-fixer + - id: mixed-line-ending - id: trailing-whitespace args: [--markdown-linebreak-ext=md] + - id: requirements-txt-fixer + + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + additional_dependencies: + - tomli - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.7 + rev: v0.6.3 hooks: - id: ruff args: ["--fix", "--show-fixes"] - id: ruff-format + - repo: https://github.com/abravalheri/validate-pyproject + rev: v0.19 + hooks: + - id: validate-pyproject + ci: autoupdate_schedule: monthly diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b3d7081e7..000000000 --- a/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -language: python - -before_install: - - sudo apt-get update - - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh - - bash miniconda.sh -b -p $HOME/miniconda - - export PATH="$HOME/miniconda/bin:$PATH" - - hash -r - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - # Useful for debugging any issues with conda - - conda info -a - -install: - - conda create --name icepyx-env --channel conda-forge python=3.10 proj geos - - source activate icepyx-env - - pip install -r requirements.txt -r requirements-dev.txt - - pip install -e .[complete] - -stages: - - name: basic tests - if: (type = pull_request) OR (type = push AND repo = icesat2py/icepyx AND branch IN (main, development)) - - name: behind Earthdata - if: branch = main OR commit_message =~ nsidc_tests OR type = cron - -#ultimately move basic tests list into a separate script with the list of files to run (then this can be put into a matrix and parallellized as well) -jobs: - include: - - stage: basic tests - script: pytest icepyx/ --verbose --cov app --ignore icepyx/tests/test_behind_NSIDC_API_login.py - # includes an integrity check of the uploader as recommended by CodeCov - after_success: - - curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import # One-time step - - curl -Os https://uploader.codecov.io/latest/linux/codecov - - curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM - - curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM.sig - - gpgv codecov.SHA256SUM.sig codecov.SHA256SUM - - shasum -a 256 -c codecov.SHA256SUM - - chmod +x codecov - - ./codecov -t ${CODECOV_TOKEN} - - stage: behind Earthdata - script: - - export EARTHDATA_PASSWORD=$NSIDC_LOGIN - - pytest icepyx/tests/test_behind_NSIDC_API_login.py diff --git a/ATTRIBUTION.rst b/ATTRIBUTION.rst index 655a678db..a595e32d4 100644 --- a/ATTRIBUTION.rst +++ b/ATTRIBUTION.rst @@ -99,7 +99,7 @@ to identify core issues and propose solutions to challenges around software cred For software, current best practices (`e.g. `_) emphasize the importance of having a document such as this one to describe an individual community's policies for credit, authorship, and attribution. This document is an effort to describe icepyx's policies, with an awareness that they may change -to accomodate community growth, best practices, and feedback. +to accommodate community growth, best practices, and feedback. We do not attempt to identify contribution levels through the number of commits made to the repository (e.g. ``git shortlog -sne``) or active engagement on GitHub (e.g. through issues, discussions, and pull requests) and Discourse. diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 5d5c4530c..aeea99573 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -17,51 +17,56 @@ Thanks goes to these wonderful people (`emoji key Anna Valentine
Anna Valentine

πŸ’‘ Anthony Arendt
Anthony Arendt

πŸ› πŸ’Ό πŸ“‹ πŸ” Bruce Wallin
Bruce Wallin

πŸ’» πŸ“– πŸ€” πŸ‘€ πŸ’¬ + Christian Clauss
Christian Clauss

🚧 πŸ‘€ πŸ”§ David Shean
David Shean

πŸ› πŸ§‘β€πŸ« Don Setiawan
Don Setiawan

πŸš‡ πŸ“¦ - Facundo Sapienza
Facundo Sapienza

πŸ’‘ πŸ› + Facundo Sapienza
Facundo Sapienza

πŸ’‘ πŸ› Fernando Perez
Fernando Perez

🎨 πŸ’Ό πŸ€” JP Swinski
JP Swinski

πŸ’» πŸ‘€ + Jeremy Turner
Jeremy Turner

πŸ› πŸ’» Jessica
Jessica

πŸ› πŸ’» πŸ–‹ πŸ“– 🎨 πŸ’‘ πŸ€” 🚧 πŸ§‘β€πŸ« πŸ“† πŸ’¬ πŸ‘€ Joachim Meyer
Joachim Meyer

πŸ§‘β€πŸ« 🚧 Kelsey Bisson
Kelsey Bisson

πŸ› πŸ’» πŸ“– πŸ€” πŸ’‘ πŸ€” πŸ§‘β€πŸ« πŸ’¬ πŸ‘€ βœ… - Lindsey Heagy
Lindsey Heagy

πŸ§‘β€πŸ« πŸ‘€ - Molly Wieringa
Molly Wieringa

πŸ€” + Lindsey Heagy
Lindsey Heagy

πŸ§‘β€πŸ« πŸ‘€ + Matt Fisher
Matt Fisher

πŸ› πŸ’» πŸ“– 🚧 ⚠️ πŸš‡ + Molly Wieringa
Molly Wieringa

πŸ€” Nicole Abib
Nicole Abib

πŸ’» πŸ€” Rachel Wegener
Rachel Wegener

πŸ› πŸ’» πŸ“– πŸ€” 🚧 πŸ‘€ ⚠️ βœ… Raphael Hagen
Raphael Hagen

πŸ“– 🎨 πŸ’» πŸš‡ πŸ‘€ Romina Piunno
Romina Piunno

πŸ’» πŸ€” πŸ§‘β€πŸ« πŸ‘€ βœ… + + Sarah Hall
Sarah Hall

πŸ› πŸ’» πŸ“– 🚧 ⚠️ Scott Henderson
Scott Henderson

🚧 Sebastian Alvis
Sebastian Alvis

πŸ“– πŸš‡ - - Shashank Bhushan
Shashank Bhushan

πŸ’‘ Tian Li
Tian Li

πŸ› πŸ’» πŸ“– πŸ’‘ πŸ€” πŸ‘€ ⚠️ πŸ”§ Tom Johnson
Tom Johnson

πŸ“– πŸš‡ Tyler Sutterley
Tyler Sutterley

πŸ“– πŸ’» πŸ€” πŸ’¬ πŸ›‘οΈ ⚠️ + + Wei Ji
Wei Ji

πŸ› πŸ’» πŸ“– πŸ’‘ πŸ€” πŸš‡ 🚧 πŸ§‘β€πŸ« πŸ’¬ πŸ‘€ ⚠️ πŸ“’ Whyjay Zheng
Whyjay Zheng

βœ… πŸ› πŸ’» πŸ‘€ Wilson Sauthoff
Wilson Sauthoff

πŸ‘€ - - Zach Fair
Zach Fair

πŸ› πŸ’» πŸ“– πŸ€” πŸ’¬ πŸ‘€ βœ… alexdibella
alexdibella

πŸ› πŸ€” πŸ’» bidhya
bidhya

πŸ’‘ learn2phoenix
learn2phoenix

πŸ’» + + liuzheng-arctic
liuzheng-arctic

πŸ“– πŸ› πŸ’» πŸ€” πŸ‘€ πŸ”§ πŸ’‘ nitin-ravinder
nitin-ravinder

πŸ› πŸ‘€ ravindraK08
ravindraK08

πŸ‘€ - - rtilling
rtilling

πŸ€” smithb
smithb

πŸ€” tedmaksym
tedmaksym

πŸ€” trevorskaggs
trevorskaggs

πŸ› πŸ’» + + trey-stafford
trey-stafford

πŸ’» πŸ€” 🚧 πŸ‘€ πŸ’¬ diff --git a/README.rst b/README.rst index 5240a1113..b89dd51e0 100644 --- a/README.rst +++ b/README.rst @@ -7,9 +7,9 @@ icepyx |JOSS| |Zenodo-all| -Latest release (main branch): |Docs Status main| |Travis main Build Status| |Code Coverage main| +Latest release (main branch): |Docs Status main| |Unit Tests Status (main)| |Integration Tests Status (main)| |Code Coverage main| -Current development version (development branch): |Docs Status dev| |Travis dev Build Status| |Code Coverage dev| |Pre-commit dev| +Current development version (development branch): |Docs Status dev| |Unit Tests Status (dev)| |Integration Tests Status (main)| |Code Coverage dev| |Pre-commit dev| .. |GitHub license| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg :target: https://opensource.org/licenses/BSD-3-Clause @@ -38,11 +38,17 @@ Current development version (development branch): |Docs Status dev| |Travis dev .. |Docs Status dev| image:: https://readthedocs.org/projects/icepyx/badge/?version=development :target: https://icepyx.readthedocs.io/en/development -.. |Travis main Build Status| image:: https://app.travis-ci.com/icesat2py/icepyx.svg?branch=main - :target: https://app.travis-ci.com/icesat2py/icepyx +.. |Unit Tests Status (main)| image:: https://github.com/icesat2py/icepyx/actions/workflows/unit_test.yml/badge.svg?branch=main + :target: https://github.com/icesat2py/icepyx/actions/workflows/unit_test.yml -.. |Travis dev Build Status| image:: https://app.travis-ci.com/icesat2py/icepyx.svg?branch=development - :target: https://app.travis-ci.com/icesat2py/icepyx +.. |Integration Tests Status (main)| image:: https://github.com/icesat2py/icepyx/actions/workflows/integration_test.yml/badge.svg?branch=main + :target: https://github.com/icesat2py/icepyx/actions/workflows/integration_test.yml + +.. |Unit Tests Status (dev)| image:: https://github.com/icesat2py/icepyx/actions/workflows/unit_test.yml/badge.svg?branch=development + :target: https://github.com/icesat2py/icepyx/actions/workflows/unit_test.yml + +.. |Integration Tests Status (dev)| image:: https://github.com/icesat2py/icepyx/actions/workflows/integration_test.yml/badge.svg?branch=development + :target: https://github.com/icesat2py/icepyx/actions/workflows/integration_test.yml .. |Code Coverage main| image:: https://codecov.io/gh/icesat2py/icepyx/branch/main/graph/badge.svg :target: https://codecov.io/gh/icesat2py/icepyx @@ -85,6 +91,32 @@ Alternatively, you can also install icepyx using `pip `_. -For contribution examples, please see contribution guidelines. +For contribution examples, please see :doc:`contribution guidelines `. Contributing for the first time @@ -13,52 +13,60 @@ Contributing for the first time 1. If you don't have one, sign up for a GitHub account (visit https://github.com/ and β€˜sign up for GitHub account’). 2. Clone the icepyx repo: Open a terminal window. -Navigate to the folder on your computer where you want to store icepyx. -For example, + Navigate to the folder on your computer where you want to store icepyx. + For example, -.. code-block:: shell + .. code-block:: shell - cd /Users/YOURNAMEHERE/documents/ICESat-2 + cd /Users/YOURNAMEHERE/documents/ICESat-2 -Within this folder, clone the icepyx repo by executing + Within this folder, clone the icepyx repo by executing -.. code-block:: shell + .. code-block:: shell - git clone https://github.com/icesat2py/icepyx.git + git clone https://github.com/icesat2py/icepyx.git -You should receive confirmation in terminal of the files loading into your workspace. -For help navigating git and GitHub, see this `guide `__. -`GitHub `_ also provides a lot of great how-to materials for navigating and contributing. +You should receive confirmation in terminal of the files downloading into your workspace. +For help navigating ``git`` and GitHub, see this `guide `__. +`GitHub `_ also provides great how-to materials for navigating and contributing. Every time you contribute ------------------------- +.. important:: + + If you do not have write permissions on this repository, start with creating a fork by clicking the Fork button in GitHub. + All actions from here on should be performed in your fork. + 1. To add new content, you need to create a new branch. -You can do this on GitHub by clicking the down arrow next to β€˜development’ and making a new branch -(you can give it whatever name you want - the naming doesn't matter much as it will only be a temporary branch). + You can do this on GitHub by clicking the down arrow next to β€˜development’ and making a new branch + (you can give it whatever name you want - the naming doesn't matter much as it will only be a temporary branch). 2. Navigate to the new branch you created. -Make any edits or additions on this branch (this can be done locally or on GitHub directly). -After you do this, commit your changes and add a descriptive commit message. + Make any edits or additions on this branch (this can be done locally with ``git`` or on GitHub directly). + After you do this, commit your changes and add a descriptive commit message. -3. After committing the changes, push them to GitHub if you were working locally. -Then, open a pull request to merge your branch into the development branch. -Members of the icepyx community will review your changes and may ask you to make some more. +3. Push your new commits to GitHub if you were working locally. + Then, open a pull request to merge your branch into the ``development`` branch. + Members of the icepyx community will review your changes and may ask you to make some more. 4. If this is your first PR, someone on the icepyx team should add you to the contributors list. -icepyx follows the `all-contributors `_ specification using the contributors bot to add new contributors. -You are also welcome to add yourself by adding a comment with the text: + icepyx follows the `all-contributors `_ specification using the contributors bot to add new contributors. + You are also welcome to add yourself by adding a comment with the text: -.. code-block:: none + .. code-block:: none - @all-contributors add @[GitHub_handle] for a, b, and c + @all-contributors add @[GitHub_handle] for a, b, and c -where a, b, etc. is a list of the appropriate `contribution emojis `_. -The bot will open a separate PR to add the contributor or new contribution types! + where a, b, etc. is a list of the appropriate `contribution emojis `_. + The bot will open a separate PR to add the contributor or new contribution types! 5. Repeat these steps, creating a new branch and ultimately a pull request for each change. -More, smaller pull requests are easier to debug and merge than fewer large ones, so create pull requests regularly! + + .. tip:: + + More, smaller pull requests are easier to debug and merge than fewer large ones, so please create pull requests regularly! Steps for working with icepyx locally @@ -94,10 +102,10 @@ environment (from the home level of your local copy of the icepyx repo) with mamba env create --name icepyx-env --channel conda-forge -f requirements-dev.txt -f requirements.txt -and then (1) running `pre-commit install` to let git know about pre-commit and +and then (1) running ``pre-commit install`` to let git know about pre-commit and (2) pip installing icepyx as described above and below. -One of the tools installed with "requirements-dev.txt" is called [pre-commit](https://pre-commit.com/). +One of the tools installed with "requirements-dev.txt" is called `pre-commit `_. We have included a set of pre-commit formatting hooks that we strongly encourage all contributors to use. These hooks will check the files you are committing for format consistency, reformatting the files if necessary. diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst index 61c3e8ccb..53909d8ae 100644 --- a/doc/source/contributing/icepyx_internals.rst +++ b/doc/source/contributing/icepyx_internals.rst @@ -13,7 +13,7 @@ by any modules that need an Earthdata login. **Property Access** -Even though they aren't explicity defined in the init method, properties +Even though they aren't explicitly defined in the init method, properties like ``.session`` are accessible on a Query object because they are inherited. The code that indicates this to Python is ``EarthdataAuthMixin.__init__(self)``. diff --git a/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb b/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb index bf1bc8af4..f6cef3494 100644 --- a/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb +++ b/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb @@ -81,7 +81,7 @@ "import shutil\n", "import h5py\n", "import xarray as xr\n", - "# depedencies\n", + "# dependencies\n", "import getpass\n", "#from topolib.subsetDat import subsetBBox;\n", "from topolib import icesat2_data\n", @@ -265,7 +265,7 @@ "metadata": {}, "source": [ "## Preprocess #2\n", - "- Convert data into geopandas dataframe, which allows for doing basing geospatial opertaions" + "- Convert data into geopandas dataframe, which allows for doing basing geospatial operations" ] }, { @@ -316,7 +316,7 @@ "metadata": {}, "outputs": [], "source": [ - "# dict containing data entries to retrive\n", + "# dict containing data entries to retrieve\n", "dataset_dict = {'land_segments':['delta_time','longitude','latitude','atl06_quality_summary','quality','terrain_flg'], 'land_segments/terrain':['h_te_best_fit']}" ] }, @@ -438,7 +438,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## We will use the TANDEM-X Global DEM for our comparison. The resolution of the globally avaialable product is 90 m, with *horizontal* and *vertical* accuracy better than 2 to 3 m.\n", + "## We will use the TANDEM-X Global DEM for our comparison. The resolution of the globally available product is 90 m, with *horizontal* and *vertical* accuracy better than 2 to 3 m.\n", "- TANDEM-X DEM for the region was downloaded and preprocessed, filtered using scripts from the [tandemx](https://github.com/dshean/tandemx) repository" ] }, @@ -741,7 +741,7 @@ "metadata": {}, "outputs": [], "source": [ - "### Save the geodataframe in the specified way as expected by Ames Stereo Pipline\n", + "### Save the geodataframe in the specified way as expected by Ames Stereo Pipeline\n", "icesat2_pc = '/home/jovyan/icesat2/icesat2_colombia_pc.csv' \n", "gdf_colombia_dem_extent[['latitude','longitude','h_te_best_fit']].to_csv(icesat2_pc,header=False,index=None)" ] @@ -761,7 +761,7 @@ "metadata": {}, "outputs": [], "source": [ - "### Save the geodataframe in the specified way as expected by Ames Stereo Pipline\n", + "### Save the geodataframe in the specified way as expected by Ames Stereo Pipeline\n", "icesat2_pc = '/home/jovyan/icesat2/icesat2_colombia_pc.csv'\n", "pc_rename_dict = {'latitude':'lat','longitude':'lon','h_te_best_fit':'height_above_datum'}\n", "gdf_colombia_dem_extent = gdf_colombia_dem_extent.rename(columns=pc_rename_dict)\n", @@ -867,7 +867,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "- We see that after coregistration, the bias reduces to an extent. Note that this is a very preliminary analysis, results will be better after filtering the ATL08 points based on quality metrics and finding truly static surfaces (snow free during acquisiton time of ICESat-2 points)" + "- We see that after coregistration, the bias reduces to an extent. Note that this is a very preliminary analysis, results will be better after filtering the ATL08 points based on quality metrics and finding truly static surfaces (snow free during acquisition time of ICESat-2 points)" ] }, { diff --git a/doc/source/example_notebooks/IS2_cloud_data_access.ipynb b/doc/source/example_notebooks/IS2_cloud_data_access.ipynb index 194e25210..3f448aa4b 100644 --- a/doc/source/example_notebooks/IS2_cloud_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_cloud_data_access.ipynb @@ -352,7 +352,7 @@ "source": [ "### Some important caveats\n", "\n", - "While the cloud data reading is functional within icepyx, it is very slow. Approximate timing shows it takes ~6 minutes of load time per variable per file from s3. Because of this you will recieve a warning if you try to load either more than three variables or two files at once.\n", + "While the cloud data reading is functional within icepyx, it is very slow. Approximate timing shows it takes ~6 minutes of load time per variable per file from s3. Because of this you will receive a warning if you try to load either more than three variables or two files at once.\n", "\n", "The slow load speed is a demonstration of the many steps involved in making cloud data actionable - the data supply chain needs optimized source data, efficient low level data readers, and high level libraries which are enabled to use the fastest low level data readers. Not all of these pieces fully developed right now, but the progress being made it exciting and there is lots of room for contribution!" ] diff --git a/doc/source/example_notebooks/IS2_data_access.ipynb b/doc/source/example_notebooks/IS2_data_access.ipynb index 67f94a7e7..268a9a3b9 100644 --- a/doc/source/example_notebooks/IS2_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_data_access.ipynb @@ -485,7 +485,7 @@ }, "source": [ "```{admonition} Important Authentication Update\n", - "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is deprecated and will result in an error, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed above.\n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is deprecated and will result in an error, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods described above.\n", "```" ] }, @@ -504,7 +504,7 @@ "\n", "#### More details about the configuration parameters\n", "`request_mode` is \"asynchronous\" by default, which allows concurrent requests to be queued and processed without the need for a continuous connection between you and the API endpoint.\n", - "In contrast, using a \"synchronous\" `request_mode` means that the request relies on a direct, continous connection between you and the API endpoint.\n", + "In contrast, using a \"synchronous\" `request_mode` means that the request relies on a direct, continuous connection between you and the API endpoint.\n", "Outputs are directly downloaded, or \"streamed\", to your working directory.\n", "For this tutorial, we will set the request mode to asynchronous.\n", "\n", diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index c20cfbc95..9cd61ac01 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -15,7 +15,7 @@ "\n", "### Motivation\n", "Most often, when you open a data file, you must specify the underlying data structure and how you'd like the information to be read in.\n", - "A simple example of this, for instance when opening a csv or similarly delimited file, is letting the software know if the data contains a header row, what the data type is (string, double, float, boolean, etc.) for each column, what the delimeter is, and which columns or rows you'd like to be loaded.\n", + "A simple example of this, for instance when opening a csv or similarly delimited file, is letting the software know if the data contains a header row, what the data type is (string, double, float, boolean, etc.) for each column, what the delimiter is, and which columns or rows you'd like to be loaded.\n", "Many ICESat-2 data readers are quite manual in nature, requiring that you accurately type out a list of string paths to the various data variables.\n", "\n", "icepyx simplifies this process by relying on its awareness of ICESat-2 specific data file variable storage structure.\n", diff --git a/doc/source/example_notebooks/IS2_data_variables.ipynb b/doc/source/example_notebooks/IS2_data_variables.ipynb index 90fa8500c..2263ea768 100644 --- a/doc/source/example_notebooks/IS2_data_variables.ipynb +++ b/doc/source/example_notebooks/IS2_data_variables.ipynb @@ -278,7 +278,7 @@ "user_expressions": [] }, "source": [ - "Now that you know how to create or access Variables the remainder of this notebook showcases the functions availble for building and modifying variables lists. Remember, the example shown below uses a Query object, but the same methods are available if you are using a Read object or a Variables object." + "Now that you know how to create or access Variables the remainder of this notebook showcases the functions available for building and modifying variables lists. Remember, the example shown below uses a Query object, but the same methods are available if you are using a Read object or a Variables object." ] }, { @@ -360,7 +360,7 @@ "### ICESat-2 data variables\n", "\n", "ICESat-2 data is natively stored in a nested file format called hdf5.\n", - "Much like a directory-file system on a computer, each variable (file) has a unique path through the heirarchy (directories) within the file.\n", + "Much like a directory-file system on a computer, each variable (file) has a unique path through the hierarchy (directories) within the file.\n", "Thus, some variables (e.g. `'latitude'`, `'longitude'`) have multiple paths (one for each of the six beams in most products).\n", "\n", "#### Determine what variables are available\n", @@ -887,7 +887,7 @@ "source": [ "#### Example 2.8: add all possible values for variables+paths\n", "Append all `longitude` paths and all variables/paths with keyword `high_rate`.\n", - "Simlarly to what is shown in Example 4, if you submit only one `append` call as `region_a.order_vars.append(var_list=['longitude'], keyword_list=['high_rate'])` rather than the two `append` calls shown below, you will only add the variable `longitude` and only paths containing `high_rate`, not ALL paths for `longitude` and ANY variables with `high_rate` in their path." + "Similarly to what is shown in Example 4, if you submit only one `append` call as `region_a.order_vars.append(var_list=['longitude'], keyword_list=['high_rate'])` rather than the two `append` calls shown below, you will only add the variable `longitude` and only paths containing `high_rate`, not ALL paths for `longitude` and ANY variables with `high_rate` in their path." ] }, { diff --git a/doc/source/example_notebooks/IS2_data_visualization.ipynb b/doc/source/example_notebooks/IS2_data_visualization.ipynb index 0f2819862..1654a83d2 100644 --- a/doc/source/example_notebooks/IS2_data_visualization.ipynb +++ b/doc/source/example_notebooks/IS2_data_visualization.ipynb @@ -7,7 +7,14 @@ "source": [ "# Visualizing ICESat-2 Elevations\n", "\n", - "This notebook ({nb-download}`download `) demonstrates interactive ICESat-2 elevation visualization by requesting data from [OpenAltimetry](https://www.openaltimetry.org/) based on metadata provided by [icepyx](https://icepyx.readthedocs.io/en/latest/). We will show how to plot spatial extent and elevation interactively. " + "This notebook ({nb-download}`download `) demonstrates interactive ICESat-2 elevation visualization by requesting data from [OpenAltimetry](https://www.openaltimetry.org/) based on metadata provided by [icepyx](https://icepyx.readthedocs.io/en/latest/). We will show how to plot spatial extent and elevation interactively.\n", + "\n", + "> ⚠️ **Some of this notebook is currently non-functional**\n", + ">\n", + "> Visualizations requiring the\n", + "> [OpenAltimetry API](https://openaltimetry.earthdatacloud.nasa.gov/data/openapi/swagger-ui/index.html)\n", + "> are currently unavailable (since ~October 2023).\n", + "> The API changed and we haven't yet updated this notebook correspondingly." ] }, { @@ -33,7 +40,7 @@ "id": "57f2cfd8", "metadata": {}, "source": [ - "Create an ICESat-2 query object\n", + "## Create an ICESat-2 query object\n", "\n", "Set the desired parameters for your data visualization.\n", "\n", @@ -138,7 +145,7 @@ "\n", "**Note: this function currently only supports products `ATL06, ATL07, ATL08, ATL10, ATL12, ATL13`**\n", "\n", - "Now that we have produced an interactive map showing the spatial extent of ICESat-2 data to be requested from NSIDC using icepyx, what if we want to have a quick check on the ICESat-2 elevations we plan to download from NSIDC? [OpenAltimetry API](https://openaltimetry.org/data/swagger-ui/#/) provides a nice way to achieve this. By sending metadata (product, date, bounding box, trackId) of each ICESat-2 file to the API, it can return elevation data almost instantaneously. The major drawback is requests are limited to 5x5 degree spatial bounding box selection for most of the ICESat-2 L3A products [ATL06, ATL07, ATL08, ATL10, ATL12, ATL13](https://icesat-2.gsfc.nasa.gov/science/data-products). To solve this issue, if you input spatial extent exceeds the 5 degree maximum in either horizontal dimension, your input spatial extent will be splited into 5x5 degree lat/lon grids first, use icepyx to query the metadata of ICESat-2 files located in each grid, and send each request to OpenAltimetry. Data sampling rates are 1/50 for ATL06 and 1/20 for other products.\n", + "Now that we have produced an interactive map showing the spatial extent of ICESat-2 data to be requested from NSIDC using icepyx, what if we want to have a quick check on the ICESat-2 elevations we plan to download from NSIDC? [OpenAltimetry API](https://openaltimetry.org/data/swagger-ui/#/) provides a nice way to achieve this. By sending metadata (product, date, bounding box, trackId) of each ICESat-2 file to the API, it can return elevation data almost instantaneously. The major drawback is requests are limited to 5x5 degree spatial bounding box selection for most of the ICESat-2 L3A products [ATL06, ATL07, ATL08, ATL10, ATL12, ATL13](https://icesat-2.gsfc.nasa.gov/science/data-products). To solve this issue, if you input spatial extent exceeds the 5 degree maximum in either horizontal dimension, your input spatial extent will be split into 5x5 degree lat/lon grids first, use icepyx to query the metadata of ICESat-2 files located in each grid, and send each request to OpenAltimetry. Data sampling rates are 1/50 for ATL06 and 1/20 for other products.\n", "\n", "There are multiple ways to access icepyx's visualization module. This option assumes you are visualizing the data as part of a workflow that will result in a data download. Alternative options for accessing the OpenAltimetry-based visualization module directly are provided at the end of this example." ] @@ -148,6 +155,7 @@ "execution_count": null, "id": "93a712af-ab1f-4d79-834d-c2735a5677a8", "metadata": { + "scrolled": true, "tags": [] }, "outputs": [], @@ -222,16 +230,16 @@ "### Alternative Access Options to Visualize ICESat-2 elevation using OpenAltimetry API\n", "\n", "You can also view elevation data by importing the visualization module directly and initializing it with your query object or a list of parameters:\n", - " ```\n", + " ```python\n", " from icepyx.core.visualization import Visualize\n", " ```\n", " - passing your query object directly to the visualization module\n", - " ```\n", + " ```python\n", " region2 = ipx.Query(short_name, spatial_extent, date_range)\n", " vis = Visualize(region2)\n", " ```\n", " - creating a visualization object directly without first creating a query object\n", - " ```\n", + " ```python\n", " vis = Visualize(product=short_name, spatial_extent=spatial_extent, date_range=date_range)\n", " ```" ] @@ -264,7 +272,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.12.4" } }, "nbformat": 4, diff --git a/doc/source/tracking/pypistats/downloads.svg b/doc/source/tracking/pypistats/downloads.svg index 484dc6d7f..410c2a02e 100644 --- a/doc/source/tracking/pypistats/downloads.svg +++ b/doc/source/tracking/pypistats/downloads.svg @@ -6,11 +6,11 @@ - 2024-05-01T20:57:00.508010 + 2024-09-01T20:56:47.103398 image/svg+xml - Matplotlib v3.8.4, https://matplotlib.org/ + Matplotlib v3.9.2, https://matplotlib.org/ @@ -41,12 +41,12 @@ z - - + @@ -205,12 +205,12 @@ z - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - + - - - + + + - + - + - + - - + + - + - - - + + + - + - + - + - - + + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -424,11 +422,33 @@ z - + + + + + + + + + + + + + + + + + + + + + + + - + @@ -547,1260 +567,1383 @@ z - + - - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + - - + + - + - + @@ -2165,7 +2308,7 @@ z - + diff --git a/doc/source/tracking/pypistats/downloads_data.csv b/doc/source/tracking/pypistats/downloads_data.csv index b2ea37f93..b94d03847 100644 --- a/doc/source/tracking/pypistats/downloads_data.csv +++ b/doc/source/tracking/pypistats/downloads_data.csv @@ -1386,6 +1386,129 @@ with_mirrors,2024-04-27,14 with_mirrors,2024-04-28,33 with_mirrors,2024-04-29,77 with_mirrors,2024-04-30,54 +with_mirrors,2024-05-01,8 +with_mirrors,2024-05-02,52 +with_mirrors,2024-05-03,62 +with_mirrors,2024-05-04,44 +with_mirrors,2024-05-05,18 +with_mirrors,2024-05-06,45 +with_mirrors,2024-05-07,73 +with_mirrors,2024-05-08,82 +with_mirrors,2024-05-09,64 +with_mirrors,2024-05-10,63 +with_mirrors,2024-05-11,65 +with_mirrors,2024-05-12,4 +with_mirrors,2024-05-13,49 +with_mirrors,2024-05-14,10 +with_mirrors,2024-05-15,24 +with_mirrors,2024-05-16,134 +with_mirrors,2024-05-17,11 +with_mirrors,2024-05-18,27 +with_mirrors,2024-05-19,15 +with_mirrors,2024-05-20,86 +with_mirrors,2024-05-21,42 +with_mirrors,2024-05-22,78 +with_mirrors,2024-05-23,23 +with_mirrors,2024-05-24,44 +with_mirrors,2024-05-25,14 +with_mirrors,2024-05-26,16 +with_mirrors,2024-05-27,51 +with_mirrors,2024-05-28,12 +with_mirrors,2024-05-29,31 +with_mirrors,2024-05-30,51 +with_mirrors,2024-05-31,48 +with_mirrors,2024-06-01,45 +with_mirrors,2024-06-02,7 +with_mirrors,2024-06-03,54 +with_mirrors,2024-06-04,11 +with_mirrors,2024-06-05,32 +with_mirrors,2024-06-06,263 +with_mirrors,2024-06-07,82 +with_mirrors,2024-06-08,8 +with_mirrors,2024-06-09,59 +with_mirrors,2024-06-10,24 +with_mirrors,2024-06-11,48 +with_mirrors,2024-06-12,21 +with_mirrors,2024-06-13,16 +with_mirrors,2024-06-14,114 +with_mirrors,2024-06-15,8 +with_mirrors,2024-06-16,4 +with_mirrors,2024-06-17,40 +with_mirrors,2024-06-18,10 +with_mirrors,2024-06-19,2 +with_mirrors,2024-06-20,1 +with_mirrors,2024-06-21,17 +with_mirrors,2024-06-22,71 +with_mirrors,2024-06-23,23 +with_mirrors,2024-06-24,84 +with_mirrors,2024-06-25,72 +with_mirrors,2024-06-26,82 +with_mirrors,2024-06-27,63 +with_mirrors,2024-06-28,19 +with_mirrors,2024-06-29,31 +with_mirrors,2024-06-30,20 +with_mirrors,2024-07-01,31 +with_mirrors,2024-07-02,92 +with_mirrors,2024-07-03,73 +with_mirrors,2024-07-04,119 +with_mirrors,2024-07-05,74 +with_mirrors,2024-07-06,54 +with_mirrors,2024-07-07,55 +with_mirrors,2024-07-08,81 +with_mirrors,2024-07-09,50 +with_mirrors,2024-07-10,107 +with_mirrors,2024-07-11,77 +with_mirrors,2024-07-12,75 +with_mirrors,2024-07-13,84 +with_mirrors,2024-07-14,17 +with_mirrors,2024-07-15,39 +with_mirrors,2024-07-16,47 +with_mirrors,2024-07-17,63 +with_mirrors,2024-07-18,66 +with_mirrors,2024-07-19,87 +with_mirrors,2024-07-20,52 +with_mirrors,2024-07-21,17 +with_mirrors,2024-07-22,58 +with_mirrors,2024-07-23,94 +with_mirrors,2024-07-24,82 +with_mirrors,2024-07-25,91 +with_mirrors,2024-07-26,78 +with_mirrors,2024-07-27,76 +with_mirrors,2024-07-28,30 +with_mirrors,2024-07-29,49 +with_mirrors,2024-07-30,65 +with_mirrors,2024-07-31,54 +with_mirrors,2024-08-01,128 +with_mirrors,2024-08-02,117 +with_mirrors,2024-08-03,118 +with_mirrors,2024-08-04,48 +with_mirrors,2024-08-05,100 +with_mirrors,2024-08-06,78 +with_mirrors,2024-08-07,96 +with_mirrors,2024-08-08,82 +with_mirrors,2024-08-09,91 +with_mirrors,2024-08-10,70 +with_mirrors,2024-08-11,12 +with_mirrors,2024-08-12,56 +with_mirrors,2024-08-13,67 +with_mirrors,2024-08-14,212 +with_mirrors,2024-08-15,177 +with_mirrors,2024-08-16,70 +with_mirrors,2024-08-17,95 +with_mirrors,2024-08-18,53 +with_mirrors,2024-08-19,96 +with_mirrors,2024-08-20,136 +with_mirrors,2024-08-21,77 +with_mirrors,2024-08-22,97 +with_mirrors,2024-08-23,89 +with_mirrors,2024-08-24,59 +with_mirrors,2024-08-25,56 +with_mirrors,2024-08-26,26 +with_mirrors,2024-08-27,18 +with_mirrors,2024-08-28,24 +with_mirrors,2024-08-29,81 +with_mirrors,2024-08-30,11 +with_mirrors,2024-08-31,67 without_mirrors,2020-06-18,22 without_mirrors,2020-06-19,14 without_mirrors,2020-06-21,4 @@ -2669,3 +2792,125 @@ without_mirrors,2024-04-27,14 without_mirrors,2024-04-28,33 without_mirrors,2024-04-29,40 without_mirrors,2024-04-30,50 +without_mirrors,2024-05-01,7 +without_mirrors,2024-05-02,14 +without_mirrors,2024-05-03,25 +without_mirrors,2024-05-04,7 +without_mirrors,2024-05-05,16 +without_mirrors,2024-05-06,6 +without_mirrors,2024-05-07,73 +without_mirrors,2024-05-08,43 +without_mirrors,2024-05-09,43 +without_mirrors,2024-05-10,25 +without_mirrors,2024-05-11,1 +without_mirrors,2024-05-12,2 +without_mirrors,2024-05-13,37 +without_mirrors,2024-05-14,9 +without_mirrors,2024-05-15,23 +without_mirrors,2024-05-16,16 +without_mirrors,2024-05-17,11 +without_mirrors,2024-05-18,10 +without_mirrors,2024-05-19,9 +without_mirrors,2024-05-20,47 +without_mirrors,2024-05-21,23 +without_mirrors,2024-05-22,41 +without_mirrors,2024-05-23,23 +without_mirrors,2024-05-24,44 +without_mirrors,2024-05-25,13 +without_mirrors,2024-05-26,16 +without_mirrors,2024-05-27,51 +without_mirrors,2024-05-28,12 +without_mirrors,2024-05-29,31 +without_mirrors,2024-05-30,41 +without_mirrors,2024-05-31,48 +without_mirrors,2024-06-01,8 +without_mirrors,2024-06-02,7 +without_mirrors,2024-06-03,11 +without_mirrors,2024-06-04,7 +without_mirrors,2024-06-05,32 +without_mirrors,2024-06-06,153 +without_mirrors,2024-06-07,52 +without_mirrors,2024-06-08,4 +without_mirrors,2024-06-09,7 +without_mirrors,2024-06-10,20 +without_mirrors,2024-06-11,42 +without_mirrors,2024-06-12,13 +without_mirrors,2024-06-13,15 +without_mirrors,2024-06-14,43 +without_mirrors,2024-06-15,4 +without_mirrors,2024-06-17,39 +without_mirrors,2024-06-18,10 +without_mirrors,2024-06-19,2 +without_mirrors,2024-06-20,1 +without_mirrors,2024-06-21,17 +without_mirrors,2024-06-22,32 +without_mirrors,2024-06-23,23 +without_mirrors,2024-06-24,41 +without_mirrors,2024-06-25,31 +without_mirrors,2024-06-26,69 +without_mirrors,2024-06-27,57 +without_mirrors,2024-06-28,14 +without_mirrors,2024-06-29,11 +without_mirrors,2024-06-30,3 +without_mirrors,2024-07-01,31 +without_mirrors,2024-07-02,47 +without_mirrors,2024-07-03,61 +without_mirrors,2024-07-04,36 +without_mirrors,2024-07-05,71 +without_mirrors,2024-07-06,15 +without_mirrors,2024-07-07,14 +without_mirrors,2024-07-08,78 +without_mirrors,2024-07-09,50 +without_mirrors,2024-07-10,48 +without_mirrors,2024-07-11,34 +without_mirrors,2024-07-12,33 +without_mirrors,2024-07-13,4 +without_mirrors,2024-07-14,8 +without_mirrors,2024-07-15,36 +without_mirrors,2024-07-16,45 +without_mirrors,2024-07-17,61 +without_mirrors,2024-07-18,42 +without_mirrors,2024-07-19,47 +without_mirrors,2024-07-20,7 +without_mirrors,2024-07-21,5 +without_mirrors,2024-07-22,53 +without_mirrors,2024-07-23,80 +without_mirrors,2024-07-24,43 +without_mirrors,2024-07-25,50 +without_mirrors,2024-07-26,48 +without_mirrors,2024-07-27,32 +without_mirrors,2024-07-28,28 +without_mirrors,2024-07-29,47 +without_mirrors,2024-07-30,62 +without_mirrors,2024-07-31,50 +without_mirrors,2024-08-01,126 +without_mirrors,2024-08-02,70 +without_mirrors,2024-08-03,79 +without_mirrors,2024-08-04,46 +without_mirrors,2024-08-05,100 +without_mirrors,2024-08-06,78 +without_mirrors,2024-08-07,96 +without_mirrors,2024-08-08,63 +without_mirrors,2024-08-09,83 +without_mirrors,2024-08-10,70 +without_mirrors,2024-08-11,10 +without_mirrors,2024-08-12,55 +without_mirrors,2024-08-13,28 +without_mirrors,2024-08-14,113 +without_mirrors,2024-08-15,82 +without_mirrors,2024-08-16,60 +without_mirrors,2024-08-17,49 +without_mirrors,2024-08-18,8 +without_mirrors,2024-08-19,88 +without_mirrors,2024-08-20,57 +without_mirrors,2024-08-21,75 +without_mirrors,2024-08-22,93 +without_mirrors,2024-08-23,47 +without_mirrors,2024-08-24,14 +without_mirrors,2024-08-25,14 +without_mirrors,2024-08-26,26 +without_mirrors,2024-08-27,18 +without_mirrors,2024-08-28,21 +without_mirrors,2024-08-29,81 +without_mirrors,2024-08-30,11 +without_mirrors,2024-08-31,8 diff --git a/doc/source/tracking/pypistats/get_pypi_stats.py b/doc/source/tracking/pypistats/get_pypi_stats.py index d137b99c3..78a197e8f 100644 --- a/doc/source/tracking/pypistats/get_pypi_stats.py +++ b/doc/source/tracking/pypistats/get_pypi_stats.py @@ -1,6 +1,7 @@ import os -import pypistats + import pandas as pd +import pypistats cwd = os.getcwd() diff --git a/doc/source/tracking/pypistats/sys_downloads_data.csv b/doc/source/tracking/pypistats/sys_downloads_data.csv index cb8ff00c5..86c89887a 100644 --- a/doc/source/tracking/pypistats/sys_downloads_data.csv +++ b/doc/source/tracking/pypistats/sys_downloads_data.csv @@ -211,6 +211,33 @@ Darwin,2024-04-10,2 Darwin,2024-04-12,2 Darwin,2024-04-25,2 Darwin,2024-04-29,1 +Darwin,2024-05-03,2 +Darwin,2024-05-21,2 +Darwin,2024-05-22,2 +Darwin,2024-05-27,2 +Darwin,2024-05-29,2 +Darwin,2024-05-31,2 +Darwin,2024-06-01,2 +Darwin,2024-06-03,2 +Darwin,2024-06-04,1 +Darwin,2024-06-05,4 +Darwin,2024-06-06,2 +Darwin,2024-06-07,4 +Darwin,2024-06-10,2 +Darwin,2024-06-11,2 +Darwin,2024-06-13,3 +Darwin,2024-06-18,1 +Darwin,2024-07-06,2 +Darwin,2024-07-14,2 +Darwin,2024-07-16,3 +Darwin,2024-07-29,1 +Darwin,2024-07-31,2 +Darwin,2024-08-08,1 +Darwin,2024-08-10,5 +Darwin,2024-08-12,1 +Darwin,2024-08-14,2 +Darwin,2024-08-20,2 +Darwin,2024-08-21,2 Linux,2020-06-18,9 Linux,2020-06-19,2 Linux,2020-06-22,2 @@ -1128,6 +1155,122 @@ Linux,2024-04-27,12 Linux,2024-04-28,18 Linux,2024-04-29,18 Linux,2024-04-30,47 +Linux,2024-05-01,2 +Linux,2024-05-02,8 +Linux,2024-05-03,18 +Linux,2024-05-04,2 +Linux,2024-05-05,1 +Linux,2024-05-07,69 +Linux,2024-05-08,37 +Linux,2024-05-09,38 +Linux,2024-05-10,18 +Linux,2024-05-12,2 +Linux,2024-05-13,9 +Linux,2024-05-14,8 +Linux,2024-05-15,13 +Linux,2024-05-16,14 +Linux,2024-05-17,10 +Linux,2024-05-18,4 +Linux,2024-05-20,38 +Linux,2024-05-21,17 +Linux,2024-05-22,33 +Linux,2024-05-23,13 +Linux,2024-05-24,19 +Linux,2024-05-25,9 +Linux,2024-05-26,12 +Linux,2024-05-27,31 +Linux,2024-05-28,6 +Linux,2024-05-29,28 +Linux,2024-05-30,38 +Linux,2024-05-31,41 +Linux,2024-06-01,5 +Linux,2024-06-02,5 +Linux,2024-06-03,5 +Linux,2024-06-04,4 +Linux,2024-06-05,8 +Linux,2024-06-06,25 +Linux,2024-06-07,10 +Linux,2024-06-09,5 +Linux,2024-06-10,4 +Linux,2024-06-11,35 +Linux,2024-06-12,11 +Linux,2024-06-14,20 +Linux,2024-06-15,2 +Linux,2024-06-17,35 +Linux,2024-06-18,6 +Linux,2024-06-19,1 +Linux,2024-06-20,1 +Linux,2024-06-21,17 +Linux,2024-06-22,22 +Linux,2024-06-23,18 +Linux,2024-06-24,29 +Linux,2024-06-25,25 +Linux,2024-06-26,67 +Linux,2024-06-27,41 +Linux,2024-06-28,10 +Linux,2024-06-29,10 +Linux,2024-06-30,1 +Linux,2024-07-01,26 +Linux,2024-07-02,43 +Linux,2024-07-03,48 +Linux,2024-07-04,30 +Linux,2024-07-05,26 +Linux,2024-07-06,11 +Linux,2024-07-07,2 +Linux,2024-07-08,74 +Linux,2024-07-09,47 +Linux,2024-07-10,38 +Linux,2024-07-11,26 +Linux,2024-07-12,30 +Linux,2024-07-13,4 +Linux,2024-07-14,5 +Linux,2024-07-15,32 +Linux,2024-07-16,37 +Linux,2024-07-17,58 +Linux,2024-07-18,31 +Linux,2024-07-19,44 +Linux,2024-07-20,5 +Linux,2024-07-22,52 +Linux,2024-07-23,77 +Linux,2024-07-24,40 +Linux,2024-07-25,43 +Linux,2024-07-26,48 +Linux,2024-07-27,22 +Linux,2024-07-28,27 +Linux,2024-07-29,38 +Linux,2024-07-30,50 +Linux,2024-07-31,48 +Linux,2024-08-01,98 +Linux,2024-08-02,70 +Linux,2024-08-03,76 +Linux,2024-08-04,46 +Linux,2024-08-05,95 +Linux,2024-08-06,75 +Linux,2024-08-07,88 +Linux,2024-08-08,57 +Linux,2024-08-09,69 +Linux,2024-08-10,62 +Linux,2024-08-11,8 +Linux,2024-08-12,50 +Linux,2024-08-13,25 +Linux,2024-08-14,68 +Linux,2024-08-15,63 +Linux,2024-08-16,55 +Linux,2024-08-17,8 +Linux,2024-08-18,6 +Linux,2024-08-19,43 +Linux,2024-08-20,46 +Linux,2024-08-21,58 +Linux,2024-08-22,40 +Linux,2024-08-23,44 +Linux,2024-08-24,14 +Linux,2024-08-25,12 +Linux,2024-08-26,20 +Linux,2024-08-27,10 +Linux,2024-08-28,16 +Linux,2024-08-29,38 +Linux,2024-08-30,8 +Linux,2024-08-31,6 Windows,2020-06-21,1 Windows,2020-06-25,1 Windows,2020-06-30,1 @@ -1894,6 +2037,97 @@ Windows,2024-04-27,1 Windows,2024-04-28,15 Windows,2024-04-29,4 Windows,2024-04-30,2 +Windows,2024-05-01,4 +Windows,2024-05-02,1 +Windows,2024-05-03,5 +Windows,2024-05-04,2 +Windows,2024-05-05,2 +Windows,2024-05-06,4 +Windows,2024-05-07,2 +Windows,2024-05-08,4 +Windows,2024-05-09,5 +Windows,2024-05-10,7 +Windows,2024-05-13,10 +Windows,2024-05-15,9 +Windows,2024-05-16,1 +Windows,2024-05-19,7 +Windows,2024-05-20,6 +Windows,2024-05-21,2 +Windows,2024-05-22,6 +Windows,2024-05-23,9 +Windows,2024-05-24,3 +Windows,2024-05-26,2 +Windows,2024-05-27,16 +Windows,2024-05-28,4 +Windows,2024-05-29,1 +Windows,2024-05-30,2 +Windows,2024-05-31,2 +Windows,2024-06-02,2 +Windows,2024-06-03,3 +Windows,2024-06-04,2 +Windows,2024-06-05,20 +Windows,2024-06-06,6 +Windows,2024-06-07,8 +Windows,2024-06-08,2 +Windows,2024-06-09,2 +Windows,2024-06-10,8 +Windows,2024-06-11,4 +Windows,2024-06-13,8 +Windows,2024-06-14,4 +Windows,2024-06-15,2 +Windows,2024-06-17,1 +Windows,2024-06-18,3 +Windows,2024-06-19,1 +Windows,2024-06-22,10 +Windows,2024-06-23,3 +Windows,2024-06-24,9 +Windows,2024-06-25,4 +Windows,2024-06-27,14 +Windows,2024-06-28,4 +Windows,2024-07-01,5 +Windows,2024-07-02,2 +Windows,2024-07-03,2 +Windows,2024-07-04,4 +Windows,2024-07-05,6 +Windows,2024-07-06,2 +Windows,2024-07-07,7 +Windows,2024-07-08,4 +Windows,2024-07-09,3 +Windows,2024-07-10,9 +Windows,2024-07-11,5 +Windows,2024-07-15,4 +Windows,2024-07-16,4 +Windows,2024-07-17,2 +Windows,2024-07-18,8 +Windows,2024-07-19,3 +Windows,2024-07-20,1 +Windows,2024-07-24,2 +Windows,2024-07-25,7 +Windows,2024-07-27,10 +Windows,2024-07-29,5 +Windows,2024-07-30,4 +Windows,2024-08-01,27 +Windows,2024-08-05,4 +Windows,2024-08-06,2 +Windows,2024-08-07,7 +Windows,2024-08-08,3 +Windows,2024-08-09,9 +Windows,2024-08-10,2 +Windows,2024-08-11,2 +Windows,2024-08-12,4 +Windows,2024-08-13,2 +Windows,2024-08-19,4 +Windows,2024-08-20,6 +Windows,2024-08-21,15 +Windows,2024-08-22,5 +Windows,2024-08-23,2 +Windows,2024-08-25,2 +Windows,2024-08-26,6 +Windows,2024-08-27,7 +Windows,2024-08-28,2 +Windows,2024-08-29,2 +Windows,2024-08-30,2 +Windows,2024-08-31,2 null,2020-06-18,12 null,2020-06-19,12 null,2020-06-21,2 @@ -2739,3 +2973,88 @@ null,2024-04-26,2 null,2024-04-27,1 null,2024-04-29,17 null,2024-04-30,1 +null,2024-05-01,1 +null,2024-05-02,5 +null,2024-05-04,3 +null,2024-05-05,13 +null,2024-05-06,2 +null,2024-05-07,2 +null,2024-05-08,2 +null,2024-05-11,1 +null,2024-05-13,18 +null,2024-05-14,1 +null,2024-05-15,1 +null,2024-05-16,1 +null,2024-05-17,1 +null,2024-05-18,6 +null,2024-05-19,2 +null,2024-05-20,3 +null,2024-05-21,2 +null,2024-05-23,1 +null,2024-05-24,22 +null,2024-05-25,4 +null,2024-05-26,2 +null,2024-05-27,2 +null,2024-05-28,2 +null,2024-05-30,1 +null,2024-05-31,3 +null,2024-06-01,1 +null,2024-06-03,1 +null,2024-06-06,120 +null,2024-06-07,30 +null,2024-06-08,2 +null,2024-06-10,6 +null,2024-06-11,1 +null,2024-06-12,2 +null,2024-06-13,4 +null,2024-06-14,19 +null,2024-06-17,3 +null,2024-06-23,2 +null,2024-06-24,3 +null,2024-06-25,2 +null,2024-06-26,2 +null,2024-06-27,2 +null,2024-06-29,1 +null,2024-06-30,2 +null,2024-07-02,2 +null,2024-07-03,11 +null,2024-07-04,2 +null,2024-07-05,39 +null,2024-07-07,5 +null,2024-07-10,1 +null,2024-07-11,3 +null,2024-07-12,3 +null,2024-07-14,1 +null,2024-07-16,1 +null,2024-07-17,1 +null,2024-07-18,3 +null,2024-07-20,1 +null,2024-07-21,5 +null,2024-07-22,1 +null,2024-07-23,3 +null,2024-07-24,1 +null,2024-07-28,1 +null,2024-07-29,3 +null,2024-07-30,8 +null,2024-08-01,1 +null,2024-08-03,3 +null,2024-08-05,1 +null,2024-08-06,1 +null,2024-08-07,1 +null,2024-08-08,2 +null,2024-08-09,5 +null,2024-08-10,1 +null,2024-08-13,1 +null,2024-08-14,43 +null,2024-08-15,19 +null,2024-08-16,5 +null,2024-08-17,41 +null,2024-08-18,2 +null,2024-08-19,41 +null,2024-08-20,3 +null,2024-08-22,48 +null,2024-08-23,1 +null,2024-08-27,1 +null,2024-08-28,3 +null,2024-08-29,41 +null,2024-08-30,1 diff --git a/doc/source/tracking/traffic/clones.csv b/doc/source/tracking/traffic/clones.csv index 67575c77f..4b2fd01c4 100644 --- a/doc/source/tracking/traffic/clones.csv +++ b/doc/source/tracking/traffic/clones.csv @@ -1002,3 +1002,94 @@ _date,total_clones,unique_clones 2024-05-10,34,16 2024-05-11,2,2 2024-05-12,2,2 +2024-05-13,5,4 +2024-05-15,1,1 +2024-05-16,45,23 +2024-05-17,3,3 +2024-05-18,1,1 +2024-05-20,7,4 +2024-05-22,1,1 +2024-05-23,2,2 +2024-05-24,1,1 +2024-05-25,1,1 +2024-05-27,4,4 +2024-05-28,1,1 +2024-05-29,16,10 +2024-05-31,1,1 +2024-06-01,4,3 +2024-06-02,1,1 +2024-06-03,4,4 +2024-06-04,28,17 +2024-06-05,11,9 +2024-06-06,18,14 +2024-06-07,6,4 +2024-06-08,3,3 +2024-06-10,6,5 +2024-06-11,2,2 +2024-06-13,2,2 +2024-06-14,1,1 +2024-06-15,1,1 +2024-06-17,6,6 +2024-06-18,4,4 +2024-06-19,2,2 +2024-06-20,2,2 +2024-06-21,5,4 +2024-06-22,2,2 +2024-06-24,6,4 +2024-06-27,1,1 +2024-06-28,1,1 +2024-06-30,1,1 +2024-07-01,4,3 +2024-07-02,1,1 +2024-07-05,1,1 +2024-07-06,1,1 +2024-07-08,3,3 +2024-07-11,5,3 +2024-07-12,1,1 +2024-07-13,1,1 +2024-07-15,1,1 +2024-07-18,10,4 +2024-07-20,1,1 +2024-07-22,3,3 +2024-07-24,11,5 +2024-07-25,1,1 +2024-07-27,1,1 +2024-07-29,1,1 +2024-08-01,2,2 +2024-08-03,2,2 +2024-08-04,1,1 +2024-08-05,4,3 +2024-08-06,11,3 +2024-08-07,22,8 +2024-08-08,27,9 +2024-08-09,2,2 +2024-08-10,5,2 +2024-08-11,2,2 +2024-08-12,32,6 +2024-08-13,45,6 +2024-08-14,38,8 +2024-08-15,20,7 +2024-08-16,19,5 +2024-08-17,3,2 +2024-08-18,11,3 +2024-08-19,16,6 +2024-08-20,8,4 +2024-08-21,20,4 +2024-08-22,35,9 +2024-08-23,39,11 +2024-08-24,2,2 +2024-08-25,3,3 +2024-08-26,28,6 +2024-08-27,100,13 +2024-08-28,11,3 +2024-08-29,39,6 +2024-08-30,27,5 +2024-08-31,2,2 +2024-09-01,5,2 +2024-09-02,10,4 +2024-09-03,7,1 +2024-09-04,38,4 +2024-09-05,57,6 +2024-09-06,9,4 +2024-09-07,1,1 +2024-09-09,5,2 diff --git a/doc/source/tracking/traffic/plots.svg b/doc/source/tracking/traffic/plots.svg index b682d6b72..6ef19a3a4 100644 --- a/doc/source/tracking/traffic/plots.svg +++ b/doc/source/tracking/traffic/plots.svg @@ -6,11 +6,11 @@ - 2024-05-13T00:40:56.977866 + 2024-09-09T18:35:09.251749 image/svg+xml - Matplotlib v3.8.4, https://matplotlib.org/ + Matplotlib v3.9.2, https://matplotlib.org/ @@ -41,12 +41,12 @@ z - - + @@ -136,12 +136,12 @@ z - + - + - + - + - + - + - + - + - + - + - - + @@ -546,7 +546,7 @@ L -3.5 0 - + @@ -561,7 +561,7 @@ L -3.5 0 - + @@ -576,7 +576,7 @@ L -3.5 0 - + @@ -591,1881 +591,2046 @@ L -3.5 0 +L 115.827747 129.61084 +L 116.291857 130.778182 +L 116.755968 130.778182 +L 117.220078 130.194511 +L 117.684189 130.194511 +L 118.148299 126.108813 +L 118.61241 126.108813 +L 119.07652 130.778182 +L 119.54063 130.778182 +L 120.004741 127.859826 +L 120.468851 128.735333 +L 120.932962 130.778182 +L 121.397072 129.319004 +L 121.861183 129.902675 +L 122.325293 129.902675 +L 122.789404 130.778182 +L 123.717625 129.61084 +L 124.181735 130.486346 +L 124.645845 130.778182 +L 125.109956 130.486346 +L 125.574066 130.486346 +L 126.038177 130.194511 +L 126.502287 130.486346 +L 126.966398 130.486346 +L 127.430508 129.902675 +L 127.894619 130.486346 +L 128.358729 130.486346 +L 128.82284 126.98432 +L 129.28695 129.319004 +L 129.75106 130.486346 +L 130.215171 123.774129 +L 130.679281 130.778182 +L 134.392165 130.778182 +L 134.856275 130.486346 +L 135.320386 130.778182 +L 138.569159 130.778182 +L 139.03327 129.902675 +L 139.49738 130.194511 +L 139.96149 130.778182 +L 140.425601 130.194511 +L 140.889711 129.319004 +L 141.353822 130.486346 +L 141.817932 130.486346 +L 142.282043 129.902675 +L 142.746153 126.108813 +L 143.210264 130.486346 +L 143.674374 130.778182 +L 144.138485 130.486346 +L 144.602595 129.027169 +L 145.066705 130.486346 +L 145.530816 130.194511 +L 145.994926 128.151662 +L 146.459037 129.902675 +L 146.923147 129.027169 +L 147.387258 130.486346 +L 147.851368 130.194511 +L 148.315479 130.486346 +L 148.779589 130.194511 +L 149.70781 130.194511 +L 150.17192 129.61084 +L 150.636031 130.778182 +L 151.100141 130.778182 +L 151.564252 129.61084 +L 152.028362 129.61084 +L 152.492473 128.151662 +L 152.956583 130.194511 +L 153.420694 129.319004 +L 153.884804 130.778182 +L 154.348915 128.443497 +L 154.813025 129.902675 +L 155.277135 130.194511 +L 155.741246 129.902675 +L 156.205356 128.735333 +L 156.669467 130.486346 +L 157.133577 129.61084 +L 157.597688 126.400649 +L 158.061798 128.735333 +L 158.525909 126.108813 +L 158.990019 110.349693 +L 159.45413 129.319004 +L 159.91824 130.778182 +L 160.38235 129.902675 +L 160.846461 127.276155 +L 161.310571 127.859826 +L 161.774682 129.319004 +L 162.238792 125.525142 +L 162.702903 129.902675 +L 163.167013 129.902675 +L 163.631124 130.486346 +L 164.095234 126.98432 +L 164.559345 127.859826 +L 165.023455 130.778182 +L 165.487565 130.194511 +L 165.951676 130.778182 +L 166.415786 129.61084 +L 166.879897 116.47824 +L 167.344007 124.941471 +L 167.808118 126.400649 +L 168.272228 129.319004 +L 168.736339 130.778182 +L 169.200449 128.735333 +L 169.66456 129.902675 +L 170.12867 126.692484 +L 170.592781 129.902675 +L 171.056891 127.276155 +L 171.521001 123.774129 +L 171.985112 126.98432 +L 172.449222 129.319004 +L 172.913333 123.482293 +L 173.377443 123.482293 +L 173.841554 124.065964 +L 174.305664 112.684378 +L 174.769775 119.688431 +L 175.233885 119.688431 +L 175.697996 125.525142 +L 176.162106 121.147609 +L 177.090327 130.194511 +L 177.554437 130.486346 +L 178.018548 124.065964 +L 178.482658 123.190457 +L 178.946769 123.774129 +L 179.410879 121.73128 +L 179.87499 119.10476 +L 180.3391 129.61084 +L 180.803211 130.486346 +L 181.267321 124.065964 +L 181.731431 124.649635 +L 182.195542 116.47824 +L 182.659652 123.774129 +L 183.123763 124.065964 +L 183.587873 130.486346 +L 184.051984 129.902675 +L 184.980205 117.353746 +L 185.444315 124.3578 +L 185.908426 122.606786 +L 186.372536 114.143555 +L 186.836646 124.3578 +L 187.300757 130.486346 +L 187.764867 123.190457 +L 188.228978 119.10476 +L 188.693088 117.645582 +L 189.157199 120.563937 +L 189.621309 121.73128 +L 190.08542 130.194511 +L 190.54953 123.482293 +L 191.013641 120.272102 +L 191.477751 123.774129 +L 191.941861 123.482293 +L 192.405972 122.898622 +L 192.870082 128.443497 +L 193.334193 123.774129 +L 193.798303 122.606786 +L 194.262414 123.774129 +L 194.726524 124.065964 +L 195.190635 124.065964 +L 195.654745 130.778182 +L 196.118856 130.778182 +L 196.582966 123.482293 +L 197.047076 122.023115 +L 197.511187 123.482293 +L 197.975297 117.645582 +L 198.439408 119.10476 +L 198.903518 130.778182 +L 199.367629 123.774129 +L 199.831739 122.898622 +L 200.29585 122.606786 +L 200.75996 122.023115 +L 201.224071 124.3578 +L 201.688181 130.486346 +L 202.152291 123.190457 +L 202.616402 121.439444 +L 203.080512 118.812924 +L 203.544623 118.521089 +L 204.008733 87.878356 +L 204.936954 130.778182 +L 205.401065 124.941471 +L 205.865175 124.3578 +L 206.793396 130.778182 +L 207.257506 130.486346 +L 207.721617 127.276155 +L 208.185727 128.151662 +L 208.649838 130.486346 +L 209.113948 129.902675 +L 209.578059 130.486346 +L 210.042169 130.778182 +L 210.50628 130.486346 +L 210.97039 130.778182 +L 211.434501 129.902675 +L 211.898611 130.194511 +L 212.362721 130.778182 +L 213.755053 130.778182 +L 214.219163 129.61084 +L 214.683274 130.486346 +L 215.147384 130.778182 +L 215.611495 130.486346 +L 216.075605 129.027169 +L 216.539716 130.778182 +L 217.003826 124.3578 +L 217.467936 130.194511 +L 217.932047 130.778182 +L 218.860268 130.194511 +L 219.324378 130.778182 +L 219.788489 130.486346 +L 220.252599 130.778182 +L 220.71671 129.902675 +L 221.18082 130.486346 +L 221.644931 130.194511 +L 222.109041 130.778182 +L 223.037262 130.778182 +L 223.965483 130.194511 +L 224.429593 129.027169 +L 224.893704 130.486346 +L 225.357814 130.486346 +L 225.821925 127.859826 +L 226.286035 126.692484 +L 226.750146 130.778182 +L 227.678366 130.778182 +L 228.606587 130.194511 +L 229.070698 130.486346 +L 229.534808 128.151662 +L 229.998919 122.606786 +L 230.463029 129.319004 +L 230.92714 121.147609 +L 231.39125 128.735333 +L 231.855361 130.486346 +L 232.319471 130.778182 +L 233.247692 130.778182 +L 233.711802 130.486346 +L 234.175913 130.778182 +L 234.640023 130.778182 +L 235.104134 129.61084 +L 235.568244 115.602733 +L 236.032355 124.3578 +L 236.496465 130.194511 +L 236.960576 126.98432 +L 237.424686 115.894569 +L 237.888796 114.727226 +L 238.352907 112.100706 +L 238.817017 118.229253 +L 239.281128 126.108813 +L 239.745238 126.98432 +L 240.209349 130.778182 +L 240.673459 128.443497 +L 241.13757 130.778182 +L 241.60168 130.778182 +L 242.065791 126.692484 +L 242.529901 130.194511 +L 242.994011 115.310898 +L 243.458122 126.98432 +L 243.922232 114.435391 +L 244.386343 127.276155 +L 244.850453 129.61084 +L 245.314564 126.400649 +L 245.778674 113.559884 +L 246.242785 126.108813 +L 246.706895 126.98432 +L 247.171006 130.194511 +L 247.635116 130.778182 +L 248.099226 130.778182 +L 248.563337 130.194511 +L 249.491558 127.567991 +L 249.955668 126.98432 +L 250.419779 130.778182 +L 250.883889 130.778182 +L 251.348 125.816977 +L 251.81211 123.774129 +L 252.276221 130.778182 +L 252.740331 130.194511 +L 253.204441 130.778182 +L 253.668552 128.151662 +L 254.132662 130.194511 +L 254.596773 130.778182 +L 255.060883 130.486346 +L 255.524994 129.902675 +L 255.989104 129.902675 +L 256.453215 119.396595 +L 256.917325 129.902675 +L 257.381436 129.902675 +L 257.845546 126.108813 +L 258.309656 118.812924 +L 258.773767 127.276155 +L 259.237877 127.276155 +L 259.701988 130.194511 +L 260.166098 125.816977 +L 260.630209 117.937417 +L 261.094319 99.259942 +L 261.55843 127.276155 +L 262.02254 122.606786 +L 262.486651 130.778182 +L 262.950761 118.521089 +L 263.414871 116.186404 +L 263.878982 129.027169 +L 264.343092 124.3578 +L 264.807203 130.778182 +L 265.271313 130.778182 +L 265.735424 116.770075 +L 266.199534 115.894569 +L 266.663645 130.486346 +L 267.127755 126.108813 +L 267.591866 130.778182 +L 268.055976 130.778182 +L 268.520087 130.194511 +L 268.984197 130.486346 +L 269.448307 129.902675 +L 269.912418 130.778182 +L 270.376528 126.692484 +L 270.840639 124.3578 +L 271.304749 113.559884 +L 271.76886 127.859826 +L 272.23297 130.486346 +L 272.697081 123.482293 +L 273.161191 130.486346 +L 273.625302 128.443497 +L 274.089412 125.816977 +L 274.553522 126.98432 +L 275.017633 129.319004 +L 275.481743 130.486346 +L 275.945854 129.027169 +L 276.409964 123.774129 +L 276.874075 129.61084 +L 277.338185 126.98432 +L 277.802296 128.151662 +L 278.266406 130.778182 +L 278.730517 104.804818 +L 279.194627 124.649635 +L 279.658737 115.019062 +L 280.122848 126.692484 +L 280.586958 106.263995 +L 281.051069 130.778182 +L 281.97929 120.563937 +L 282.4434 116.186404 +L 282.907511 120.563937 +L 283.371621 128.443497 +L 283.835732 130.778182 +L 284.763952 110.641529 +L 285.228063 112.100706 +L 285.692173 130.778182 +L 286.156284 126.98432 +L 286.620394 129.902675 +L 287.084505 113.85172 +L 287.548615 129.902675 +L 288.012726 130.778182 +L 288.940947 130.778182 +L 289.405057 129.61084 +L 289.869167 129.902675 +L 290.333278 127.859826 +L 290.797388 129.027169 +L 291.261499 127.567991 +L 291.725609 122.314951 +L 292.18972 130.486346 +L 292.65383 106.555831 +L 293.117941 127.276155 +L 293.582051 126.692484 +L 294.046162 114.143555 +L 294.510272 124.649635 +L 295.438493 130.486346 +L 295.902603 129.319004 +L 296.366714 130.486346 +L 296.830824 127.859826 +L 297.294935 104.804818 +L 297.759045 93.423231 +L 298.223156 121.147609 +L 298.687266 130.486346 +L 299.151377 126.108813 +L 299.615487 129.902675 +L 300.079597 130.194511 +L 300.543708 130.778182 +L 301.007818 130.778182 +L 301.471929 130.486346 +L 302.40015 130.486346 +L 302.86426 130.778182 +L 303.328371 130.778182 +L 303.792481 130.194511 +L 304.256592 130.194511 +L 304.720702 130.778182 +L 305.184812 130.778182 +L 305.648923 130.486346 +L 306.113033 130.486346 +L 306.577144 130.778182 +L 307.041254 130.486346 +L 307.505365 129.902675 +L 307.969475 130.486346 +L 308.433586 130.778182 +L 308.897696 130.194511 +L 309.361807 130.194511 +L 309.825917 129.61084 +L 310.290027 127.276155 +L 310.754138 129.61084 +L 311.218248 130.486346 +L 311.682359 130.194511 +L 312.146469 128.443497 +L 312.61058 125.816977 +L 313.07469 130.778182 +L 313.538801 130.486346 +L 314.002911 130.778182 +L 314.467022 130.778182 +L 314.931132 127.276155 +L 315.395242 130.778182 +L 315.859353 127.276155 +L 316.323463 130.778182 +L 316.787574 130.486346 +L 317.251684 122.606786 +L 317.715795 130.486346 +L 318.179905 118.521089 +L 318.644016 127.567991 +L 319.108126 102.178298 +L 319.572237 118.812924 +L 320.036347 129.61084 +L 320.500457 130.486346 +L 320.964568 130.194511 +L 321.428678 130.486346 +L 321.892789 117.645582 +L 322.356899 129.902675 +L 322.82101 130.778182 +L 323.28512 130.486346 +L 323.749231 125.816977 +L 324.213341 130.778182 +L 325.141562 130.778182 +L 325.605672 128.735333 +L 326.069783 120.563937 +L 326.533893 130.778182 +L 326.998004 129.902675 +L 327.462114 123.774129 +L 327.926225 122.606786 +L 328.390335 130.778182 +L 328.854446 129.902675 +L 329.318556 130.194511 +L 329.782667 127.859826 +L 330.246777 130.194511 +L 330.710887 129.319004 +L 331.174998 130.486346 +L 331.639108 130.778182 +L 332.103219 129.61084 +L 332.567329 129.027169 +L 333.03144 129.902675 +L 333.49555 119.10476 +L 333.959661 130.194511 +L 334.423771 122.023115 +L 334.887882 130.778182 +L 335.351992 129.027169 +L 335.816102 125.816977 +L 336.280213 130.778182 +L 336.744323 130.194511 +L 337.208434 130.486346 +L 337.672544 110.933364 +L 338.136655 129.027169 +L 338.600765 130.778182 +L 339.064876 130.486346 +L 339.528986 122.898622 +L 339.993097 126.108813 +L 340.457207 130.486346 +L 340.921317 124.3578 +L 341.385428 130.778182 +L 341.849538 130.778182 +L 342.313649 129.61084 +L 342.777759 130.778182 +L 343.24187 127.276155 +L 343.70598 130.194511 +L 344.170091 130.486346 +L 344.634201 130.486346 +L 345.098312 129.902675 +L 345.562422 127.276155 +L 346.026532 126.108813 +L 346.490643 126.400649 +L 346.954753 130.486346 +L 347.418864 130.486346 +L 348.347085 113.559884 +L 348.811195 130.778182 +L 349.275306 121.147609 +L 349.739416 129.902675 +L 350.203527 130.778182 +L 350.667637 129.319004 +L 351.131747 129.61084 +L 351.595858 130.778182 +L 352.059968 39.141818 +L 352.524079 129.027169 +L 352.988189 126.98432 +L 353.4523 100.71912 +L 353.91641 125.816977 +L 354.380521 130.486346 +L 354.844631 128.443497 +L 355.308742 130.778182 +L 355.772852 130.194511 +L 356.236962 127.859826 +L 356.701073 130.486346 +L 357.165183 124.3578 +L 357.629294 127.567991 +L 358.093404 129.902675 +L 358.557515 129.319004 +L 359.021625 121.73128 +L 359.485736 130.778182 +L 359.949846 130.486346 +L 360.413957 129.61084 +L 360.878067 126.400649 +L 361.342177 130.194511 +L 361.806288 130.778182 +L 362.270398 125.525142 +L 362.734509 129.319004 +L 363.198619 130.778182 +L 363.66273 130.194511 +L 364.12684 119.396595 +L 364.590951 130.778182 +L 365.055061 130.486346 +L 365.983282 130.486346 +L 366.447392 130.778182 +L 366.911503 130.194511 +L 367.375613 130.778182 +L 367.839724 126.108813 +L 368.303834 126.400649 +L 368.767945 130.194511 +L 369.232055 130.778182 +L 369.696166 125.233306 +L 370.160276 129.027169 +L 370.624387 129.61084 +L 371.088497 121.439444 +L 371.552608 126.108813 +L 372.016718 124.941471 +L 372.480828 130.778182 +L 372.944939 129.319004 +L 373.409049 126.400649 +L 373.87316 129.61084 +L 374.33727 126.400649 +L 374.801381 126.692484 +L 375.265491 114.435391 +L 375.729602 130.778182 +L 376.193712 117.061911 +L 376.657823 128.735333 +L 377.121933 130.194511 +L 377.586043 130.778182 +L 378.514264 130.778182 +L 378.978375 126.400649 +L 379.442485 129.027169 +L 379.906596 129.902675 +L 380.370706 129.61084 +L 380.834817 130.194511 +L 381.298927 129.319004 +L 381.763038 130.778182 +L 382.227148 130.486346 +L 382.691258 130.778182 +L 383.155369 130.778182 +L 383.619479 129.319004 +L 384.08359 128.735333 +L 384.5477 130.486346 +L 385.011811 129.902675 +L 385.475921 130.194511 +L 385.940032 130.778182 +L 386.404142 130.486346 +L 386.868253 129.319004 +L 387.332363 130.778182 +L 387.796473 130.778182 +L 388.260584 129.027169 +L 388.724694 130.778182 +L 389.188805 129.61084 +L 389.652915 129.319004 +L 390.117026 129.319004 +L 390.581136 130.778182 +L 391.045247 130.778182 +L 391.509357 130.194511 +L 391.973468 125.816977 +L 392.437578 130.486346 +L 392.901688 130.778182 +L 393.829909 130.194511 +L 394.29402 130.486346 +L 394.75813 129.902675 +L 395.222241 130.486346 +L 395.686351 130.486346 +L 396.150462 130.194511 +L 396.614572 122.898622 +L 397.078683 129.319004 +L 397.542793 130.778182 +L 398.006903 130.778182 +L 398.471014 130.194511 +L 398.935124 124.941471 +L 399.399235 130.778182 +L 399.863345 130.486346 +L 400.327456 130.778182 +L 400.791566 129.902675 +L 401.255677 125.525142 +L 401.719787 130.778182 +L 402.183898 130.778182 +L 402.648008 110.641529 +L 403.112118 128.151662 +L 403.576229 130.486346 +L 404.040339 130.778182 +L 404.50445 122.314951 +L 404.96856 130.486346 +L 405.432671 130.194511 +L 405.896781 130.486346 +L 406.360892 130.486346 +L 406.825002 122.606786 +L 407.289113 130.486346 +L 407.753223 130.486346 +L 408.217333 130.778182 +L 408.681444 128.735333 +L 409.145554 130.778182 +L 409.609665 128.151662 +L 410.073775 122.898622 +L 410.537886 129.902675 +L 411.001996 128.735333 +L 411.466107 130.194511 +L 411.930217 121.439444 +L 412.394328 129.61084 +L 412.858438 129.902675 +L 413.322548 119.688431 +L 413.786659 130.194511 +L 414.250769 129.61084 +L 414.71488 130.486346 +L 415.17899 129.61084 +L 415.643101 130.486346 +L 416.107211 128.735333 +L 416.571322 130.778182 +L 417.035432 130.194511 +L 417.499543 130.778182 +L 417.963653 130.486346 +L 418.427763 129.027169 +L 418.891874 128.151662 +L 419.355984 130.486346 +L 419.820095 130.486346 +L 420.284205 128.443497 +L 420.748316 124.3578 +L 421.212426 130.778182 +L 421.676537 129.902675 +L 422.140647 127.276155 +L 422.604758 130.486346 +L 423.068868 122.606786 +L 423.532978 127.859826 +L 423.997089 127.859826 +L 424.461199 130.486346 +L 424.92531 128.735333 +L 425.38942 103.929311 +L 425.853531 114.143555 +L 426.317641 130.778182 +L 426.781752 130.194511 +L 427.245862 130.778182 +L 427.709973 130.194511 +L 428.174083 130.194511 +L 428.638193 129.61084 +L 429.102304 128.735333 +L 429.566414 130.194511 +L 430.030525 130.778182 +L 430.958746 130.194511 +L 431.422856 127.859826 +L 431.886967 127.859826 +L 432.351077 126.108813 +L 432.815188 130.778182 +L 433.279298 130.778182 +L 433.743408 130.486346 +L 434.207519 124.065964 +L 434.671629 126.400649 +L 435.13574 130.778182 +L 435.59985 130.194511 +L 436.063961 130.486346 +L 436.528071 117.937417 +L 436.992182 119.10476 +L 437.456292 130.778182 +L 437.920403 130.194511 +L 438.384513 130.778182 +L 438.848623 129.61084 +L 439.312734 130.778182 +L 439.776844 130.778182 +L 440.240955 130.194511 +L 440.705065 130.778182 +L 441.169176 130.194511 +L 441.633286 128.735333 +L 442.097397 122.606786 +L 442.561507 130.778182 +L 443.489728 130.778182 +L 443.953838 129.902675 +L 444.417949 130.778182 +L 444.882059 128.735333 +L 445.34617 129.902675 +L 445.81028 119.980266 +L 446.274391 130.778182 +L 446.738501 122.314951 +L 447.202612 130.194511 +L 447.666722 130.486346 +L 448.130833 124.065964 +L 448.594943 130.486346 +L 449.059053 130.194511 +L 449.523164 130.194511 +L 449.987274 129.902675 +L 450.451385 129.902675 +L 450.915495 129.319004 +L 451.379606 129.027169 +L 451.843716 130.194511 +L 452.307827 127.859826 +L 452.771937 128.735333 +L 453.236048 128.151662 +L 453.700158 130.486346 +L 454.164268 130.486346 +L 454.628379 128.735333 +L 455.092489 129.61084 +L 455.5566 128.735333 +L 456.02071 123.774129 +L 456.484821 121.73128 +L 456.948931 130.194511 +L 457.413042 129.902675 +L 457.877152 129.902675 +L 458.341263 130.194511 +L 459.269483 130.194511 +L 459.733594 130.778182 +L 460.197704 129.902675 +L 460.661815 130.778182 +L 461.125925 130.778182 +L 461.590036 129.902675 +L 462.054146 130.486346 +L 462.518257 130.194511 +L 462.982367 130.778182 +L 463.446478 130.486346 +L 463.910588 128.443497 +L 464.374698 129.027169 +L 464.838809 130.778182 +L 465.302919 130.778182 +L 466.23114 130.194511 +L 466.695251 130.778182 +L 467.623472 130.778182 +L 468.087582 126.400649 +L 468.551693 130.778182 +L 469.015803 124.941471 +L 469.479913 129.027169 +L 469.944024 129.319004 +L 470.408134 130.486346 +L 470.872245 130.194511 +L 471.800466 130.194511 +L 472.264576 124.3578 +L 472.728687 125.816977 +L 473.192797 126.692484 +L 473.656908 129.902675 +L 474.121018 130.778182 +L 474.585129 124.941471 +L 475.049239 129.027169 +L 475.513349 130.194511 +L 475.97746 130.486346 +L 476.44157 128.151662 +L 476.905681 129.902675 +L 477.369791 129.902675 +L 477.833902 126.400649 +L 478.298012 128.443497 +L 478.762123 125.525142 +L 479.226233 130.486346 +L 480.154454 130.486346 +L 480.618564 128.443497 +L 481.082675 128.735333 +L 481.546785 121.439444 +L 482.010896 126.400649 +L 482.475006 125.525142 +L 482.939117 130.778182 +L 483.403227 129.027169 +L 483.867338 128.735333 +L 484.331448 127.276155 +L 484.795559 130.486346 +L 485.259669 128.735333 +L 485.723779 128.443497 +L 486.652 123.190457 +L 487.116111 119.688431 +L 487.580221 129.319004 +L 488.044332 130.778182 +L 488.508442 130.778182 +L 488.972553 129.61084 +L 489.436663 127.859826 +L 489.900774 130.778182 +L 490.364884 129.61084 +L 490.828994 126.98432 +L 491.293105 129.61084 +L 491.757215 129.902675 +L 492.221326 130.778182 +L 492.685436 130.194511 +L 493.149547 130.486346 +L 493.613657 128.735333 +L 494.077768 129.027169 +L 494.541878 130.778182 +L 495.005989 115.894569 +L 495.470099 130.778182 +L 495.934209 127.859826 +L 496.39832 126.108813 +L 496.86243 130.194511 +L 497.790651 130.778182 +L 498.254762 130.486346 +L 498.718872 129.027169 +L 499.182983 126.98432 +L 499.647093 119.980266 +L 500.111204 128.443497 +L 500.575314 128.443497 +L 501.039424 129.902675 +L 501.503535 128.151662 +L 501.967645 130.194511 +L 502.431756 130.778182 +L 502.895866 125.816977 +L 503.359977 123.190457 +L 503.824087 130.486346 +L 504.288198 130.486346 +L 504.752308 129.61084 +L 505.216419 126.692484 +L 505.680529 129.319004 +L 506.144639 126.98432 +L 506.60875 127.276155 +L 507.07286 129.61084 +L 507.536971 130.778182 +L 508.001081 126.400649 +L 508.465192 129.319004 +L 509.393413 130.486346 +L 509.857523 130.486346 +L 510.321634 129.319004 +L 510.785744 126.98432 +L 511.249854 126.692484 +L 511.713965 129.902675 +L 512.178075 128.735333 +L 512.642186 130.778182 +L 513.106296 130.486346 +L 513.570407 127.276155 +L 514.034517 129.319004 +L 514.498628 130.778182 +L 514.962738 130.194511 +L 515.426849 130.486346 +L 516.355069 130.486346 +L 516.81918 124.649635 +L 517.28329 130.778182 +L 517.747401 130.194511 +L 518.211511 129.902675 +L 518.675622 130.778182 +L 519.139732 122.314951 +L 519.603843 127.276155 +L 520.067953 129.319004 +L 520.532064 122.898622 +L 520.996174 129.027169 +L 521.460284 129.61084 +L 521.924395 130.486346 +L 522.388505 126.98432 +L 522.852616 128.735333 +L 523.316726 125.525142 +L 523.780837 113.559884 +L 524.244947 119.396595 +L 524.709058 130.486346 +L 525.173168 130.778182 +L 525.637279 114.727226 +L 526.101389 128.151662 +L 526.565499 126.98432 +L 527.02961 124.065964 +L 527.49372 130.486346 +L 527.957831 130.486346 +L 528.421941 129.61084 +L 528.886052 130.778182 +L 529.350162 129.319004 +L 529.814273 130.194511 +L 530.278383 130.194511 +L 530.742494 129.319004 +L 531.206604 129.027169 +L 531.670714 110.933364 +L 532.134825 108.015009 +L 532.598935 130.486346 +L 533.063046 130.194511 +L 533.527156 130.778182 +L 533.991267 128.735333 +L 534.455377 130.778182 +L 534.919488 129.027169 +L 535.383598 129.902675 +L 535.847709 130.486346 +L 536.311819 129.902675 +L 536.775929 130.778182 +L 537.24004 129.902675 +L 537.70415 130.778182 +L 538.168261 130.194511 +L 538.632371 130.194511 +L 539.096482 130.778182 +L 539.560592 124.649635 +L 540.024703 130.486346 +L 540.488813 123.190457 +L 540.952924 129.902675 +L 541.417034 130.778182 +L 541.881144 129.61084 +L 542.345255 127.859826 +L 542.809365 117.645582 +L 543.273476 128.151662 +L 543.737586 127.859826 +L 544.201697 130.778182 +L 544.665807 120.855773 +L 545.129918 126.692484 +L 545.594028 129.61084 +L 546.058139 112.976213 +L 546.522249 127.859826 +L 546.986359 129.902675 +L 547.45047 126.108813 +L 547.91458 129.902675 +L 548.378691 127.567991 +L 548.842801 127.859826 +L 549.306912 124.065964 +L 549.771022 129.61084 +L 550.235133 129.61084 +L 551.163354 127.567991 +L 551.627464 119.10476 +L 552.091574 129.027169 +L 552.555685 130.778182 +L 553.019795 127.859826 +L 553.483906 124.065964 +L 553.948016 116.186404 +L 554.412127 121.439444 +L 554.876237 129.027169 +L 555.340348 130.486346 +L 555.804458 128.151662 +L 556.268569 127.276155 +L 556.732679 126.692484 +L 557.196789 126.400649 +L 557.6609 127.567991 +L 558.12501 120.563937 +L 558.589121 129.61084 +L 559.053231 129.61084 +L 559.981452 122.898622 +L 560.445563 120.855773 +L 560.909673 130.486346 +L 561.373784 122.314951 +L 561.837894 128.443497 +L 562.302004 130.778182 +L 562.766115 127.567991 +L 563.230225 130.194511 +L 563.694336 129.61084 +L 565.086667 130.486346 +L 565.550778 124.649635 +L 566.014888 130.486346 +L 566.478999 124.3578 +L 566.943109 129.319004 +L 567.407219 129.319004 +L 567.87133 130.486346 +L 568.33544 130.778182 +L 568.799551 130.486346 +L 569.263661 130.778182 +L 569.727772 130.486346 +L 570.191882 129.61084 +L 570.655993 130.486346 +L 571.120103 130.778182 +L 571.584214 129.902675 +L 572.048324 130.778182 +L 572.512435 130.194511 +L 572.976545 130.194511 +L 573.440655 130.778182 +L 573.904766 129.61084 +L 574.368876 130.194511 +L 574.832987 130.486346 +L 575.297097 130.194511 +L 575.761208 130.486346 +L 576.225318 130.486346 +L 576.689429 130.194511 +L 577.153539 130.486346 +L 577.61765 130.486346 +L 578.08176 130.194511 +L 578.54587 128.443497 +L 579.009981 130.194511 +L 579.474091 121.147609 +L 579.938202 130.486346 +L 580.402312 130.486346 +L 580.866423 129.61084 +L 581.330533 130.778182 +L 581.794644 117.937417 +L 582.258754 130.194511 +L 582.722865 130.778182 +L 583.186975 129.027169 +L 583.651085 130.778182 +L 584.115196 130.486346 +L 584.579306 130.778182 +L 585.043417 130.778182 +L 585.507527 129.902675 +L 585.971638 130.778182 +L 586.435748 126.400649 +L 586.899859 130.778182 +L 587.363969 129.902675 +L 587.82808 130.778182 +L 588.29219 129.902675 +L 588.7563 122.898622 +L 589.220411 127.859826 +L 589.684521 125.816977 +L 590.148632 129.319004 +L 590.612742 130.194511 +L 591.076853 129.319004 +L 591.540963 130.486346 +L 592.005074 130.486346 +L 592.469184 130.778182 +L 592.933295 130.778182 +L 593.397405 129.319004 +L 594.325626 130.486346 +L 594.789736 130.486346 +L 595.253847 129.61084 +L 595.717957 130.486346 +L 596.182068 129.319004 +L 596.646178 130.778182 +L 597.574399 130.778182 +L 598.03851 129.902675 +L 598.50262 130.778182 +L 599.430841 130.778182 +L 600.359062 129.61084 +L 600.823172 130.778182 +L 601.751393 130.778182 +L 602.215504 128.151662 +L 602.679614 130.778182 +L 603.143725 130.194511 +L 603.607835 127.859826 +L 604.071945 130.778182 +L 605.000166 130.778182 +L 605.464277 130.486346 +L 605.928387 130.486346 +L 606.392498 130.778182 +L 606.856608 129.902675 +L 607.320719 127.859826 +L 607.784829 124.649635 +L 608.24894 123.190457 +L 608.71305 130.486346 +L 609.17716 129.61084 +L 609.641271 130.486346 +L 610.105381 121.73128 +L 610.569492 117.937417 +L 611.033602 119.980266 +L 611.497713 125.233306 +L 611.961823 125.525142 +L 612.425934 130.194511 +L 612.890044 127.859826 +L 613.354155 126.400649 +L 613.818265 128.735333 +L 614.282375 125.233306 +L 614.746486 120.855773 +L 615.210596 119.688431 +L 615.674707 130.486346 +L 616.138817 130.194511 +L 616.602928 122.898622 +L 617.067038 101.886462 +L 617.531149 127.859826 +L 617.995259 119.688431 +L 618.45937 123.190457 +L 618.92348 130.486346 +L 619.38759 129.61084 +L 619.851701 128.151662 +L 620.315811 129.027169 +L 620.779922 119.980266 +L 621.244032 114.435391 +L 621.708143 128.443497 +L 622.172253 130.778182 +L 622.636364 129.61084 +L 622.636364 129.61084 +" clip-path="url(#p4123ba94f7)" style="fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square"/> +" clip-path="url(#p4123ba94f7)" style="fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square"/> - + @@ -2858,12 +3023,12 @@ z - + - + @@ -2880,12 +3045,12 @@ z - + - + - + - + @@ -2965,12 +3130,12 @@ z - + - + @@ -2987,12 +3152,12 @@ z - + - + @@ -3009,12 +3174,12 @@ z - + - + @@ -3028,6 +3193,13 @@ z + + + + + + + @@ -3041,27 +3213,27 @@ z - + - + - + - + - + - + @@ -3069,14 +3241,14 @@ z - + - + - + @@ -3084,2432 +3256,2629 @@ z - + - + - + + + + + + + + + + + + + + + + - + +L 115.727273 234.261143 +L 116.090909 232.135558 +L 116.454545 245.597601 +L 116.818182 251.502006 +L 117.181818 240.874077 +L 117.545455 240.637901 +L 117.909091 237.331434 +L 118.272727 240.637901 +L 118.636364 241.346429 +L 119 250.793477 +L 119.363636 248.904067 +L 119.727273 248.195539 +L 120.090909 241.346429 +L 120.454545 218.201162 +L 121.181818 245.125248 +L 121.909091 251.265829 +L 122.636364 228.829091 +L 123 246.778482 +L 123.363636 244.652896 +L 123.727273 239.220843 +L 124.090909 239.220843 +L 124.454545 250.084948 +L 124.818182 239.45702 +L 125.181818 236.386729 +L 125.545455 244.889072 +L 125.909091 244.889072 +L 126.272727 240.874077 +L 126.636364 247.723187 +L 127 249.612596 +L 127.363636 230.482324 +L 127.727273 249.37642 +L 128.090909 248.667891 +L 128.454545 250.084948 +L 128.818182 248.431715 +L 129.181818 251.502006 +L 129.545455 251.502006 +L 129.909091 231.899381 +L 130.272727 221.271453 +L 130.636364 245.125248 +L 131 246.306129 +L 131.363636 230.7185 +L 131.727273 251.029653 +L 132.090909 246.069953 +L 132.454545 243.235839 +L 132.818182 247.014658 +L 133.181818 238.748491 +L 133.545455 247.723187 +L 133.909091 251.029653 +L 134.272727 251.738182 +L 134.636364 245.125248 +L 135 243.708191 +L 135.363636 243.944367 +L 135.727273 242.763486 +L 136.090909 249.37642 +L 136.454545 251.029653 +L 136.818182 250.793477 +L 137.181818 247.959363 +L 137.545455 248.431715 +L 137.909091 244.180544 +L 138.272727 250.321125 +L 138.636364 251.265829 +L 139 251.502006 +L 139.363636 248.904067 +L 140.454545 251.738182 +L 140.818182 247.959363 +L 141.181818 248.195539 +L 141.545455 251.029653 +L 142.272727 244.180544 +L 142.636364 242.054958 +L 143 248.431715 +L 143.363636 249.37642 +L 143.727273 235.678201 +L 144.090909 250.557301 +L 144.454545 237.095258 +L 144.818182 238.512315 +L 145.181818 242.054958 +L 145.545455 236.622905 +L 145.909091 247.723187 +L 146.272727 237.803786 +L 146.636364 251.265829 +L 147 236.859082 +L 147.363636 238.039963 +L 147.727273 230.954677 +L 148.818182 244.41672 +L 149.181818 248.904067 +L 149.545455 232.844086 +L 149.909091 229.065267 +L 150.272727 238.984667 +L 150.636364 237.803786 +L 151 235.678201 +L 151.363636 248.195539 +L 151.727273 249.140244 +L 152.090909 233.788791 +L 152.454545 247.723187 +L 153.181818 236.386729 +L 153.909091 251.029653 +L 154.272727 248.431715 +L 154.636364 238.276139 +L 155 237.803786 +L 155.363636 229.773796 +L 155.727273 243.708191 +L 156.090909 250.557301 +L 156.454545 250.793477 +L 156.818182 249.612596 +L 157.181818 244.180544 +L 157.545455 244.41672 +L 157.909091 247.723187 +L 158.272727 234.49732 +L 158.636364 248.904067 +L 159 243.708191 +L 159.363636 241.346429 +L 159.727273 242.763486 +L 160.090909 230.009972 +L 160.454545 238.512315 +L 160.818182 237.803786 +L 161.181818 242.054958 +L 161.545455 240.637901 +L 161.909091 241.582605 +L 162.272727 195.055895 +L 162.636364 246.778482 +L 163 234.49732 +L 163.363636 237.56761 +L 163.727273 231.190853 +L 164.090909 243.472015 +L 164.454545 208.754114 +L 164.818182 207.337057 +L 165.181818 212.296757 +L 165.545455 233.080262 +L 165.909091 187.025904 +L 166.272727 228.356739 +L 166.636364 247.014658 +L 167 246.306129 +L 167.727273 234.733496 +L 168.090909 231.899381 +L 168.454545 237.56761 +L 168.818182 228.592915 +L 169.181818 245.125248 +L 169.545455 246.778482 +L 169.909091 213.241462 +L 170.272727 235.914377 +L 170.636364 237.331434 +L 171 247.250834 +L 171.363636 249.140244 +L 171.727273 248.667891 +L 172.090909 236.150553 +L 172.454545 195.528247 +L 172.818182 233.552615 +L 173.181818 237.331434 +L 173.545455 220.562924 +L 173.909091 245.597601 +L 174.272727 248.904067 +L 174.636364 246.069953 +L 175 226.939681 +L 175.363636 240.874077 +L 175.727273 228.120562 +L 176.090909 208.990291 +L 176.454545 236.859082 +L 176.818182 242.999663 +L 177.181818 247.014658 +L 177.545455 188.915314 +L 177.909091 231.663205 +L 178.272727 244.889072 +L 178.636364 238.039963 +L 179 239.220843 +L 179.363636 249.37642 +L 179.727273 247.723187 +L 180.090909 198.362362 +L 180.454545 192.694133 +L 180.818182 207.337057 +L 181.181818 244.41672 +L 181.545455 249.612596 +L 181.909091 239.220843 +L 182.272727 248.195539 +L 183 229.065267 +L 183.363636 177.34268 +L 183.727273 227.175858 +L 184.090909 226.467329 +L 184.454545 230.482324 +L 184.818182 246.542306 +L 185.181818 247.250834 +L 185.545455 225.522624 +L 185.909091 238.748491 +L 186.272727 238.512315 +L 186.636364 230.7185 +L 187 244.652896 +L 187.363636 249.612596 +L 187.727273 207.100881 +L 188.090909 239.693196 +L 188.454545 219.382043 +L 188.818182 214.186167 +L 189.181818 219.854396 +L 189.545455 250.084948 +L 189.909091 250.084948 +L 190.272727 227.412034 +L 190.636364 236.150553 +L 191 235.678201 +L 191.363636 241.110253 +L 191.727273 244.180544 +L 192.090909 248.904067 +L 192.454545 247.014658 +L 192.818182 230.246148 +L 193.181818 245.361425 +L 193.545455 242.291134 +L 193.909091 235.442024 +L 194.272727 240.874077 +L 194.636364 250.084948 +L 195 250.084948 +L 195.363636 244.41672 +L 195.727273 242.054958 +L 196.090909 247.250834 +L 196.454545 242.999663 +L 196.818182 244.889072 +L 197.181818 249.612596 +L 197.545455 248.195539 +L 197.909091 234.49732 +L 198.272727 238.984667 +L 198.636364 182.066204 +L 199 220.090572 +L 199.363636 245.361425 +L 199.727273 243.708191 +L 200.090909 250.321125 +L 200.454545 235.442024 +L 200.818182 237.095258 +L 201.181818 243.472015 +L 201.545455 242.763486 +L 201.909091 238.276139 +L 202.272727 250.084948 +L 202.636364 250.557301 +L 203 202.849709 +L 203.363636 241.346429 +L 203.727273 246.069953 +L 204.090909 247.959363 +L 204.454545 209.934995 +L 204.818182 247.959363 +L 205.181818 248.667891 +L 205.909091 243.472015 +L 206.272727 243.708191 +L 206.636364 228.592915 +L 207 245.597601 +L 207.363636 250.084948 +L 207.727273 244.889072 +L 208.090909 246.306129 +L 208.454545 191.985604 +L 208.818182 206.392352 +L 209.181818 242.291134 +L 209.909091 245.833777 +L 210.272727 245.361425 +L 210.636364 234.969672 +L 211 243.708191 +L 211.363636 244.652896 +L 211.727273 227.175858 +L 212.090909 241.346429 +L 212.454545 250.557301 +L 212.818182 251.738182 +L 213.181818 245.833777 +L 213.545455 246.306129 +L 213.909091 247.48701 +L 214.272727 244.889072 +L 214.636364 247.014658 +L 215 249.848772 +L 215.363636 251.265829 +L 215.727273 244.889072 +L 216.090909 244.652896 +L 216.454545 234.261143 +L 216.818182 232.844086 +L 217.181818 250.793477 +L 217.545455 247.014658 +L 217.909091 251.738182 +L 218.272727 241.110253 +L 218.636364 242.054958 +L 219 244.180544 +L 219.363636 241.818782 +L 219.727273 248.904067 +L 220.090909 246.542306 +L 220.454545 250.321125 +L 220.818182 239.220843 +L 221.181818 240.874077 +L 221.545455 245.125248 +L 221.909091 242.52731 +L 222.272727 234.733496 +L 222.636364 243.472015 +L 223 248.904067 +L 223.363636 235.678201 +L 223.727273 250.557301 +L 224.090909 246.778482 +L 224.454545 245.361425 +L 224.818182 251.265829 +L 225.181818 251.029653 +L 225.545455 245.833777 +L 225.909091 246.306129 +L 226.272727 235.442024 +L 226.636364 234.024967 +L 227 249.37642 +L 227.727273 250.557301 +L 228.090909 243.708191 +L 228.454545 230.954677 +L 228.818182 238.276139 +L 229.181818 238.039963 +L 229.545455 246.069953 +L 229.909091 250.084948 +L 230.272727 246.542306 +L 230.636364 247.250834 +L 231 250.084948 +L 231.363636 238.984667 +L 231.727273 248.195539 +L 232.090909 243.708191 +L 232.454545 229.065267 +L 232.818182 251.029653 +L 233.181818 248.667891 +L 233.909091 221.035276 +L 234.272727 238.512315 +L 234.636364 248.667891 +L 235 248.195539 +L 235.363636 250.557301 +L 235.727273 247.250834 +L 236.090909 234.49732 +L 236.454545 233.080262 +L 236.818182 225.050272 +L 237.545455 248.904067 +L 237.909091 251.502006 +L 238.272727 248.904067 +L 238.636364 250.084948 +L 239 241.346429 +L 239.363636 196.945305 +L 239.727273 232.135558 +L 240.090909 243.708191 +L 240.454545 242.291134 +L 240.818182 233.316439 +L 241.181818 233.316439 +L 241.545455 224.577919 +L 241.909091 204.739119 +L 242.272727 221.507629 +L 242.636364 247.014658 +L 243 250.793477 +L 243.363636 227.884386 +L 243.727273 230.954677 +L 244.090909 217.256457 +L 244.454545 241.582605 +L 244.818182 238.039963 +L 245.181818 246.778482 +L 245.545455 248.667891 +L 245.909091 219.854396 +L 246.272727 240.165548 +L 246.636364 249.848772 +L 247 226.939681 +L 247.363636 175.217095 +L 247.727273 241.818782 +L 248.090909 237.803786 +L 248.454545 230.7185 +L 248.818182 231.663205 +L 249.181818 243.944367 +L 249.545455 234.733496 +L 250.272727 247.48701 +L 250.636364 246.542306 +L 251 237.803786 +L 251.363636 249.37642 +L 251.727273 244.41672 +L 252.090909 232.135558 +L 252.818182 251.029653 +L 253.181818 250.321125 +L 253.545455 245.833777 +L 253.909091 234.024967 +L 254.636364 247.723187 +L 255 248.431715 +L 255.363636 248.431715 +L 255.727273 249.140244 +L 256.090909 240.874077 +L 256.454545 237.56761 +L 256.818182 244.889072 +L 257.545455 239.220843 +L 257.909091 250.321125 +L 258.272727 250.084948 +L 258.636364 236.622905 +L 259 235.205848 +L 259.363636 246.306129 +L 260.090909 251.029653 +L 260.454545 248.904067 +L 260.818182 248.195539 +L 261.181818 245.361425 +L 261.545455 231.427029 +L 261.909091 239.929372 +L 262.272727 240.401724 +L 262.636364 229.773796 +L 263 250.084948 +L 263.363636 230.954677 +L 263.727273 238.984667 +L 264.090909 208.754114 +L 264.454545 241.346429 +L 264.818182 225.522624 +L 265.181818 247.959363 +L 265.545455 248.667891 +L 266.272727 213.713814 +L 266.636364 236.622905 +L 267 238.984667 +L 267.363636 244.41672 +L 267.727273 235.442024 +L 268.090909 249.37642 +L 268.454545 221.271453 +L 268.818182 237.803786 +L 269.181818 241.346429 +L 269.545455 243.708191 +L 269.909091 243.944367 +L 270.272727 247.48701 +L 270.636364 249.37642 +L 271 246.542306 +L 271.727273 251.029653 +L 272.090909 249.848772 +L 272.454545 249.612596 +L 272.818182 247.48701 +L 273.181818 221.743805 +L 273.909091 243.235839 +L 274.272727 244.180544 +L 274.636364 250.084948 +L 275.363636 251.738182 +L 276.090909 238.512315 +L 276.454545 242.52731 +L 276.818182 223.397038 +L 277.181818 247.48701 +L 277.545455 246.778482 +L 277.909091 251.029653 +L 278.272727 248.195539 +L 278.636364 240.874077 +L 279 245.597601 +L 279.363636 243.235839 +L 280.090909 250.793477 +L 280.454545 250.321125 +L 280.818182 223.397038 +L 281.181818 223.869391 +L 281.909091 248.195539 +L 282.272727 221.507629 +L 282.636364 247.48701 +L 283 237.803786 +L 283.363636 217.492634 +L 283.727273 239.693196 +L 284.090909 214.894695 +L 284.454545 204.975295 +L 284.818182 234.969672 +L 285.181818 250.793477 +L 285.545455 250.084948 +L 285.909091 203.322062 +L 286.636364 227.175858 +L 287 227.884386 +L 287.363636 187.734433 +L 287.727273 244.889072 +L 288.090909 246.306129 +L 288.454545 221.507629 +L 288.818182 229.065267 +L 289.181818 243.708191 +L 289.545455 242.054958 +L 289.909091 229.301443 +L 290.272727 248.195539 +L 290.636364 250.084948 +L 291 228.829091 +L 291.363636 237.803786 +L 291.727273 226.703505 +L 292.090909 234.49732 +L 292.454545 220.562924 +L 292.818182 241.110253 +L 293.181818 248.667891 +L 293.545455 225.7588 +L 293.909091 231.190853 +L 294.272727 234.261143 +L 294.636364 230.482324 +L 295 193.638838 +L 295.363636 227.175858 +L 295.727273 242.52731 +L 296.090909 170.965923 +L 296.454545 206.864705 +L 296.818182 228.120562 +L 297.181818 242.52731 +L 297.545455 241.110253 +L 298.272727 247.959363 +L 298.636364 216.547929 +L 299 226.467329 +L 299.363636 214.658519 +L 299.727273 217.72881 +L 300.090909 228.356739 +L 300.454545 250.321125 +L 300.818182 249.848772 +L 301.181818 217.964986 +L 301.545455 237.56761 +L 301.909091 225.994977 +L 302.272727 233.080262 +L 302.636364 237.331434 +L 303 243.944367 +L 303.363636 248.195539 +L 303.727273 232.371734 +L 304.090909 238.039963 +L 304.454545 220.7991 +L 304.818182 218.673515 +L 305.181818 243.944367 +L 305.545455 249.37642 +L 305.909091 251.738182 +L 306.272727 241.110253 +L 306.636364 239.45702 +L 307 244.652896 +L 307.363636 237.56761 +L 307.727273 245.125248 +L 308.090909 249.612596 +L 308.454545 250.321125 +L 309.181818 236.622905 +L 309.545455 248.431715 +L 309.909091 248.431715 +L 310.636364 242.054958 +L 311 232.135558 +L 311.363636 240.637901 +L 311.727273 240.165548 +L 312.090909 247.014658 +L 312.818182 247.959363 +L 313.181818 250.557301 +L 313.545455 249.140244 +L 314.272727 234.49732 +L 314.636364 236.859082 +L 315 243.944367 +L 315.363636 237.56761 +L 315.727273 250.084948 +L 316.090909 251.502006 +L 316.454545 244.652896 +L 316.818182 247.014658 +L 317.181818 235.914377 +L 317.545455 217.72881 +L 317.909091 245.125248 +L 318.272727 250.793477 +L 318.636364 249.612596 +L 319 241.818782 +L 319.363636 238.512315 +L 319.727273 240.874077 +L 320.090909 239.929372 +L 320.454545 236.859082 +L 320.818182 251.029653 +L 321.181818 242.52731 +L 321.545455 230.954677 +L 321.909091 229.773796 +L 322.272727 246.306129 +L 322.636364 248.667891 +L 323 216.075576 +L 323.363636 248.431715 +L 323.727273 250.793477 +L 324.090909 230.7185 +L 324.454545 246.778482 +L 324.818182 224.814096 +L 325.181818 232.135558 +L 325.545455 246.778482 +L 325.909091 251.502006 +L 326.272727 251.502006 +L 326.636364 250.084948 +L 327 245.361425 +L 327.363636 246.542306 +L 327.727273 244.41672 +L 328.090909 251.502006 +L 328.454545 250.084948 +L 328.818182 251.738182 +L 329.181818 246.306129 +L 329.545455 248.431715 +L 329.909091 245.597601 +L 330.272727 244.180544 +L 330.636364 250.793477 +L 331 251.265829 +L 331.363636 242.291134 +L 331.727273 224.341743 +L 332.090909 246.542306 +L 332.454545 246.778482 +L 332.818182 241.818782 +L 333.181818 248.667891 +L 333.545455 251.502006 +L 333.909091 247.959363 +L 334.272727 242.763486 +L 334.636364 244.652896 +L 335 245.125248 +L 335.363636 249.612596 +L 335.727273 251.502006 +L 336.090909 251.265829 +L 336.454545 244.180544 +L 336.818182 244.889072 +L 337.181818 247.959363 +L 337.545455 239.220843 +L 337.909091 249.37642 +L 338.272727 251.029653 +L 338.636364 249.140244 +L 339 251.029653 +L 339.363636 240.637901 +L 340.090909 230.482324 +L 340.454545 231.190853 +L 340.818182 248.195539 +L 341.181818 249.848772 +L 341.545455 225.286448 +L 341.909091 239.693196 +L 342.272727 247.250834 +L 342.636364 244.652896 +L 343 236.622905 +L 343.363636 251.265829 +L 343.727273 246.778482 +L 344.090909 240.401724 +L 344.454545 247.959363 +L 344.818182 230.954677 +L 345.181818 236.386729 +L 345.545455 251.029653 +L 345.909091 251.502006 +L 346.272727 250.321125 +L 346.636364 241.346429 +L 347 242.763486 +L 347.363636 249.140244 +L 347.727273 233.552615 +L 348.090909 249.848772 +L 348.454545 251.502006 +L 348.818182 249.37642 +L 349.181818 249.37642 +L 349.545455 242.291134 +L 349.909091 247.723187 +L 350.272727 242.52731 +L 350.636364 249.612596 +L 351 251.738182 +L 351.363636 248.667891 +L 351.727273 230.009972 +L 352.090909 247.48701 +L 352.454545 242.999663 +L 352.818182 248.195539 +L 353.545455 251.502006 +L 353.909091 245.597601 +L 354.272727 220.090572 +L 354.636364 250.084948 +L 355 229.537619 +L 355.363636 244.180544 +L 355.727273 251.738182 +L 356.090909 251.502006 +L 356.454545 250.321125 +L 356.818182 248.667891 +L 357.181818 240.401724 +L 357.545455 243.235839 +L 357.909091 208.990291 +L 358.272727 250.084948 +L 358.636364 249.612596 +L 359.363636 216.784105 +L 359.727273 239.45702 +L 360.090909 247.250834 +L 360.454545 247.959363 +L 360.818182 250.793477 +L 361.181818 251.029653 +L 361.545455 249.848772 +L 361.909091 238.748491 +L 362.272727 246.306129 +L 362.636364 223.160862 +L 363 238.748491 +L 363.363636 241.582605 +L 363.727273 251.265829 +L 364.090909 221.035276 +L 364.454545 215.8394 +L 364.818182 239.693196 +L 365.181818 248.904067 +L 365.545455 249.37642 +L 365.909091 250.557301 +L 366.636364 236.150553 +L 367 240.401724 +L 367.363636 237.56761 +L 367.727273 237.803786 +L 368.090909 243.472015 +L 368.454545 251.502006 +L 368.818182 236.386729 +L 369.181818 248.195539 +L 369.545455 249.848772 +L 369.909091 236.859082 +L 370.272727 245.361425 +L 370.636364 249.848772 +L 371 251.265829 +L 371.363636 243.472015 +L 371.727273 242.52731 +L 372.090909 244.180544 +L 372.454545 244.652896 +L 372.818182 240.874077 +L 373.181818 251.265829 +L 373.545455 249.612596 +L 373.909091 245.361425 +L 374.272727 248.195539 +L 374.636364 245.597601 +L 375 249.848772 +L 375.363636 235.678201 +L 375.727273 244.652896 +L 376.090909 250.793477 +L 376.454545 237.803786 +L 376.818182 242.291134 +L 377.545455 232.135558 +L 377.909091 234.49732 +L 378.636364 248.431715 +L 379 237.803786 +L 379.363636 237.095258 +L 379.727273 235.205848 +L 380.090909 239.45702 +L 380.454545 238.276139 +L 380.818182 249.848772 +L 381.181818 249.848772 +L 381.545455 238.984667 +L 381.909091 242.291134 +L 382.272727 240.401724 +L 382.636364 245.833777 +L 383 237.095258 +L 383.363636 250.557301 +L 383.727273 250.793477 +L 384.090909 242.291134 +L 384.454545 245.361425 +L 384.818182 244.180544 +L 385.181818 247.959363 +L 385.545455 248.195539 +L 385.909091 250.793477 +L 386.272727 251.265829 +L 386.636364 242.52731 +L 387 250.321125 +L 387.363636 242.763486 +L 387.727273 242.52731 +L 388.090909 249.848772 +L 388.454545 251.502006 +L 388.818182 248.904067 +L 389.181818 250.321125 +L 389.909091 242.763486 +L 390.272727 249.37642 +L 390.636364 250.321125 +L 391 245.833777 +L 391.363636 249.612596 +L 391.727273 233.316439 +L 392.090909 246.069953 +L 392.454545 247.959363 +L 392.818182 244.41672 +L 393.545455 251.502006 +L 393.909091 250.557301 +L 394.272727 239.220843 +L 395 246.069953 +L 395.363636 246.542306 +L 395.727273 249.612596 +L 396.090909 249.37642 +L 396.454545 248.431715 +L 396.818182 236.386729 +L 397.181818 241.582605 +L 397.545455 248.904067 +L 397.909091 250.557301 +L 399 244.180544 +L 399.363636 250.084948 +L 399.727273 245.833777 +L 400.454545 251.738182 +L 400.818182 251.738182 +L 401.181818 251.265829 +L 401.545455 251.738182 +L 401.909091 250.793477 +L 402.636364 251.738182 +L 403 247.959363 +L 403.363636 248.431715 +L 403.727273 250.793477 +L 404.090909 232.844086 +L 404.454545 240.637901 +L 404.818182 240.637901 +L 405.181818 247.250834 +L 405.545455 250.793477 +L 405.909091 244.41672 +L 406.272727 227.175858 +L 406.636364 245.361425 +L 407 244.180544 +L 407.363636 242.52731 +L 407.727273 248.431715 +L 408.090909 250.793477 +L 408.454545 250.793477 +L 408.818182 247.723187 +L 409.181818 248.667891 +L 409.545455 244.652896 +L 409.909091 245.125248 +L 410.272727 240.874077 +L 410.636364 246.306129 +L 411 244.889072 +L 411.363636 226.703505 +L 411.727273 218.437338 +L 412.090909 247.014658 +L 412.454545 245.833777 +L 412.818182 236.622905 +L 413.181818 248.904067 +L 413.545455 249.848772 +L 413.909091 229.065267 +L 414.272727 249.612596 +L 414.636364 247.014658 +L 415 239.45702 +L 415.363636 249.37642 +L 415.727273 250.793477 +L 416.090909 242.763486 +L 416.454545 242.763486 +L 416.818182 244.41672 +L 417.181818 241.110253 +L 417.545455 229.773796 +L 417.909091 232.60791 +L 418.272727 251.502006 +L 418.636364 250.084948 +L 419 244.41672 +L 419.363636 232.135558 +L 419.727273 244.180544 +L 420.090909 240.637901 +L 420.454545 230.7185 +L 420.818182 248.904067 +L 421.181818 249.140244 +L 421.545455 248.667891 +L 421.909091 241.582605 +L 422.272727 246.778482 +L 422.636364 242.054958 +L 423 248.904067 +L 423.363636 246.069953 +L 423.727273 249.140244 +L 424.090909 234.49732 +L 424.454545 244.180544 +L 424.818182 242.291134 +L 425.545455 223.869391 +L 425.909091 249.612596 +L 426.272727 245.597601 +L 426.636364 236.386729 +L 427 238.748491 +L 427.727273 245.361425 +L 428.090909 247.014658 +L 428.454545 249.848772 +L 428.818182 251.029653 +L 429.181818 245.833777 +L 429.545455 231.663205 +L 429.909091 234.261143 +L 430.272727 235.678201 +L 430.636364 236.622905 +L 431 245.833777 +L 431.363636 248.431715 +L 431.727273 218.909691 +L 432.090909 234.261143 +L 432.454545 244.652896 +L 432.818182 241.582605 +L 433.545455 250.557301 +L 433.909091 250.557301 +L 434.272727 231.663205 +L 434.636364 241.582605 +L 435 237.331434 +L 435.363636 245.125248 +L 435.727273 237.56761 +L 436.090909 251.029653 +L 436.454545 250.557301 +L 437.181818 240.165548 +L 437.545455 245.833777 +L 437.909091 217.492634 +L 438.272727 250.793477 +L 438.636364 251.029653 +L 439 250.557301 +L 439.727273 235.442024 +L 440.090909 236.622905 +L 440.454545 244.41672 +L 440.818182 244.889072 +L 441.181818 251.502006 +L 441.545455 250.321125 +L 441.909091 215.8394 +L 442.272727 237.331434 +L 442.636364 248.904067 +L 443 242.291134 +L 443.363636 250.557301 +L 443.727273 250.321125 +L 444.090909 251.029653 +L 444.454545 238.512315 +L 444.818182 237.331434 +L 445.181818 246.778482 +L 445.545455 241.582605 +L 445.909091 245.597601 +L 446.272727 247.723187 +L 446.636364 251.738182 +L 447 247.48701 +L 447.363636 238.276139 +L 447.727273 233.080262 +L 448.090909 246.778482 +L 448.454545 251.265829 +L 448.818182 250.557301 +L 449.181818 249.37642 +L 449.545455 245.361425 +L 449.909091 247.723187 +L 450.272727 243.708191 +L 450.636364 236.622905 +L 451 247.723187 +L 451.363636 242.054958 +L 451.727273 238.276139 +L 452.090909 238.039963 +L 452.454545 239.693196 +L 452.818182 232.60791 +L 453.181818 239.929372 +L 453.545455 242.52731 +L 453.909091 251.502006 +L 454.272727 240.165548 +L 454.636364 233.316439 +L 455.363636 247.959363 +L 455.727273 245.125248 +L 456.090909 249.848772 +L 456.454545 250.557301 +L 456.818182 246.778482 +L 457.181818 249.848772 +L 457.545455 240.401724 +L 458.272727 248.667891 +L 458.636364 238.984667 +L 459 249.37642 +L 459.363636 250.793477 +L 459.727273 247.014658 +L 460.090909 245.597601 +L 460.454545 242.763486 +L 460.818182 235.442024 +L 461.181818 249.140244 +L 461.545455 249.140244 +L 461.909091 250.084948 +L 462.272727 244.652896 +L 462.636364 233.788791 +L 463 236.859082 +L 463.363636 238.748491 +L 463.727273 216.547929 +L 464.090909 248.431715 +L 464.454545 251.738182 +L 464.818182 239.693196 +L 465.181818 241.818782 +L 465.545455 249.140244 +L 465.909091 247.723187 +L 466.636364 251.502006 +L 467 249.848772 +L 467.363636 234.969672 +L 467.727273 247.48701 +L 468.090909 242.999663 +L 468.454545 246.778482 +L 468.818182 236.859082 +L 469.181818 251.029653 +L 469.545455 245.597601 +L 469.909091 246.306129 +L 470.272727 250.321125 +L 470.636364 238.984667 +L 471 232.844086 +L 471.727273 245.833777 +L 472.090909 247.48701 +L 472.454545 246.306129 +L 472.818182 243.235839 +L 473.181818 244.652896 +L 473.545455 247.250834 +L 473.909091 240.874077 +L 474.272727 250.793477 +L 474.636364 250.793477 +L 475.363636 235.205848 +L 475.727273 233.080262 +L 476.090909 237.803786 +L 476.454545 250.084948 +L 476.818182 251.738182 +L 477.181818 242.291134 +L 477.545455 242.52731 +L 477.909091 246.778482 +L 478.272727 236.622905 +L 478.636364 249.612596 +L 479 220.090572 +L 479.363636 240.401724 +L 479.727273 238.748491 +L 480.090909 177.106504 +L 480.454545 208.281762 +L 480.818182 218.673515 +L 481.181818 210.171172 +L 481.545455 233.080262 +L 481.909091 229.065267 +L 482.272727 246.069953 +L 482.636364 237.56761 +L 483 205.211471 +L 483.363636 231.190853 +L 483.727273 246.778482 +L 484.454545 234.49732 +L 484.818182 231.899381 +L 485.181818 240.165548 +L 485.545455 243.944367 +L 485.909091 217.492634 +L 486.272727 243.235839 +L 486.636364 216.784105 +L 487 237.803786 +L 487.363636 237.331434 +L 487.727273 235.442024 +L 488.090909 225.050272 +L 488.454545 238.512315 +L 488.818182 229.065267 +L 489.181818 245.833777 +L 489.545455 250.321125 +L 489.909091 250.793477 +L 490.272727 224.105567 +L 490.636364 234.733496 +L 491 213.241462 +L 491.363636 231.899381 +L 491.727273 228.120562 +L 492.090909 250.557301 +L 492.454545 251.265829 +L 492.818182 246.542306 +L 493.181818 230.246148 +L 493.545455 193.875014 +L 493.909091 239.929372 +L 494.636364 221.979981 +L 495 241.346429 +L 495.727273 228.592915 +L 496.090909 231.663205 +L 496.454545 211.352052 +L 497.181818 241.346429 +L 497.545455 222.68851 +L 497.909091 225.994977 +L 498.272727 242.054958 +L 498.636364 236.386729 +L 499 243.472015 +L 499.363636 238.984667 +L 499.727273 250.793477 +L 500.090909 225.286448 +L 500.454545 240.401724 +L 500.818182 233.316439 +L 501.181818 248.904067 +L 501.545455 250.321125 +L 501.909091 236.859082 +L 502.272727 216.547929 +L 502.636364 250.793477 +L 503.363636 232.60791 +L 503.727273 232.844086 +L 504.090909 250.557301 +L 504.454545 232.135558 +L 504.818182 249.612596 +L 505.181818 249.848772 +L 505.545455 232.844086 +L 505.909091 230.009972 +L 506.272727 241.346429 +L 506.636364 244.180544 +L 507 249.612596 +L 507.363636 250.557301 +L 507.727273 248.195539 +L 508.090909 235.678201 +L 508.454545 234.969672 +L 508.818182 226.467329 +L 509.181818 233.316439 +L 509.545455 245.125248 +L 509.909091 249.612596 +L 510.272727 241.818782 +L 510.636364 242.763486 +L 511 237.095258 +L 511.363636 222.68851 +L 511.727273 239.929372 +L 512.090909 251.502006 +L 512.454545 250.793477 +L 512.818182 242.999663 +L 513.181818 200.251771 +L 513.545455 224.814096 +L 513.909091 230.7185 +L 514.272727 240.637901 +L 514.636364 238.748491 +L 515 243.944367 +L 515.363636 223.397038 +L 515.727273 235.678201 +L 516.090909 242.054958 +L 516.454545 241.346429 +L 516.818182 246.542306 +L 517.181818 247.014658 +L 517.545455 247.723187 +L 517.909091 233.316439 +L 518.272727 209.698819 +L 518.636364 229.537619 +L 519 239.693196 +L 519.363636 241.346429 +L 519.727273 251.265829 +L 520.090909 247.250834 +L 520.454545 214.894695 +L 520.818182 235.442024 +L 521.545455 243.472015 +L 521.909091 251.502006 +L 522.272727 250.557301 +L 522.636364 250.793477 +L 523 182.774733 +L 523.363636 241.110253 +L 523.727273 247.250834 +L 524.090909 240.637901 +L 524.454545 239.693196 +L 525.181818 250.321125 +L 525.545455 224.814096 +L 525.909091 235.914377 +L 526.272727 225.522624 +L 526.636364 232.371734 +L 527 246.542306 +L 527.363636 249.848772 +L 527.727273 247.48701 +L 528.090909 215.8394 +L 528.454545 236.622905 +L 528.818182 231.427029 +L 529.545455 211.352052 +L 529.909091 248.431715 +L 530.272727 249.848772 +L 530.636364 227.412034 +L 531 241.346429 +L 531.363636 238.039963 +L 531.727273 237.803786 +L 532.090909 230.482324 +L 532.454545 248.431715 +L 532.818182 251.502006 +L 533.181818 248.195539 +L 533.545455 247.250834 +L 533.909091 249.140244 +L 534.272727 251.738182 +L 534.636364 249.612596 +L 535 250.793477 +L 535.363636 250.793477 +L 535.727273 249.848772 +L 536.090909 230.482324 +L 536.454545 237.803786 +L 536.818182 200.251771 +L 537.181818 190.096195 +L 537.545455 248.667891 +L 537.909091 245.125248 +L 538.272727 236.859082 +L 538.636364 241.818782 +L 539 214.658519 +L 539.363636 247.48701 +L 539.727273 246.542306 +L 540.090909 244.41672 +L 540.454545 251.265829 +L 540.818182 248.904067 +L 541.545455 240.637901 +L 541.909091 245.361425 +L 542.272727 246.069953 +L 542.636364 243.944367 +L 543 250.793477 +L 543.363636 248.904067 +L 544.090909 225.7588 +L 544.454545 246.778482 +L 544.818182 232.60791 +L 545.181818 250.084948 +L 545.545455 251.029653 +L 545.909091 244.180544 +L 546.272727 242.054958 +L 546.636364 230.7185 +L 547 238.039963 +L 547.363636 234.024967 +L 548.090909 251.029653 +L 548.454545 231.427029 +L 548.818182 240.874077 +L 549.181818 238.512315 +L 549.545455 228.829091 +L 549.909091 245.597601 +L 550.272727 239.220843 +L 550.636364 242.054958 +L 551 247.250834 +L 551.363636 237.331434 +L 551.727273 235.678201 +L 552.090909 245.597601 +L 552.454545 227.175858 +L 552.818182 245.597601 +L 553.181818 246.778482 +L 553.545455 246.542306 +L 553.909091 238.748491 +L 554.272727 242.054958 +L 554.636364 239.693196 +L 555 242.054958 +L 555.363636 246.306129 +L 555.727273 247.014658 +L 556.090909 242.054958 +L 556.454545 242.291134 +L 556.818182 218.909691 +L 557.181818 236.859082 +L 557.545455 248.904067 +L 557.909091 250.557301 +L 558.272727 240.637901 +L 558.636364 249.848772 +L 559 225.522624 +L 559.363636 217.020281 +L 559.727273 248.667891 +L 560.090909 237.56761 +L 560.454545 250.793477 +L 560.818182 248.667891 +L 561.181818 242.763486 +L 561.545455 221.507629 +L 561.909091 215.367048 +L 562.272727 244.889072 +L 562.636364 232.844086 +L 563 250.793477 +L 563.727273 238.984667 +L 564.090909 238.512315 +L 564.454545 238.984667 +L 564.818182 235.205848 +L 565.545455 251.029653 +L 565.909091 235.442024 +L 566.272727 246.069953 +L 566.636364 235.678201 +L 567 246.542306 +L 567.363636 246.542306 +L 567.727273 247.723187 +L 568.090909 250.793477 +L 568.454545 251.738182 +L 568.818182 249.140244 +L 569.181818 249.140244 +L 569.545455 248.667891 +L 569.909091 237.331434 +L 570.272727 243.708191 +L 570.636364 240.874077 +L 571 236.622905 +L 571.363636 245.833777 +L 571.727273 250.557301 +L 572.090909 250.557301 +L 572.454545 246.306129 +L 572.818182 235.442024 +L 573.181818 247.250834 +L 573.545455 238.984667 +L 574.272727 250.793477 +L 574.636364 248.667891 +L 575.363636 241.346429 +L 575.727273 249.848772 +L 576.090909 242.52731 +L 576.454545 239.929372 +L 576.818182 251.029653 +L 577.181818 250.084948 +L 577.545455 242.763486 +L 577.909091 237.803786 +L 578.272727 244.41672 +L 578.636364 246.778482 +L 579 232.371734 +L 579.363636 251.029653 +L 579.727273 248.904067 +L 580.454545 249.848772 +L 580.818182 248.904067 +L 581.181818 233.788791 +L 581.545455 245.833777 +L 581.909091 248.667891 +L 582.272727 246.542306 +L 582.636364 236.386729 +L 583.363636 246.069953 +L 583.727273 245.597601 +L 584.090909 249.612596 +L 584.454545 251.029653 +L 584.818182 248.431715 +L 585.545455 247.48701 +L 585.909091 247.959363 +L 586.272727 246.778482 +L 586.636364 251.265829 +L 587 241.346429 +L 587.363636 242.763486 +L 587.727273 247.250834 +L 588.454545 228.829091 +L 588.818182 236.859082 +L 589.181818 251.502006 +L 589.545455 251.029653 +L 589.909091 246.778482 +L 590.272727 251.029653 +L 590.636364 242.054958 +L 591 240.874077 +L 591.363636 249.37642 +L 591.727273 240.401724 +L 592.090909 250.793477 +L 592.454545 245.361425 +L 592.818182 234.733496 +L 593.181818 250.793477 +L 593.545455 246.542306 +L 593.909091 246.069953 +L 594.272727 251.738182 +L 594.636364 248.667891 +L 595 241.582605 +L 595.363636 241.110253 +L 595.727273 246.778482 +L 596.090909 238.748491 +L 596.454545 249.37642 +L 596.818182 251.265829 +L 597.181818 238.748491 +L 597.545455 242.52731 +L 597.909091 244.652896 +L 598.272727 224.577919 +L 598.636364 246.306129 +L 599 248.431715 +L 599.363636 248.431715 +L 599.727273 246.069953 +L 600.090909 242.291134 +L 600.454545 242.763486 +L 600.818182 240.165548 +L 601.181818 244.180544 +L 601.545455 237.331434 +L 601.909091 248.904067 +L 602.272727 247.250834 +L 602.636364 250.321125 +L 603 249.848772 +L 603.363636 238.984667 +L 603.727273 242.054958 +L 604.090909 241.110253 +L 604.454545 250.793477 +L 604.818182 251.738182 +L 605.181818 249.612596 +L 605.545455 235.442024 +L 605.909091 237.56761 +L 606.272727 246.542306 +L 607 251.265829 +L 607.727273 241.818782 +L 608.090909 238.512315 +L 608.454545 242.52731 +L 608.818182 242.52731 +L 609.181818 248.904067 +L 609.545455 248.904067 +L 610.272727 245.125248 +L 610.636364 228.592915 +L 611.727273 251.502006 +L 612.090909 251.502006 +L 612.454545 226.231153 +L 612.818182 160.101818 +L 613.181818 215.130872 +L 613.545455 231.663205 +L 613.909091 218.673515 +L 614.272727 243.235839 +L 614.636364 239.929372 +L 615 209.934995 +L 615.363636 219.145867 +L 615.727273 207.573233 +L 616.090909 224.105567 +L 616.454545 233.316439 +L 616.818182 249.37642 +L 617.181818 242.52731 +L 617.545455 238.039963 +L 617.909091 229.065267 +L 618.272727 235.442024 +L 618.636364 234.733496 +L 619 244.180544 +L 619.363636 248.667891 +L 619.727273 251.265829 +L 620.090909 251.029653 +L 620.454545 241.110253 +L 620.818182 247.48701 +L 621.545455 225.7588 +L 621.909091 245.361425 +L 622.272727 246.542306 +L 622.636364 241.582605 +L 622.636364 241.582605 +" clip-path="url(#p10b7ab2e7a)" style="fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square"/> - + +L 115.727273 249.848772 +L 116.090909 248.904067 +L 116.454545 249.848772 +L 116.818182 251.738182 +L 117.181818 250.321125 +L 117.545455 249.612596 +L 117.909091 249.612596 +L 118.272727 249.37642 +L 118.636364 249.848772 +L 119 251.502006 +L 120.454545 249.612596 +L 120.818182 249.37642 +L 121.545455 251.029653 +L 121.909091 251.738182 +L 122.272727 249.37642 +L 122.636364 249.848772 +L 123 250.793477 +L 123.363636 251.029653 +L 123.727273 250.793477 +L 124.090909 251.502006 +L 124.454545 251.265829 +L 124.818182 250.321125 +L 125.181818 251.265829 +L 125.545455 249.37642 +L 126.636364 251.265829 +L 127 251.265829 +L 127.363636 248.195539 +L 127.727273 251.502006 +L 128.090909 251.502006 +L 128.454545 251.265829 +L 129.181818 251.738182 +L 129.545455 251.502006 +L 130.272727 247.723187 +L 131 250.321125 +L 131.363636 250.321125 +L 131.727273 251.502006 +L 132.090909 250.557301 +L 132.454545 250.321125 +L 132.818182 251.029653 +L 133.181818 248.431715 +L 133.909091 251.502006 +L 134.272727 251.738182 +L 134.636364 249.612596 +L 135.363636 249.612596 +L 135.727273 250.321125 +L 136.090909 250.557301 +L 136.454545 251.265829 +L 136.818182 251.502006 +L 137.181818 251.029653 +L 137.545455 250.793477 +L 137.909091 251.265829 +L 138.636364 251.265829 +L 139 251.502006 +L 139.363636 251.029653 +L 140.090909 251.029653 +L 140.454545 251.738182 +L 140.818182 251.265829 +L 141.181818 251.265829 +L 141.545455 251.029653 +L 141.909091 250.084948 +L 142.272727 248.667891 +L 142.636364 250.321125 +L 143 251.265829 +L 143.363636 251.029653 +L 143.727273 251.029653 +L 144.090909 251.265829 +L 144.454545 249.848772 +L 144.818182 249.140244 +L 145.181818 250.084948 +L 145.545455 247.723187 +L 145.909091 250.084948 +L 146.272727 250.557301 +L 146.636364 251.265829 +L 147 250.793477 +L 147.363636 250.793477 +L 147.727273 248.904067 +L 148.090909 249.848772 +L 148.454545 249.612596 +L 148.818182 249.612596 +L 149.181818 250.557301 +L 149.545455 247.014658 +L 150.272727 249.612596 +L 150.636364 248.195539 +L 151 247.250834 +L 151.363636 251.029653 +L 151.727273 250.793477 +L 152.090909 249.140244 +L 152.454545 250.321125 +L 152.818182 248.667891 +L 153.181818 249.848772 +L 153.545455 249.848772 +L 153.909091 251.029653 +L 154.272727 251.265829 +L 154.636364 249.37642 +L 155 248.667891 +L 155.363636 248.904067 +L 155.727273 251.029653 +L 156.090909 251.502006 +L 156.818182 251.029653 +L 157.181818 251.029653 +L 157.545455 249.848772 +L 157.909091 250.557301 +L 158.272727 249.37642 +L 158.636364 251.029653 +L 159 250.557301 +L 159.363636 251.029653 +L 159.727273 249.612596 +L 160.090909 249.37642 +L 160.454545 249.37642 +L 160.818182 248.667891 +L 161.181818 250.557301 +L 161.545455 251.029653 +L 161.909091 251.029653 +L 162.272727 243.944367 +L 162.636364 249.37642 +L 163 249.37642 +L 163.363636 248.195539 +L 164.090909 250.793477 +L 164.454545 250.793477 +L 164.818182 247.250834 +L 165.181818 247.48701 +L 165.545455 248.904067 +L 165.909091 247.48701 +L 166.272727 248.195539 +L 166.636364 250.321125 +L 167 251.029653 +L 167.363636 248.195539 +L 167.727273 247.014658 +L 168.090909 247.959363 +L 168.454545 248.195539 +L 169.181818 251.265829 +L 169.545455 250.321125 +L 169.909091 248.431715 +L 170.272727 248.431715 +L 170.636364 249.140244 +L 171 250.793477 +L 171.727273 251.265829 +L 172.090909 250.321125 +L 172.454545 247.250834 +L 172.818182 247.959363 +L 173.181818 249.140244 +L 173.545455 247.723187 +L 173.909091 250.084948 +L 174.272727 251.265829 +L 175.363636 248.904067 +L 175.727273 249.140244 +L 176.090909 248.195539 +L 176.454545 249.612596 +L 176.818182 249.848772 +L 177.181818 251.029653 +L 177.545455 246.542306 +L 177.909091 248.667891 +L 178.272727 249.37642 +L 178.636364 249.612596 +L 179 249.612596 +L 179.363636 251.029653 +L 179.727273 250.557301 +L 180.090909 246.778482 +L 180.454545 245.597601 +L 181.181818 249.37642 +L 181.545455 250.557301 +L 181.909091 249.612596 +L 182.272727 250.557301 +L 182.636364 247.250834 +L 183 247.48701 +L 183.363636 232.844086 +L 183.727273 248.667891 +L 184.090909 247.48701 +L 184.454545 250.793477 +L 184.818182 251.738182 +L 185.545455 248.904067 +L 185.909091 248.904067 +L 186.272727 249.140244 +L 186.636364 248.431715 +L 187.363636 251.265829 +L 187.727273 249.612596 +L 188.090909 248.904067 +L 188.454545 247.723187 +L 188.818182 247.959363 +L 189.181818 246.778482 +L 189.545455 250.793477 +L 189.909091 251.738182 +L 190.272727 246.778482 +L 190.636364 247.959363 +L 191 249.848772 +L 191.363636 248.195539 +L 191.727273 248.904067 +L 192.090909 251.502006 +L 192.454545 250.557301 +L 192.818182 248.904067 +L 193.181818 249.848772 +L 193.909091 247.250834 +L 194.636364 251.029653 +L 195 251.265829 +L 195.727273 248.431715 +L 196.090909 250.321125 +L 196.454545 249.848772 +L 196.818182 249.848772 +L 197.545455 250.321125 +L 197.909091 247.723187 +L 198.272727 249.37642 +L 198.636364 249.37642 +L 199 250.321125 +L 199.363636 249.612596 +L 199.727273 251.265829 +L 200.090909 250.557301 +L 200.454545 248.904067 +L 200.818182 249.612596 +L 201.181818 249.37642 +L 201.545455 248.904067 +L 201.909091 249.612596 +L 202.272727 251.265829 +L 202.636364 251.029653 +L 203 248.195539 +L 203.363636 250.793477 +L 204.090909 249.612596 +L 204.454545 246.778482 +L 204.818182 251.265829 +L 205.181818 250.793477 +L 205.545455 250.084948 +L 205.909091 250.557301 +L 206.272727 249.37642 +L 206.636364 248.667891 +L 207 249.612596 +L 207.363636 251.029653 +L 207.727273 251.029653 +L 208.090909 249.848772 +L 208.454545 247.959363 +L 208.818182 247.959363 +L 209.181818 250.557301 +L 209.545455 249.140244 +L 209.909091 250.793477 +L 210.272727 249.848772 +L 210.636364 248.431715 +L 211 249.140244 +L 211.363636 249.140244 +L 211.727273 248.431715 +L 212.090909 248.667891 +L 212.454545 251.265829 +L 212.818182 251.738182 +L 213.181818 250.321125 +L 213.545455 250.321125 +L 213.909091 250.557301 +L 214.272727 250.557301 +L 214.636364 250.793477 +L 215.363636 251.738182 +L 215.727273 250.557301 +L 216.090909 249.848772 +L 216.454545 250.084948 +L 216.818182 249.140244 +L 217.181818 251.265829 +L 217.545455 250.557301 +L 217.909091 251.738182 +L 218.272727 250.557301 +L 218.636364 250.557301 +L 219 248.904067 +L 219.363636 248.431715 +L 219.727273 249.848772 +L 220.090909 250.793477 +L 220.454545 250.793477 +L 220.818182 249.140244 +L 221.181818 249.848772 +L 221.545455 250.084948 +L 221.909091 250.084948 +L 222.272727 249.37642 +L 222.636364 249.612596 +L 223 250.793477 +L 223.363636 248.904067 +L 223.727273 251.502006 +L 224.090909 250.084948 +L 224.454545 250.084948 +L 224.818182 251.265829 +L 225.181818 251.029653 +L 225.545455 250.321125 +L 225.909091 250.321125 +L 226.272727 249.612596 +L 226.636364 249.848772 +L 227 251.265829 +L 227.363636 251.029653 +L 227.727273 251.502006 +L 228.090909 250.557301 +L 228.454545 250.321125 +L 228.818182 249.140244 +L 229.181818 249.612596 +L 229.545455 250.557301 +L 229.909091 251.029653 +L 230.272727 250.557301 +L 230.636364 251.502006 +L 231 251.029653 +L 231.363636 249.612596 +L 232.090909 251.265829 +L 232.454545 248.904067 +L 232.818182 251.502006 +L 233.181818 251.265829 +L 233.545455 248.667891 +L 234.272727 249.612596 +L 234.636364 250.557301 +L 235 250.084948 +L 235.363636 251.265829 +L 235.727273 250.793477 +L 236.090909 248.431715 +L 236.454545 250.084948 +L 236.818182 249.612596 +L 237.181818 250.084948 +L 237.545455 250.084948 +L 237.909091 251.502006 +L 238.272727 251.502006 +L 238.636364 251.029653 +L 239 248.904067 +L 239.727273 248.904067 +L 240.090909 250.084948 +L 240.454545 250.084948 +L 240.818182 249.37642 +L 241.181818 249.140244 +L 241.545455 247.959363 +L 241.909091 249.848772 +L 242.272727 248.195539 +L 242.636364 250.321125 +L 243 251.265829 +L 243.727273 250.084948 +L 244.090909 248.667891 +L 244.454545 248.904067 +L 245.181818 250.084948 +L 245.545455 250.321125 +L 245.909091 248.195539 +L 246.272727 248.904067 +L 246.636364 250.793477 +L 247 249.848772 +L 247.727273 249.37642 +L 248.090909 249.848772 +L 248.454545 248.195539 +L 248.818182 250.321125 +L 249.181818 250.557301 +L 249.545455 248.904067 +L 249.909091 249.37642 +L 250.272727 251.029653 +L 250.636364 250.557301 +L 251 249.848772 +L 251.363636 251.029653 +L 251.727273 249.612596 +L 252.090909 249.140244 +L 252.454545 249.37642 +L 252.818182 251.265829 +L 253.181818 251.265829 +L 253.545455 249.612596 +L 253.909091 250.557301 +L 254.272727 248.431715 +L 255 250.321125 +L 255.363636 250.793477 +L 255.727273 250.321125 +L 256.090909 249.37642 +L 256.454545 247.959363 +L 256.818182 248.904067 +L 257.181818 248.431715 +L 257.545455 249.37642 +L 257.909091 250.793477 +L 258.272727 251.029653 +L 258.636364 249.612596 +L 259 250.793477 +L 259.363636 250.084948 +L 259.727273 250.321125 +L 260.090909 251.502006 +L 260.454545 251.029653 +L 260.818182 251.029653 +L 261.181818 251.502006 +L 261.545455 249.848772 +L 261.909091 250.557301 +L 262.272727 249.37642 +L 262.636364 250.793477 +L 263 251.265829 +L 263.363636 249.37642 +L 263.727273 249.848772 +L 264.090909 249.848772 +L 264.454545 247.48701 +L 264.818182 247.250834 +L 265.181818 250.557301 +L 265.545455 250.557301 +L 265.909091 249.140244 +L 266.272727 249.140244 +L 266.636364 250.084948 +L 267 249.612596 +L 267.363636 250.557301 +L 267.727273 250.793477 +L 268.090909 250.793477 +L 268.454545 248.667891 +L 268.818182 250.084948 +L 269.181818 250.793477 +L 269.545455 251.029653 +L 269.909091 249.848772 +L 270.272727 251.738182 +L 270.636364 251.502006 +L 271 251.029653 +L 271.363636 251.029653 +L 271.727273 251.265829 +L 272.090909 250.793477 +L 272.454545 251.265829 +L 272.818182 250.557301 +L 273.181818 245.597601 +L 273.909091 249.612596 +L 275 251.029653 +L 275.363636 251.738182 +L 275.727273 249.848772 +L 276.090909 249.848772 +L 276.454545 249.37642 +L 276.818182 246.778482 +L 277.181818 250.793477 +L 277.545455 251.738182 +L 277.909091 251.502006 +L 278.272727 250.793477 +L 278.636364 248.667891 +L 279 251.029653 +L 279.363636 250.321125 +L 279.727273 248.904067 +L 280.090909 251.265829 +L 280.454545 251.265829 +L 280.818182 250.321125 +L 281.181818 248.431715 +L 281.909091 250.084948 +L 282.272727 249.612596 +L 282.636364 251.029653 +L 283 250.793477 +L 283.363636 248.667891 +L 283.727273 249.612596 +L 284.090909 247.723187 +L 284.454545 247.250834 +L 284.818182 247.723187 +L 285.181818 251.265829 +L 285.545455 251.738182 +L 285.909091 248.431715 +L 286.272727 246.778482 +L 286.636364 248.431715 +L 287 247.250834 +L 287.363636 244.41672 +L 287.727273 249.848772 +L 288.090909 249.612596 +L 288.454545 247.959363 +L 288.818182 247.723187 +L 289.181818 248.667891 +L 289.545455 249.140244 +L 289.909091 248.431715 +L 290.272727 250.084948 +L 290.636364 251.029653 +L 291 248.195539 +L 291.727273 248.667891 +L 292.090909 247.48701 +L 292.454545 247.959363 +L 292.818182 248.195539 +L 293.181818 250.793477 +L 293.545455 246.542306 +L 293.909091 246.542306 +L 294.272727 244.889072 +L 294.636364 247.723187 +L 295 247.723187 +L 295.363636 250.084948 +L 296.090909 248.431715 +L 296.454545 246.542306 +L 296.818182 248.904067 +L 297.181818 249.37642 +L 297.545455 249.612596 +L 297.909091 249.612596 +L 298.272727 250.084948 +L 298.636364 247.250834 +L 299 247.723187 +L 299.363636 245.833777 +L 299.727273 248.431715 +L 300.090909 247.723187 +L 300.454545 251.029653 +L 300.818182 251.265829 +L 301.181818 244.889072 +L 301.545455 247.959363 +L 301.909091 246.306129 +L 302.272727 247.014658 +L 302.636364 249.848772 +L 303 250.557301 +L 303.363636 250.557301 +L 303.727273 248.904067 +L 304.090909 249.612596 +L 304.454545 247.723187 +L 304.818182 247.48701 +L 305.181818 249.848772 +L 305.545455 250.084948 +L 305.909091 251.738182 +L 306.272727 248.904067 +L 306.636364 248.667891 +L 307 249.37642 +L 307.363636 245.597601 +L 307.727273 249.612596 +L 308.090909 251.502006 +L 308.454545 251.029653 +L 308.818182 249.37642 +L 309.181818 249.848772 +L 309.545455 249.848772 +L 309.909091 250.793477 +L 310.272727 250.793477 +L 310.636364 251.265829 +L 311 250.793477 +L 311.363636 249.612596 +L 311.727273 249.37642 +L 312.090909 249.612596 +L 312.454545 250.321125 +L 312.818182 249.848772 +L 313.181818 250.793477 +L 313.909091 249.140244 +L 314.272727 248.904067 +L 314.636364 248.904067 +L 315 250.084948 +L 315.363636 247.48701 +L 315.727273 251.502006 +L 316.090909 251.502006 +L 316.454545 249.37642 +L 316.818182 250.557301 +L 317.181818 250.557301 +L 317.545455 248.667891 +L 318.272727 251.265829 +L 319.363636 248.904067 +L 319.727273 249.37642 +L 320.090909 247.959363 +L 320.454545 249.848772 +L 320.818182 251.029653 +L 321.181818 250.321125 +L 321.545455 247.250834 +L 321.909091 248.431715 +L 322.272727 250.793477 +L 322.636364 250.321125 +L 323 248.904067 +L 323.727273 251.502006 +L 324.090909 249.848772 +L 324.454545 250.321125 +L 324.818182 249.848772 +L 325.181818 249.140244 +L 325.545455 250.557301 +L 325.909091 251.502006 +L 326.272727 251.502006 +L 327 250.321125 +L 327.363636 250.321125 +L 327.727273 249.37642 +L 328.090909 251.502006 +L 328.454545 251.029653 +L 328.818182 251.738182 +L 329.181818 250.557301 +L 329.545455 250.084948 +L 329.909091 249.848772 +L 330.272727 248.904067 +L 330.636364 251.265829 +L 331 251.502006 +L 331.363636 249.612596 +L 331.727273 249.848772 +L 332.090909 250.321125 +L 332.454545 250.557301 +L 332.818182 250.084948 +L 333.181818 251.502006 +L 333.545455 251.738182 +L 334.636364 249.37642 +L 335 251.265829 +L 335.363636 250.793477 +L 335.727273 251.502006 +L 336.090909 251.265829 +L 336.454545 250.321125 +L 336.818182 249.848772 +L 337.181818 250.321125 +L 337.545455 249.37642 +L 337.909091 250.793477 +L 338.272727 251.502006 +L 338.636364 250.321125 +L 339 251.265829 +L 339.363636 250.793477 +L 339.727273 250.793477 +L 340.090909 248.904067 +L 340.818182 251.029653 +L 341.181818 251.265829 +L 341.545455 249.848772 +L 341.909091 249.848772 +L 342.272727 250.793477 +L 342.636364 249.848772 +L 343 249.848772 +L 343.363636 251.502006 +L 343.727273 249.848772 +L 344.090909 249.612596 +L 344.454545 250.793477 +L 344.818182 249.848772 +L 345.181818 249.612596 +L 345.545455 251.265829 +L 345.909091 251.738182 +L 346.272727 250.321125 +L 346.636364 249.848772 +L 347 250.793477 +L 347.727273 250.321125 +L 348.090909 250.793477 +L 348.454545 251.502006 +L 348.818182 250.321125 +L 349.181818 250.321125 +L 349.545455 249.612596 +L 349.909091 250.084948 +L 350.272727 250.084948 +L 351 251.738182 +L 351.363636 251.265829 +L 351.727273 250.557301 +L 352.090909 250.557301 +L 352.454545 251.029653 +L 352.818182 250.321125 +L 353.545455 251.502006 +L 353.909091 250.557301 +L 354.272727 250.084948 +L 354.636364 250.321125 +L 355 249.37642 +L 355.363636 249.848772 +L 355.727273 251.738182 +L 356.090909 251.502006 +L 356.454545 250.557301 +L 356.818182 250.084948 +L 357.181818 249.37642 +L 357.545455 249.848772 +L 357.909091 245.833777 +L 358.272727 251.265829 +L 358.636364 250.793477 +L 359.363636 247.723187 +L 359.727273 249.140244 +L 360.090909 250.084948 +L 360.454545 250.557301 +L 360.818182 251.265829 +L 361.181818 251.265829 +L 361.545455 250.321125 +L 361.909091 248.667891 +L 362.272727 250.084948 +L 362.636364 247.48701 +L 363 247.48701 +L 363.363636 251.265829 +L 363.727273 251.502006 +L 364.090909 247.014658 +L 364.454545 247.48701 +L 364.818182 247.723187 +L 365.181818 249.848772 +L 365.545455 250.321125 +L 365.909091 251.265829 +L 366.272727 249.848772 +L 366.636364 248.904067 +L 367 250.084948 +L 367.363636 246.778482 +L 368.090909 250.793477 +L 368.454545 251.502006 +L 368.818182 248.431715 +L 369.545455 250.793477 +L 369.909091 248.667891 +L 370.272727 250.084948 +L 370.636364 251.029653 +L 371 251.265829 +L 371.727273 249.140244 +L 372.454545 250.084948 +L 372.818182 249.848772 +L 373.181818 251.265829 +L 373.545455 251.265829 +L 373.909091 249.37642 +L 374.272727 249.37642 +L 374.636364 249.612596 +L 375 250.557301 +L 375.363636 249.140244 +L 376.090909 251.502006 +L 376.454545 244.41672 +L 376.818182 248.431715 +L 377.181818 248.195539 +L 377.545455 249.140244 +L 377.909091 248.904067 +L 378.272727 251.029653 +L 378.636364 250.321125 +L 379 248.667891 +L 379.363636 248.904067 +L 379.727273 248.904067 +L 380.090909 247.959363 +L 380.818182 251.029653 +L 381.909091 248.904067 +L 382.272727 249.612596 +L 382.636364 249.140244 +L 383 248.904067 +L 383.363636 250.793477 +L 383.727273 251.265829 +L 384.090909 248.667891 +L 384.454545 248.904067 +L 385.181818 250.321125 +L 385.545455 249.848772 +L 385.909091 251.265829 +L 386.272727 251.502006 +L 386.636364 248.667891 +L 387 251.029653 +L 387.727273 248.431715 +L 388.090909 250.793477 +L 388.454545 251.738182 +L 388.818182 250.557301 +L 389.181818 250.793477 +L 389.545455 250.557301 +L 389.909091 249.612596 +L 390.272727 251.265829 +L 390.636364 250.557301 +L 391 251.265829 +L 391.363636 251.265829 +L 391.727273 249.612596 +L 392.090909 249.140244 +L 392.454545 250.557301 +L 392.818182 248.904067 +L 393.545455 251.502006 +L 393.909091 251.738182 +L 394.272727 249.848772 +L 395 250.321125 +L 395.363636 251.029653 +L 396.090909 250.557301 +L 396.454545 251.029653 +L 396.818182 249.848772 +L 397.181818 247.250834 +L 397.545455 250.793477 +L 397.909091 251.029653 +L 398.272727 251.502006 +L 398.636364 250.084948 +L 399 250.084948 +L 399.363636 250.793477 +L 399.727273 250.321125 +L 400.090909 250.557301 +L 400.454545 251.738182 +L 400.818182 251.738182 +L 401.181818 251.265829 +L 401.545455 251.738182 +L 401.909091 251.029653 +L 402.272727 251.738182 +L 402.636364 251.738182 +L 403 250.557301 +L 403.363636 251.029653 +L 403.727273 251.029653 +L 404.090909 250.084948 +L 404.454545 249.848772 +L 404.818182 250.321125 +L 405.181818 249.612596 +L 405.545455 250.793477 +L 405.909091 251.502006 +L 406.272727 248.667891 +L 406.636364 250.321125 +L 407 250.321125 +L 407.363636 249.37642 +L 407.727273 250.084948 +L 408.090909 251.265829 +L 408.454545 251.265829 +L 408.818182 250.557301 +L 409.181818 251.029653 +L 409.545455 250.321125 +L 410.272727 250.321125 +L 410.636364 251.265829 +L 411 250.793477 +L 411.363636 247.014658 +L 411.727273 249.848772 +L 412.090909 250.084948 +L 412.454545 249.37642 +L 412.818182 249.37642 +L 413.181818 251.265829 +L 413.545455 250.793477 +L 413.909091 249.612596 +L 414.272727 251.029653 +L 414.636364 249.37642 +L 415.727273 251.502006 +L 416.090909 250.321125 +L 416.454545 249.848772 +L 416.818182 250.321125 +L 417.181818 248.667891 +L 417.545455 248.904067 +L 417.909091 249.612596 +L 418.272727 251.738182 +L 418.636364 251.029653 +L 419 249.37642 +L 419.363636 250.084948 +L 420.454545 247.723187 +L 420.818182 250.557301 +L 421.181818 251.265829 +L 421.909091 249.140244 +L 422.272727 250.557301 +L 422.636364 249.612596 +L 423 250.321125 +L 423.727273 250.793477 +L 424.090909 249.140244 +L 424.454545 249.848772 +L 425.181818 246.778482 +L 425.545455 247.959363 +L 425.909091 251.029653 +L 426.272727 250.084948 +L 426.636364 249.612596 +L 427 248.195539 +L 427.363636 249.140244 +L 427.727273 250.557301 +L 428.090909 249.612596 +L 428.454545 250.321125 +L 428.818182 251.502006 +L 429.181818 251.265829 +L 429.909091 248.667891 +L 430.272727 248.904067 +L 430.636364 249.848772 +L 431 250.321125 +L 431.363636 251.029653 +L 431.727273 249.37642 +L 432.090909 250.321125 +L 432.454545 250.084948 +L 432.818182 248.667891 +L 433.181818 248.431715 +L 433.545455 251.265829 +L 433.909091 251.029653 +L 434.272727 249.848772 +L 435 248.667891 +L 435.363636 248.904067 +L 436.090909 251.265829 +L 436.454545 250.793477 +L 436.818182 249.140244 +L 437.181818 248.904067 +L 437.545455 250.557301 +L 437.909091 249.612596 +L 438.272727 251.265829 +L 438.636364 251.265829 +L 439 250.793477 +L 439.363636 248.195539 +L 439.727273 249.140244 +L 440.090909 248.667891 +L 440.454545 248.431715 +L 440.818182 250.793477 +L 441.181818 251.738182 +L 441.545455 250.793477 +L 441.909091 248.431715 +L 442.636364 250.557301 +L 443 248.667891 +L 443.363636 250.557301 +L 443.727273 251.265829 +L 444.090909 251.265829 +L 444.454545 249.140244 +L 444.818182 250.321125 +L 445.181818 250.084948 +L 445.909091 250.557301 +L 446.272727 251.029653 +L 446.636364 251.738182 +L 447 249.140244 +L 447.727273 250.084948 +L 448.090909 249.140244 +L 448.454545 251.502006 +L 448.818182 251.029653 +L 449.181818 250.793477 +L 449.545455 250.321125 +L 449.909091 249.37642 +L 450.272727 247.959363 +L 450.636364 247.959363 +L 451.363636 251.502006 +L 452.090909 249.612596 +L 452.818182 249.612596 +L 453.181818 249.140244 +L 453.545455 249.612596 +L 453.909091 251.738182 +L 454.272727 250.321125 +L 454.636364 247.723187 +L 455 249.140244 +L 455.363636 249.612596 +L 455.727273 249.140244 +L 456.454545 251.502006 +L 456.818182 251.029653 +L 457.909091 249.140244 +L 458.272727 250.084948 +L 458.636364 249.612596 +L 459 250.793477 +L 459.363636 251.029653 +L 459.727273 250.793477 +L 460.090909 248.195539 +L 460.454545 249.37642 +L 460.818182 249.612596 +L 461.181818 250.084948 +L 461.545455 251.265829 +L 461.909091 251.265829 +L 462.272727 248.904067 +L 463 250.084948 +L 463.363636 248.195539 +L 463.727273 249.848772 +L 464.090909 250.557301 +L 464.454545 251.738182 +L 464.818182 250.793477 +L 465.181818 250.321125 +L 465.545455 250.793477 +L 465.909091 251.029653 +L 466.272727 250.557301 +L 466.636364 251.738182 +L 467 250.793477 +L 467.363636 248.667891 +L 467.727273 248.904067 +L 468.090909 250.793477 +L 468.454545 249.140244 +L 468.818182 248.431715 +L 469.181818 251.502006 +L 469.545455 250.557301 +L 469.909091 250.557301 +L 470.272727 251.029653 +L 470.636364 250.084948 +L 471 250.084948 +L 471.727273 250.557301 +L 472.090909 250.557301 +L 472.454545 249.612596 +L 472.818182 250.084948 +L 473.181818 249.37642 +L 473.545455 250.321125 +L 473.909091 250.084948 +L 474.272727 251.738182 +L 474.636364 251.265829 +L 475 248.904067 +L 475.363636 248.431715 +L 475.727273 249.140244 +L 476.090909 249.37642 +L 476.454545 250.793477 +L 476.818182 251.738182 +L 477.181818 250.793477 +L 477.545455 249.37642 +L 477.909091 250.084948 +L 478.272727 249.140244 +L 478.636364 250.321125 +L 479 250.321125 +L 479.363636 245.361425 +L 479.727273 245.361425 +L 480.090909 249.37642 +L 480.454545 244.652896 +L 480.818182 241.818782 +L 481.181818 249.37642 +L 481.545455 246.069953 +L 481.909091 243.944367 +L 482.272727 251.029653 +L 482.636364 245.125248 +L 483 241.582605 +L 483.363636 243.708191 +L 483.727273 251.502006 +L 484.090909 245.361425 +L 484.454545 247.250834 +L 484.818182 244.41672 +L 485.181818 250.793477 +L 485.545455 250.557301 +L 485.909091 240.637901 +L 486.272727 248.195539 +L 486.636364 249.612596 +L 487 245.597601 +L 487.363636 246.778482 +L 487.727273 248.904067 +L 488.454545 248.431715 +L 488.818182 249.848772 +L 489.545455 251.029653 +L 489.909091 251.265829 +L 490.272727 249.37642 +L 490.636364 248.431715 +L 491 249.140244 +L 491.363636 250.321125 +L 491.727273 249.37642 +L 492.090909 251.502006 +L 492.454545 251.265829 +L 492.818182 250.557301 +L 493.181818 248.667891 +L 493.545455 248.667891 +L 493.909091 250.321125 +L 494.272727 249.612596 +L 494.636364 251.029653 +L 495 250.321125 +L 495.363636 250.084948 +L 495.727273 249.612596 +L 496.090909 249.612596 +L 496.454545 248.431715 +L 496.818182 248.667891 +L 497.181818 251.502006 +L 497.545455 251.265829 +L 497.909091 250.084948 +L 498.272727 249.848772 +L 498.636364 248.431715 +L 499.363636 250.557301 +L 499.727273 251.029653 +L 500.090909 251.029653 +L 500.454545 249.140244 +L 500.818182 249.37642 +L 501.545455 251.265829 +L 501.909091 249.848772 +L 502.272727 251.265829 +L 502.636364 251.502006 +L 503 250.557301 +L 503.363636 250.084948 +L 503.727273 250.084948 +L 504.090909 250.793477 +L 504.454545 250.557301 +L 504.818182 251.502006 +L 505.545455 249.848772 +L 505.909091 249.848772 +L 506.272727 250.557301 +L 506.636364 250.557301 +L 507 250.793477 +L 507.363636 251.265829 +L 507.727273 251.265829 +L 508.090909 248.667891 +L 508.454545 248.667891 +L 508.818182 248.431715 +L 509.545455 250.793477 +L 509.909091 251.029653 +L 510.272727 249.612596 +L 510.636364 250.557301 +L 511 248.904067 +L 511.363636 248.195539 +L 511.727273 249.37642 +L 512.090909 251.502006 +L 512.454545 251.502006 +L 512.818182 248.904067 +L 513.181818 247.250834 +L 513.909091 248.904067 +L 514.272727 250.321125 +L 514.636364 251.265829 +L 515 250.793477 +L 515.363636 248.904067 +L 515.727273 250.084948 +L 516.090909 249.848772 +L 516.818182 249.848772 +L 517.181818 251.029653 +L 517.545455 251.029653 +L 517.909091 248.667891 +L 518.272727 247.250834 +L 518.636364 249.37642 +L 519 250.084948 +L 519.363636 249.848772 +L 519.727273 251.265829 +L 520.818182 248.195539 +L 521.181818 248.904067 +L 521.545455 248.431715 +L 521.909091 251.502006 +L 522.272727 251.029653 +L 522.636364 251.265829 +L 523 249.140244 +L 523.363636 249.140244 +L 523.727273 249.848772 +L 524.090909 249.37642 +L 524.454545 249.37642 +L 524.818182 250.557301 +L 525.181818 250.793477 +L 525.545455 249.37642 +L 525.909091 249.37642 +L 526.272727 249.848772 +L 526.636364 249.140244 +L 527 249.612596 +L 527.363636 250.793477 +L 527.727273 250.321125 +L 528.090909 249.140244 +L 528.454545 248.904067 +L 528.818182 249.37642 +L 529.181818 249.140244 +L 529.545455 250.557301 +L 529.909091 251.502006 +L 530.636364 249.848772 +L 531 249.848772 +L 531.363636 249.37642 +L 531.727273 247.959363 +L 532.454545 251.502006 +L 532.818182 251.502006 +L 533.181818 250.793477 +L 533.545455 251.265829 +L 533.909091 250.321125 +L 534.272727 251.738182 +L 534.636364 250.793477 +L 535 251.502006 +L 535.363636 251.265829 +L 535.727273 251.265829 +L 536.090909 250.321125 +L 536.454545 248.904067 +L 536.818182 248.904067 +L 537.181818 249.140244 +L 537.545455 250.557301 +L 537.909091 250.084948 +L 538.272727 248.667891 +L 539 249.612596 +L 539.363636 250.793477 +L 539.727273 250.321125 +L 540.090909 251.029653 +L 540.454545 251.265829 +L 541.181818 249.612596 +L 541.545455 249.37642 +L 541.909091 249.848772 +L 542.272727 249.612596 +L 542.636364 248.904067 +L 543 251.502006 +L 543.363636 251.029653 +L 543.727273 248.667891 +L 544.090909 250.084948 +L 544.454545 249.612596 +L 544.818182 250.793477 +L 545.181818 250.793477 +L 545.545455 251.265829 +L 546.272727 248.904067 +L 546.636364 248.904067 +L 547 248.195539 +L 547.363636 249.612596 +L 547.727273 250.084948 +L 548.090909 251.265829 +L 548.454545 248.904067 +L 548.818182 248.904067 +L 549.181818 249.612596 +L 549.545455 249.37642 +L 549.909091 250.557301 +L 550.272727 250.321125 +L 550.636364 250.321125 +L 551 250.557301 +L 551.363636 249.37642 +L 552.090909 250.321125 +L 552.454545 249.612596 +L 552.818182 251.265829 +L 553.181818 250.793477 +L 553.545455 250.557301 +L 553.909091 249.612596 +L 554.272727 249.37642 +L 554.636364 250.321125 +L 555 249.37642 +L 555.363636 250.793477 +L 555.727273 250.557301 +L 556.090909 249.612596 +L 556.454545 250.321125 +L 556.818182 249.140244 +L 557.181818 250.321125 +L 557.545455 250.084948 +L 557.909091 251.265829 +L 558.272727 251.265829 +L 558.636364 250.793477 +L 559 247.959363 +L 559.363636 248.195539 +L 559.727273 249.37642 +L 560.090909 248.431715 +L 560.454545 251.029653 +L 560.818182 251.029653 +L 561.181818 248.195539 +L 561.545455 248.431715 +L 561.909091 247.48701 +L 562.272727 248.904067 +L 563 251.029653 +L 563.363636 250.793477 +L 563.727273 248.431715 +L 564.090909 249.37642 +L 564.454545 248.431715 +L 564.818182 249.612596 +L 565.181818 249.848772 +L 565.545455 251.265829 +L 565.909091 248.195539 +L 566.272727 250.084948 +L 566.636364 249.140244 +L 567 248.667891 +L 567.363636 250.084948 +L 568.090909 251.502006 +L 568.454545 251.738182 +L 568.818182 250.793477 +L 569.181818 251.265829 +L 569.545455 250.557301 +L 569.909091 249.140244 +L 570.272727 248.904067 +L 571 250.557301 +L 571.363636 250.084948 +L 571.727273 250.793477 +L 572.090909 251.029653 +L 572.454545 249.140244 +L 572.818182 248.904067 +L 573.181818 250.793477 +L 573.545455 249.848772 +L 573.909091 250.321125 +L 574.272727 251.502006 +L 574.636364 250.793477 +L 575 249.140244 +L 575.363636 248.667891 +L 575.727273 250.793477 +L 576.090909 250.321125 +L 576.454545 251.029653 +L 576.818182 251.265829 +L 577.181818 251.265829 +L 577.545455 248.431715 +L 577.909091 248.904067 +L 578.636364 250.321125 +L 579 250.084948 +L 579.363636 251.265829 +L 579.727273 251.029653 +L 580.090909 251.502006 +L 580.454545 250.084948 +L 580.818182 250.793477 +L 581.181818 250.084948 +L 581.545455 250.793477 +L 581.909091 251.029653 +L 582.272727 251.029653 +L 582.636364 249.612596 +L 583 249.848772 +L 583.363636 248.904067 +L 583.727273 250.321125 +L 584.090909 250.793477 +L 584.454545 251.502006 +L 584.818182 251.029653 +L 585.181818 250.321125 +L 585.545455 250.321125 +L 586.272727 250.793477 +L 586.636364 251.265829 +L 587 250.557301 +L 587.363636 249.140244 +L 587.727273 250.321125 +L 588.454545 249.37642 +L 588.818182 249.848772 +L 589.181818 251.502006 +L 589.545455 251.265829 +L 589.909091 250.793477 +L 590.272727 251.029653 +L 590.636364 248.904067 +L 591 250.557301 +L 591.363636 250.321125 +L 591.727273 251.029653 +L 592.090909 251.029653 +L 592.454545 250.557301 +L 592.818182 249.848772 +L 593.181818 250.793477 +L 593.545455 251.265829 +L 593.909091 250.793477 +L 594.272727 251.738182 +L 594.636364 250.084948 +L 595 249.612596 +L 595.363636 248.667891 +L 596.818182 251.265829 +L 597.181818 251.502006 +L 597.545455 249.37642 +L 597.909091 251.029653 +L 598.272727 249.848772 +L 598.636364 250.793477 +L 599 250.321125 +L 599.363636 250.793477 +L 599.727273 250.793477 +L 600.090909 249.612596 +L 600.454545 250.793477 +L 600.818182 248.667891 +L 601.181818 249.848772 +L 601.545455 248.904067 +L 601.909091 251.502006 +L 603 250.084948 +L 603.363636 250.557301 +L 603.727273 249.37642 +L 604.090909 249.848772 +L 604.454545 251.502006 +L 604.818182 251.738182 +L 605.181818 250.321125 +L 605.545455 250.557301 +L 606.272727 250.084948 +L 606.636364 250.557301 +L 607 251.502006 +L 607.363636 249.140244 +L 607.727273 249.612596 +L 608.090909 248.431715 +L 609.181818 251.265829 +L 609.545455 251.738182 +L 609.909091 250.321125 +L 610.272727 249.848772 +L 610.636364 248.667891 +L 611 250.084948 +L 611.727273 251.738182 +L 612.090909 251.502006 +L 612.454545 250.084948 +L 612.818182 249.848772 +L 613.181818 248.904067 +L 613.545455 247.250834 +L 614.272727 250.557301 +L 615 246.778482 +L 615.363636 247.959363 +L 615.727273 247.723187 +L 616.090909 246.306129 +L 616.454545 248.904067 +L 616.818182 250.321125 +L 617.181818 249.848772 +L 617.545455 249.140244 +L 617.909091 249.848772 +L 618.272727 249.140244 +L 618.636364 249.140244 +L 619 251.029653 +L 619.363636 251.265829 +L 619.727273 251.265829 +L 620.090909 251.502006 +L 620.454545 248.667891 +L 620.818182 250.084948 +L 621.181818 250.321125 +L 621.545455 249.848772 +L 621.909091 250.793477 +L 622.272727 251.265829 +L 622.636364 250.321125 +L 622.636364 250.321125 +" clip-path="url(#p10b7ab2e7a)" style="fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square"/> - + - + @@ -5602,13 +5971,13 @@ z - + - + @@ -5636,10 +6005,10 @@ L 322.391406 183.296562 - + - + diff --git a/doc/source/tracking/traffic/traffic_data_mgmt.py b/doc/source/tracking/traffic/traffic_data_mgmt.py index 0d0a6af9c..5cdf0672b 100644 --- a/doc/source/tracking/traffic/traffic_data_mgmt.py +++ b/doc/source/tracking/traffic/traffic_data_mgmt.py @@ -1,5 +1,6 @@ -import matplotlib.pyplot as plt import os + +import matplotlib.pyplot as plt import pandas as pd cwd = os.getcwd() diff --git a/doc/source/tracking/traffic/views.csv b/doc/source/tracking/traffic/views.csv index f645da225..ac4390674 100644 --- a/doc/source/tracking/traffic/views.csv +++ b/doc/source/tracking/traffic/views.csv @@ -1277,3 +1277,121 @@ _date,total_views,unique_views 2024-05-10,83,8 2024-05-11,4,3 2024-05-12,13,4 +2024-05-13,11,2 +2024-05-14,9,8 +2024-05-15,13,5 +2024-05-16,77,8 +2024-05-17,26,5 +2024-05-18,14,4 +2024-05-19,23,4 +2024-05-20,66,10 +2024-05-21,47,9 +2024-05-22,25,13 +2024-05-23,27,7 +2024-05-24,10,5 +2024-05-25,4,2 +2024-05-26,15,4 +2024-05-27,17,7 +2024-05-28,19,7 +2024-05-29,17,6 +2024-05-30,22,5 +2024-05-31,3,3 +2024-06-01,45,6 +2024-06-03,39,12 +2024-06-04,20,7 +2024-06-05,60,9 +2024-06-06,98,11 +2024-06-07,64,9 +2024-06-08,2,2 +2024-06-09,4,3 +2024-06-10,22,5 +2024-06-11,4,4 +2024-06-12,42,13 +2024-06-13,47,6 +2024-06-14,11,7 +2024-06-15,49,4 +2024-06-16,5,4 +2024-06-17,28,6 +2024-06-18,73,9 +2024-06-19,5,5 +2024-06-20,23,3 +2024-06-21,25,5 +2024-06-22,1,1 +2024-06-23,14,8 +2024-06-24,44,10 +2024-06-25,46,14 +2024-06-26,22,11 +2024-06-27,56,8 +2024-06-28,11,4 +2024-06-29,3,3 +2024-06-30,56,2 +2024-07-01,40,11 +2024-07-02,31,4 +2024-07-03,116,9 +2024-07-04,24,5 +2024-07-05,15,7 +2024-07-06,15,5 +2024-07-07,25,5 +2024-07-08,41,10 +2024-07-09,39,5 +2024-07-10,50,14 +2024-07-11,33,9 +2024-07-12,62,13 +2024-07-13,13,2 +2024-07-14,20,4 +2024-07-15,7,6 +2024-07-16,9,8 +2024-07-17,55,6 +2024-07-18,42,11 +2024-07-19,46,9 +2024-07-20,5,2 +2024-07-21,1,1 +2024-07-22,10,7 +2024-07-23,70,6 +2024-07-24,61,7 +2024-07-25,23,8 +2024-07-26,13,6 +2024-07-28,3,2 +2024-07-29,24,12 +2024-07-30,43,10 +2024-07-31,57,15 +2024-08-01,40,11 +2024-08-02,40,6 +2024-08-03,13,3 +2024-08-04,13,1 +2024-08-05,22,7 +2024-08-06,29,9 +2024-08-07,99,14 +2024-08-08,68,8 +2024-08-09,31,5 +2024-08-10,2,1 +2024-08-11,2,2 +2024-08-12,109,8 +2024-08-13,389,9 +2024-08-14,156,13 +2024-08-15,86,20 +2024-08-16,141,13 +2024-08-17,37,6 +2024-08-18,51,13 +2024-08-19,178,22 +2024-08-20,139,17 +2024-08-21,188,18 +2024-08-22,118,24 +2024-08-23,79,13 +2024-08-24,11,7 +2024-08-25,40,9 +2024-08-26,59,12 +2024-08-27,97,9 +2024-08-28,70,12 +2024-08-29,73,12 +2024-08-30,33,4 +2024-08-31,14,3 +2024-09-01,3,3 +2024-09-02,4,2 +2024-09-03,46,14 +2024-09-04,19,8 +2024-09-05,72,7 +2024-09-06,111,9 +2024-09-07,28,5 +2024-09-08,23,3 +2024-09-09,44,7 diff --git a/doc/source/user_guide/changelog/index.rst b/doc/source/user_guide/changelog/index.rst index 927bc497f..491de3708 100644 --- a/doc/source/user_guide/changelog/index.rst +++ b/doc/source/user_guide/changelog/index.rst @@ -7,9 +7,17 @@ This is the list of changes made to icepyx in between each release. Full details can be found in the `commit logs `_. -Latest Release (Version 1.2.0) +Latest Release (Version 1.3.0) ------------------------------ +.. toctree:: + :maxdepth: 2 + + v1.3.0 + +Version 1.2.0 +------------- + .. toctree:: :maxdepth: 2 diff --git a/doc/source/user_guide/changelog/v1.3.0.rst b/doc/source/user_guide/changelog/v1.3.0.rst new file mode 100644 index 000000000..142b0eb27 --- /dev/null +++ b/doc/source/user_guide/changelog/v1.3.0.rst @@ -0,0 +1,81 @@ +What's new in 1.3.0 (13 September 2024) +--------------------------------------- + +These are the changes in icepyx 1.3.0 See :ref:`release` for a full changelog +including other versions of icepyx. + +.. warning:: + This is anticipated to be the last release in v1 of icepyx. + + NSIDC (the NASA DAAC that hosts ICESat-2 data) is transitioning their + API endpoint from the on-premises EGI system to the cloud-based Harmony services. + icepyx is being updated to access these new services; the only change users + will experience concerns services that are no longer available (e.g. reformatting). + + The developers plan to use this version change to implement additional breaking + changes concerning the Query module, transitioning it's functionality to use + the earthaccess library instead. + + Find more details on all these changes, including their progress, on GitHub issues and discussions. + + +Bug fixes +~~~~~~~~~ + +- Bugfix: catch multiple types of exceptions (#560) + + +Deprecations +~~~~~~~~~~~~ + +- Drop support for Python 3.7 and 3.8 (#608) +- Add v1.x deprecation warning (#603) + + +Maintenance +^^^^^^^^^^^ + +- Avoid running tests that require creds on PRs (#563) + + - enables PRs from forks to pass CI tests and be merged + +- Skip linting and formatting Jupyter Notebooks for now (#567) +- Keep GitHub Actions up to date with GitHub's Dependabot (#555) +- Bump the github-actions group with 3 updates (#568) +- Add codespell spelling/typo linter and fix errors (#556) +- Validate pyproject.toml (#557) +- Enable currently-ignored linting rules E721, E722, F403 (#573) +- Add ruff rules C4 to check comprehensions (#570) +- Add ruff rules SIM to simplify Python code (#572) +- More ruff & pre-commit rules (#546) +- Fix minor typo (#589) +- Extract constant URLs to own module (#591) +- Clarify some comments / docstrings (#592) +- Migrate unit and integration tests from TravisCI to GitHub Actions (#580) +- Reinstate test_download_granules_without_subsetting (#581) + + - Ensure that granules can be ordered from NSIDC and downloaded with the `subset=False` option. + - Also fix a possible race condition in case the NSIDC order status is completed right at the start (e.g. when order was cached/done already). + +- Bump sangonzal/repository-traffic-action from 0.1.5 to 1 in the github-actions group (#596) +- [pre-commit.ci] pre-commit autoupdate (#597) +- bump sangonzal/repository-traffic-action version to latest working one (fixes #596) (#601) +- Replace integration test review trigger with manual trigger (#595) + + +Documentation +^^^^^^^^^^^^^ + +- Update viz doc to clarify its current status (partial functionality - incompatible with OA API changes) (#540) +- Add quickstart to README (#549) +- docs: add cclauss as a contributor for maintenance and review (#583) +- docs: add jrenrut as a contributor for bug, and code (#586) +- docs: add mfisher87 as a contributor for bug, code, and 4 more (#585) +- Tweak format and wording of contributor doc (#566) +- [docs] traffic updates May-Aug 2024 (#606) + + +Contributors +~~~~~~~~~~~~ + +.. contributors:: v1.2.0..v1.3.0|HEAD diff --git a/doc/source/user_guide/documentation/classes_dev_uml.svg b/doc/source/user_guide/documentation/classes_dev_uml.svg index f59739433..9084ffd70 100644 --- a/doc/source/user_guide/documentation/classes_dev_uml.svg +++ b/doc/source/user_guide/documentation/classes_dev_uml.svg @@ -4,11 +4,11 @@ - + classes_dev_uml - + icepyx.quest.dataset_scripts.argo.Argo @@ -87,316 +87,309 @@ icepyx.core.auth.EarthdataAuthMixin - -EarthdataAuthMixin - -_auth : NoneType -_s3_initial_ts : NoneType, datetime -_s3login_credentials : NoneType -_session : NoneType -auth -s3login_credentials -session - -__init__(auth) -__str__() -earthdata_login(uid, email, s3token): None + +EarthdataAuthMixin + +_auth : NoneType +_s3_initial_ts : NoneType, datetime +_s3login_credentials : NoneType +_session : NoneType +auth +s3login_credentials +session + +__init__(auth) +__str__() +earthdata_login(uid, email, s3token): None icepyx.core.query.GenQuery - -GenQuery - -_spatial -_temporal -dates -end_time -spatial -spatial_extent -start_time -temporal - -__init__(spatial_extent, date_range, start_time, end_time) -__str__() + +GenQuery + +_spatial +_temporal +dates +end_time +spatial +spatial_extent +start_time +temporal + +__init__(spatial_extent, date_range, start_time, end_time) +__str__() icepyx.core.granules.Granules - -Granules - -avail : list -orderIDs : list - -__init__() -download(verbose, path, restart) -get_avail(CMRparams, reqparams, cloud) -place_order(CMRparams, reqparams, subsetparams, verbose, subset, geom_filepath) + +Granules + +avail : list +orderIDs : list + +__init__() +download(verbose, path, restart) +get_avail(CMRparams, reqparams, cloud) +place_order(CMRparams, reqparams, subsetparams, verbose, subset, geom_filepath) icepyx.core.granules.Granules->icepyx.core.auth.EarthdataAuthMixin - - + + icepyx.core.query.Query - -Query - -CMRparams -_CMRparams -_about_product -_cust_options : dict -_cycles : list -_granules -_order_vars -_prod : NoneType, str -_readable_granule_name : list -_reqparams -_subsetparams : NoneType -_tracks : list -_version -cycles -dataset -granules -order_vars -product -product_version -reqparams -tracks - -__init__(product, spatial_extent, date_range, start_time, end_time, version, cycles, tracks, auth) -__str__() -avail_granules(ids, cycles, tracks, cloud) -download_granules(path, verbose, subset, restart) -latest_version() -order_granules(verbose, subset, email) -product_all_info() -product_summary_info() -show_custom_options(dictview) -subsetparams() -visualize_elevation() -visualize_spatial_extent() + +Query + +CMRparams +_CMRparams +_about_product +_cust_options : dict +_cycles : list +_granules +_order_vars +_prod : NoneType, str +_readable_granule_name : list +_reqparams +_subsetparams : NoneType +_tracks : list +_version +cycles +dataset +granules +order_vars +product +product_version +reqparams +tracks + +__init__(product, spatial_extent, date_range, start_time, end_time, version, cycles, tracks, auth) +__str__() +avail_granules(ids, cycles, tracks, cloud) +download_granules(path, verbose, subset, restart) +latest_version() +order_granules(verbose, subset, email) +product_all_info() +product_summary_info() +show_custom_options(dictview) +subsetparams() +visualize_elevation() +visualize_spatial_extent() icepyx.core.granules.Granules->icepyx.core.query.Query - - -_granules - - - -icepyx.core.granules.Granules->icepyx.core.query.Query - - -_granules + + +_granules icepyx.core.icesat2data.Icesat2Data - -Icesat2Data - - -__init__() + +Icesat2Data + + +__init__() icepyx.core.exceptions.NsidcQueryError - -NsidcQueryError - -errmsg -msgtxt : str - -__init__(errmsg, msgtxt) -__str__() + +NsidcQueryError + +errmsg +msgtxt : str + +__init__(errmsg, msgtxt) +__str__() icepyx.core.exceptions.QueryError - -QueryError - - - + +QueryError + + + icepyx.core.exceptions.NsidcQueryError->icepyx.core.exceptions.QueryError - - + + icepyx.core.APIformatting.Parameters - -Parameters - -_fmted_keys : NoneType, dict -_poss_keys : dict -_reqtype : NoneType, str -fmted_keys -partype -poss_keys - -__init__(partype, values, reqtype) -_check_valid_keys() -_get_possible_keys() -build_params() -check_req_values() -check_values() + +Parameters + +_fmted_keys : NoneType, dict +_poss_keys : dict +_reqtype : NoneType, str +fmted_keys +partype +poss_keys + +__init__(partype, values, reqtype) +_check_valid_keys() +_get_possible_keys() +build_params() +check_req_values() +check_values() icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_CMRparams + + +_CMRparams icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_reqparams + + +_reqparams icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_subsetparams + + +_subsetparams icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_subsetparams + + +_subsetparams icepyx.core.query.Query->icepyx.core.auth.EarthdataAuthMixin - - + + icepyx.core.query.Query->icepyx.core.query.GenQuery - - + + icepyx.quest.quest.Quest - -Quest - -datasets : dict - -__init__(spatial_extent, date_range, start_time, end_time, proj) -__str__() -add_argo(params, presRange): None -add_icesat2(product, start_time, end_time, version, cycles, tracks, files): None -download_all(path) -save_all(path) -search_all() + +Quest + +datasets : dict + +__init__(spatial_extent, date_range, start_time, end_time, proj) +__str__() +add_argo(params, presRange): None +add_icesat2(product, start_time, end_time, version, cycles, tracks, files): None +download_all(path) +save_all(path) +search_all() icepyx.quest.quest.Quest->icepyx.core.query.GenQuery - - + + icepyx.core.read.Read - -Read - -_filelist -_out_obj : Dataset -_product -_read_vars -filelist -is_s3 -product -vars - -__init__(data_source, glob_kwargs, out_obj_type, product, filename_pattern, catalog) -_add_vars_to_ds(is2ds, ds, grp_path, wanted_groups_tiered, wanted_dict) -_build_dataset_template(file) -_build_single_file_dataset(file, groups_list) -_combine_nested_vars(is2ds, ds, grp_path, wanted_dict) -_read_single_grp(file, grp_path) -load() + +Read + +_filelist +_out_obj : Dataset +_product +_read_vars +filelist +is_s3 +product +vars + +__init__(data_source, glob_kwargs, out_obj_type, product, filename_pattern, catalog) +_add_vars_to_ds(is2ds, ds, grp_path, wanted_groups_tiered, wanted_dict) +_build_dataset_template(file) +_build_single_file_dataset(file, groups_list) +_combine_nested_vars(is2ds, ds, grp_path, wanted_dict) +_read_single_grp(file, grp_path) +load() icepyx.core.read.Read->icepyx.core.auth.EarthdataAuthMixin - - + + icepyx.core.spatial.Spatial - -Spatial - -_ext_type : str -_gdf_spat : GeoDataFrame -_geom_file : NoneType -_spatial_ext -_xdateln -extent -extent_as_gdf -extent_file -extent_type - -__init__(spatial_extent) -__str__() -fmt_for_CMR() -fmt_for_EGI() + +Spatial + +_ext_type : str +_gdf_spat : GeoDataFrame +_geom_file : NoneType +_spatial_ext +_xdateln +extent +extent_as_gdf +extent_file +extent_type + +__init__(spatial_extent) +__str__() +fmt_for_CMR() +fmt_for_EGI() - + icepyx.core.spatial.Spatial->icepyx.core.query.GenQuery - - -_spatial + + +_spatial - + icepyx.core.spatial.Spatial->icepyx.core.query.GenQuery - - -_spatial + + +_spatial icepyx.core.temporal.Temporal - -Temporal - -_end : datetime -_start : datetime -end -start - -__init__(date_range, start_time, end_time) -__str__() + +Temporal + +_end : datetime +_start : datetime +end +start + +__init__(date_range, start_time, end_time) +__str__() - + icepyx.core.temporal.Temporal->icepyx.core.query.GenQuery - - -_temporal + + +_temporal @@ -427,57 +420,57 @@ icepyx.core.variables.Variables->icepyx.core.auth.EarthdataAuthMixin - - + + - + icepyx.core.variables.Variables->icepyx.core.query.Query - - -_order_vars + + +_order_vars - + icepyx.core.variables.Variables->icepyx.core.query.Query - - -_order_vars + + +_order_vars - + icepyx.core.variables.Variables->icepyx.core.read.Read - - -_read_vars + + +_read_vars - + icepyx.core.variables.Variables->icepyx.core.read.Read - - -_read_vars + + +_read_vars icepyx.core.visualization.Visualize - -Visualize - -bbox : list -cycles : NoneType -date_range : NoneType -product : NoneType, str -tracks : NoneType - -__init__(query_obj, product, spatial_extent, date_range, cycles, tracks) -generate_OA_parameters(): list -grid_bbox(binsize): list -make_request(base_url, payload) -parallel_request_OA(): da.array -query_icesat2_filelist(): tuple -request_OA_data(paras): da.array -viz_elevation(): (hv.DynamicMap, hv.Layout) + +Visualize + +bbox : list +cycles : NoneType +date_range : NoneType +product : NoneType, str +tracks : NoneType + +__init__(query_obj, product, spatial_extent, date_range, cycles, tracks) +generate_OA_parameters(): list +grid_bbox(binsize): list +make_request(base_url, payload) +parallel_request_OA(): da.array +query_icesat2_filelist(): tuple +request_OA_data(paras): da.array +viz_elevation(): (hv.DynamicMap, hv.Layout) diff --git a/doc/source/user_guide/documentation/classes_user_uml.svg b/doc/source/user_guide/documentation/classes_user_uml.svg index d5c17c066..8b1273598 100644 --- a/doc/source/user_guide/documentation/classes_user_uml.svg +++ b/doc/source/user_guide/documentation/classes_user_uml.svg @@ -4,11 +4,11 @@ - + classes_user_uml - + icepyx.core.auth.AuthenticationError @@ -30,313 +30,306 @@ icepyx.core.auth.EarthdataAuthMixin - -EarthdataAuthMixin - -auth -s3login_credentials -session - -earthdata_login(uid, email, s3token): None + +EarthdataAuthMixin + +auth +s3login_credentials +session + +earthdata_login(uid, email, s3token): None icepyx.core.query.GenQuery - -GenQuery - -dates -end_time -spatial -spatial_extent -start_time -temporal - - + +GenQuery + +dates +end_time +spatial +spatial_extent +start_time +temporal + + icepyx.core.granules.Granules - -Granules - -avail : list -orderIDs : list - -download(verbose, path, restart) -get_avail(CMRparams, reqparams, cloud) -place_order(CMRparams, reqparams, subsetparams, verbose, subset, geom_filepath) + +Granules + +avail : list +orderIDs : list + +download(verbose, path, restart) +get_avail(CMRparams, reqparams, cloud) +place_order(CMRparams, reqparams, subsetparams, verbose, subset, geom_filepath) icepyx.core.granules.Granules->icepyx.core.auth.EarthdataAuthMixin - - + + icepyx.core.query.Query - -Query - -CMRparams -cycles -dataset -granules -order_vars -product -product_version -reqparams -tracks - -avail_granules(ids, cycles, tracks, cloud) -download_granules(path, verbose, subset, restart) -latest_version() -order_granules(verbose, subset, email) -product_all_info() -product_summary_info() -show_custom_options(dictview) -subsetparams() -visualize_elevation() -visualize_spatial_extent() + +Query + +CMRparams +cycles +dataset +granules +order_vars +product +product_version +reqparams +tracks + +avail_granules(ids, cycles, tracks, cloud) +download_granules(path, verbose, subset, restart) +latest_version() +order_granules(verbose, subset, email) +product_all_info() +product_summary_info() +show_custom_options(dictview) +subsetparams() +visualize_elevation() +visualize_spatial_extent() icepyx.core.granules.Granules->icepyx.core.query.Query - - -_granules - - - -icepyx.core.granules.Granules->icepyx.core.query.Query - - -_granules + + +_granules icepyx.core.icesat2data.Icesat2Data - -Icesat2Data - - - + +Icesat2Data + + + icepyx.core.exceptions.NsidcQueryError - -NsidcQueryError - -errmsg -msgtxt : str - - + +NsidcQueryError + +errmsg +msgtxt : str + + icepyx.core.exceptions.QueryError - -QueryError - - - + +QueryError + + + icepyx.core.exceptions.NsidcQueryError->icepyx.core.exceptions.QueryError - - + + icepyx.core.APIformatting.Parameters - -Parameters - -fmted_keys -partype -poss_keys - -build_params() -check_req_values() -check_values() + +Parameters + +fmted_keys +partype +poss_keys + +build_params() +check_req_values() +check_values() icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_CMRparams + + +_CMRparams icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_reqparams + + +_reqparams icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_subsetparams + + +_subsetparams icepyx.core.APIformatting.Parameters->icepyx.core.query.Query - - -_subsetparams + + +_subsetparams icepyx.core.query.Query->icepyx.core.auth.EarthdataAuthMixin - - + + icepyx.core.query.Query->icepyx.core.query.GenQuery - - + + icepyx.core.read.Read - -Read - -filelist -is_s3 -product -vars - -load() + +Read + +filelist +is_s3 +product +vars + +load() icepyx.core.read.Read->icepyx.core.auth.EarthdataAuthMixin - - + + icepyx.core.spatial.Spatial - -Spatial - -extent -extent_as_gdf -extent_file -extent_type - -fmt_for_CMR() -fmt_for_EGI() + +Spatial + +extent +extent_as_gdf +extent_file +extent_type + +fmt_for_CMR() +fmt_for_EGI() - + icepyx.core.spatial.Spatial->icepyx.core.query.GenQuery - - -_spatial + + +_spatial - + icepyx.core.spatial.Spatial->icepyx.core.query.GenQuery - - -_spatial + + +_spatial icepyx.core.temporal.Temporal - -Temporal - -end -start - - + +Temporal + +end +start + + - + icepyx.core.temporal.Temporal->icepyx.core.query.GenQuery - - -_temporal + + +_temporal icepyx.core.variables.Variables - -Variables - -path -product -version -wanted : NoneType, dict - -append(defaults, var_list, beam_list, keyword_list) -avail(options, internal) -parse_var_list(varlist, tiered, tiered_vars) -remove(all, var_list, beam_list, keyword_list) + +Variables + +path +product +version +wanted : NoneType, dict + +append(defaults, var_list, beam_list, keyword_list) +avail(options, internal) +parse_var_list(varlist, tiered, tiered_vars) +remove(all, var_list, beam_list, keyword_list) icepyx.core.variables.Variables->icepyx.core.auth.EarthdataAuthMixin - - + + - + icepyx.core.variables.Variables->icepyx.core.query.Query - - -_order_vars + + +_order_vars - + icepyx.core.variables.Variables->icepyx.core.query.Query - - -_order_vars + + +_order_vars - + icepyx.core.variables.Variables->icepyx.core.read.Read - - -_read_vars + + +_read_vars - + icepyx.core.variables.Variables->icepyx.core.read.Read - - -_read_vars + + +_read_vars icepyx.core.visualization.Visualize - -Visualize - -bbox : list -cycles : NoneType -date_range : NoneType -product : NoneType, str -tracks : NoneType - -generate_OA_parameters(): list -grid_bbox(binsize): list -make_request(base_url, payload) -parallel_request_OA(): da.array -query_icesat2_filelist(): tuple -request_OA_data(paras): da.array -viz_elevation(): (hv.DynamicMap, hv.Layout) + +Visualize + +bbox : list +cycles : NoneType +date_range : NoneType +product : NoneType, str +tracks : NoneType + +generate_OA_parameters(): list +grid_bbox(binsize): list +make_request(base_url, payload) +parallel_request_OA(): da.array +query_icesat2_filelist(): tuple +request_OA_data(paras): da.array +viz_elevation(): (hv.DynamicMap, hv.Layout) diff --git a/doc/source/user_guide/documentation/packages_user_uml.svg b/doc/source/user_guide/documentation/packages_user_uml.svg index 029a13015..2cfe26a67 100644 --- a/doc/source/user_guide/documentation/packages_user_uml.svg +++ b/doc/source/user_guide/documentation/packages_user_uml.svg @@ -4,172 +4,190 @@ - + packages_user_uml - + icepyx.core - -icepyx.core + +icepyx.core icepyx.core.APIformatting - -icepyx.core.APIformatting + +icepyx.core.APIformatting icepyx.core.auth - -icepyx.core.auth + +icepyx.core.auth icepyx.core.exceptions - -icepyx.core.exceptions + +icepyx.core.exceptions icepyx.core.auth->icepyx.core.exceptions - - + + icepyx.core.granules - -icepyx.core.granules + +icepyx.core.granules icepyx.core.granules->icepyx.core.auth - - + + + + + +icepyx.core.urls + +icepyx.core.urls + + + +icepyx.core.granules->icepyx.core.urls + + icepyx.core.icesat2data - -icepyx.core.icesat2data + +icepyx.core.icesat2data - + icepyx.core.icesat2data->icepyx.core.exceptions - - + + icepyx.core.is2ref - -icepyx.core.is2ref + +icepyx.core.is2ref + + + +icepyx.core.is2ref->icepyx.core.urls + + icepyx.core.query - -icepyx.core.query + +icepyx.core.query - + icepyx.core.query->icepyx.core.auth - - + + - + icepyx.core.query->icepyx.core.exceptions - - + + - + icepyx.core.query->icepyx.core.granules - - + + - + icepyx.core.variables - -icepyx.core.variables + +icepyx.core.variables - + icepyx.core.query->icepyx.core.variables - - + + - + icepyx.core.visualization - -icepyx.core.visualization + +icepyx.core.visualization - + icepyx.core.query->icepyx.core.visualization - - + + icepyx.core.read - -icepyx.core.read + +icepyx.core.read - + icepyx.core.read->icepyx.core.auth - - + + - + icepyx.core.read->icepyx.core.exceptions - - + + - + icepyx.core.read->icepyx.core.variables - - + + icepyx.core.spatial - -icepyx.core.spatial + +icepyx.core.spatial icepyx.core.temporal - -icepyx.core.temporal + +icepyx.core.temporal - + icepyx.core.validate_inputs - -icepyx.core.validate_inputs + +icepyx.core.validate_inputs - + icepyx.core.variables->icepyx.core.auth - - + + - + icepyx.core.variables->icepyx.core.exceptions - - + + diff --git a/doc/sphinxext/announce.py b/doc/sphinxext/announce.py old mode 100644 new mode 100755 index 6ff0e4884..e053f4b62 --- a/doc/sphinxext/announce.py +++ b/doc/sphinxext/announce.py @@ -77,10 +77,7 @@ def get_authors(revision_range): # e.g. v1.0.1|HEAD maybe_tag, head = cur_release.split("|") assert head == "HEAD" - if maybe_tag in this_repo.tags: - cur_release = maybe_tag - else: - cur_release = head + cur_release = maybe_tag if maybe_tag in this_repo.tags else head revision_range = f"{lst_release}..{cur_release}" # authors, in current release and previous to current release. @@ -125,7 +122,7 @@ def get_authors(revision_range): # pre.discard("Homu") # Append '+' to new authors. - authors = [s + " +" for s in cur - pre] + [s for s in cur & pre] + authors = [s + " +" for s in cur - pre] + list(cur & pre) authors.sort() return authors diff --git a/icepyx/__init__.py b/icepyx/__init__.py index 40ea9e1ec..b0cd8095d 100644 --- a/icepyx/__init__.py +++ b/icepyx/__init__.py @@ -1,6 +1,20 @@ -from icepyx.core.query import Query, GenQuery -from icepyx.core.read import Read -from icepyx.quest.quest import Quest -from icepyx.core.variables import Variables +from warnings import warn + +deprecation_msg = """icepyx v1.x is being deprecated; the back-end systems on which it relies +will be shut down as of late 2024. At that time, upgrade to icepyx v2.x, which uses the +new NASA Harmony back-end, will be required. Please see + for more +information! +""" +# IMPORTANT: This is being done before the other icepyx imports because the imported +# code changes warning filters. If this is done after the imports, the warning won't +# work. +warn(deprecation_msg, FutureWarning, stacklevel=2) + from _icepyx_version import version as __version__ + +from icepyx.core.query import GenQuery, Query +from icepyx.core.read import Read +from icepyx.core.variables import Variables +from icepyx.quest.quest import Quest diff --git a/icepyx/conftest.py b/icepyx/conftest.py index d90558d69..a8bae49c4 100644 --- a/icepyx/conftest.py +++ b/icepyx/conftest.py @@ -1,6 +1,7 @@ -import icepyx import pytest +import icepyx + @pytest.fixture(autouse=True) def add_ipx(doctest_namespace): diff --git a/icepyx/core/APIformatting.py b/icepyx/core/APIformatting.py index eb77c37e9..4b1966910 100644 --- a/icepyx/core/APIformatting.py +++ b/icepyx/core/APIformatting.py @@ -2,7 +2,6 @@ import datetime as dt - # ---------------------------------------------------------------------- # parameter-specific formatting for display # or input to a set of API parameters (CMR or NSIDC) @@ -73,7 +72,7 @@ def _fmt_readable_granules(dset, **kwds): # list of readable granule names readable_granule_list = [] # if querying either by 91-day orbital cycle or RGT - if "cycles" in kwargs.keys() or "tracks" in kwargs.keys(): + if "cycles" in kwargs or "tracks" in kwargs: # default character wildcards for cycles and tracks kwargs.setdefault("cycles", ["??"]) kwargs.setdefault("tracks", ["????"]) @@ -110,7 +109,7 @@ def _fmt_var_subset_list(vdict): """ subcover = "" - for vn in vdict.keys(): + for vn in vdict: vpaths = vdict[vn] for vpath in vpaths: subcover += "/" + vpath + "," @@ -122,6 +121,9 @@ def combine_params(*param_dicts): """ Combine multiple dictionaries into one. + Merging is performed in sequence using `dict.update()`; dictionaries later in the + list overwrite those earlier. + Parameters ---------- params : dictionaries @@ -129,7 +131,7 @@ def combine_params(*param_dicts): Returns ------- - single dictionary of all input dictionaries combined + A single dictionary of all input dictionaries combined Examples -------- @@ -209,7 +211,7 @@ def __init__(self, partype, values=None, reqtype=None): "CMR", "required", "subset", - ], "You need to submit a valid parametery type." + ], "You need to submit a valid parameter type." self.partype = partype if partype == "required": @@ -243,7 +245,7 @@ def poss_keys(self): @property def fmted_keys(self): """ - Returns the dictionary of formated keys associated with the + Returns the dictionary of formatted keys associated with the parameter object. """ return self._fmted_keys @@ -298,9 +300,9 @@ def _check_valid_keys(self): # if self._wanted == None: # raise ValueError("No desired parameter list was passed") - val_list = list(set(val for lis in self.poss_keys.values() for val in lis)) + val_list = list({val for lis in self.poss_keys.values() for val in lis}) - for key in self.fmted_keys.keys(): + for key in self.fmted_keys: assert key in val_list, ( "An invalid key (" + key + ") was passed. Please remove it using `del`" ) @@ -317,10 +319,10 @@ def check_req_values(self): ), "You cannot call this function for your parameter type" reqkeys = self.poss_keys[self._reqtype] - if all(keys in self.fmted_keys.keys() for keys in reqkeys): + if all(keys in self.fmted_keys for keys in reqkeys): assert all( self.fmted_keys.get(key, -9999) != -9999 for key in reqkeys - ), "One of your formated parameters is missing a value" + ), "One of your formatted parameters is missing a value" return True else: return False @@ -337,10 +339,10 @@ def check_values(self): spatial_keys = self.poss_keys["spatial"] # not the most robust check, but better than nothing... - if any(keys in self._fmted_keys.keys() for keys in spatial_keys): + if any(keys in self._fmted_keys for keys in spatial_keys): assert any( self.fmted_keys.get(key, -9999) != -9999 for key in spatial_keys - ), "One of your formated parameters is missing a value" + ), "One of your formatted parameters is missing a value" return True else: return False @@ -410,13 +412,16 @@ def build_params(self, **kwargs): opt_keys = self.poss_keys["optional"] for key in opt_keys: - if key == "Coverage" and key in kwargs.keys(): - # DevGoal: make there be an option along the lines of Coverage=default, which will get the default variables for that product without the user having to input is2obj.build_wanted_wanted_var_list as their input value for using the Coverage kwarg + if key == "Coverage" and key in kwargs: + # DevGoal: make an option along the lines of Coverage=default, + # which will get the default variables for that product without + # the user having to input is2obj.build_wanted_wanted_var_list + # as their input value for using the Coverage kwarg self._fmted_keys.update( {key: _fmt_var_subset_list(kwargs[key])} ) elif (key == "temporal" or key == "time") and ( - "start" in kwargs.keys() and "end" in kwargs.keys() + "start" in kwargs and "end" in kwargs ): self._fmted_keys.update( _fmt_temporal(kwargs["start"], kwargs["end"], key) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 55e34fd7f..9f12fbecf 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -2,6 +2,7 @@ import datetime import earthaccess + from icepyx.core.exceptions import DeprecationError @@ -10,8 +11,6 @@ class AuthenticationError(Exception): Raised when an error is encountered while authenticating Earthdata credentials """ - pass - class EarthdataAuthMixin: """ @@ -49,7 +48,7 @@ class EarthdataAuthMixin: def __init__(self, auth=None): self._auth = copy.deepcopy(auth) - # initializatin of session and s3 creds is not allowed because those are generated + # initialization of session and s3 creds is not allowed because those are generated # from the auth object self._session = None self._s3login_credentials = None @@ -107,11 +106,9 @@ def set_s3_creds(): # Only generate s3login_credentials the first time credentials are accessed, or if an hour # has passed since the last login - if self._s3login_credentials is None: - set_s3_creds() - elif (datetime.datetime.now() - self._s3_initial_ts) >= datetime.timedelta( - hours=1 - ): + if self._s3login_credentials is None or ( + datetime.datetime.now() - self._s3_initial_ts + ) >= datetime.timedelta(hours=1): set_s3_creds() return self._s3login_credentials diff --git a/icepyx/core/exceptions.py b/icepyx/core/exceptions.py index d20bbfe61..94bbea768 100644 --- a/icepyx/core/exceptions.py +++ b/icepyx/core/exceptions.py @@ -3,16 +3,12 @@ class DeprecationError(Exception): Class raised for use of functionality that is no longer supported by icepyx. """ - pass - class QueryError(Exception): """ Base class for Query object exceptions """ - pass - class NsidcQueryError(QueryError): """ diff --git a/icepyx/core/granules.py b/icepyx/core/granules.py index 205149f56..b29a147e1 100644 --- a/icepyx/core/granules.py +++ b/icepyx/core/granules.py @@ -1,18 +1,20 @@ import datetime -import requests -import time import io -import re import json -import numpy as np import os import pprint +import re +import time from xml.etree import ElementTree as ET import zipfile +import numpy as np +import requests + import icepyx.core.APIformatting as apifmt from icepyx.core.auth import EarthdataAuthMixin import icepyx.core.exceptions +from icepyx.core.urls import DOWNLOAD_BASE_URL, GRANULE_SEARCH_BASE_URL, ORDER_BASE_URL def info(grans): @@ -75,14 +77,13 @@ def gran_IDs(grans, ids=False, cycles=False, tracks=False, dates=False, cloud=Fa if cloud is True: try: for link in gran["links"]: - if link["href"].startswith("s3") and link["href"].endswith( - (".h5", "nc") - ): - gran_s3urls.append(link["href"]) + href = link["href"] + if href.startswith("s3") and href.endswith((".h5", "nc")): + gran_s3urls.append(href) except KeyError: pass - if any([param is True for param in [cycles, tracks, dates]]): + if any(param is True for param in [cycles, tracks, dates]): # PRD: ICESat-2 product # HEM: Sea Ice Hemisphere flag # YY,MM,DD,HH,MN,SS: Year, Month, Day, Hour, Minute, Second @@ -202,8 +203,6 @@ def get_avail(self, CMRparams, reqparams, cloud=False): # if not hasattr(self, 'avail'): self.avail = [] - granule_search_url = "https://cmr.earthdata.nasa.gov/search/granules" - headers = {"Accept": "application/json", "Client-Id": "icepyx"} # note we should also check for errors whenever we ping NSIDC-API - # make a function to check for errors @@ -221,7 +220,7 @@ def get_avail(self, CMRparams, reqparams, cloud=False): headers["CMR-Search-After"] = cmr_search_after response = requests.get( - granule_search_url, + GRANULE_SEARCH_BASE_URL, headers=headers, params=apifmt.to_string(params), ) @@ -309,8 +308,6 @@ def place_order( query.Query.order_granules """ - base_url = "https://n5eil02u.ecs.nsidc.org/egi/request" - self.get_avail(CMRparams, reqparams) if subset is False: @@ -346,7 +343,7 @@ def place_order( ) request_params.update({"page_num": page_num}) - request = self.session.get(base_url, params=request_params) + request = self.session.get(ORDER_BASE_URL, params=request_params) # DevGoal: use the request response/number to do some error handling/ # give the user better messaging for failures @@ -378,7 +375,7 @@ def place_order( print("order ID: ", orderID) # Create status URL - statusURL = base_url + "/" + orderID + statusURL = f"{ORDER_BASE_URL}/{orderID}" if verbose is True: print("status URL: ", statusURL) @@ -399,6 +396,11 @@ def place_order( status = statuslist[0] print("Initial status of your order request at NSIDC is: ", status) + # If status is already finished without going into pending/processing + if status.startswith("complete"): + loop_response = self.session.get(statusURL) + loop_root = ET.fromstring(loop_response.content) + # Continue loop while request is still processing while status == "pending" or status == "processing": print( @@ -523,7 +525,7 @@ def download(self, verbose, path, restart=False): i_order = self.orderIDs.index(order_start) + 1 for order in self.orderIDs[i_order:]: - downloadURL = "https://n5eil02u.ecs.nsidc.org/esir/" + order + ".zip" + downloadURL = f"{DOWNLOAD_BASE_URL}/{order}.zip" # DevGoal: get the download_url from the granules if verbose is True: diff --git a/icepyx/core/is2ref.py b/icepyx/core/is2ref.py index be3a3c8da..95df81971 100644 --- a/icepyx/core/is2ref.py +++ b/icepyx/core/is2ref.py @@ -1,12 +1,13 @@ -import h5py import json -import numpy as np -import requests import warnings from xml.etree import ElementTree as ET import earthaccess +import h5py +import numpy as np +import requests +from icepyx.core.urls import COLLECTION_SEARCH_BASE_URL, EGI_BASE_URL # ICESat-2 specific reference functions @@ -82,8 +83,7 @@ def about_product(prod): query.Query.product_all_info """ - cmr_collections_url = "https://cmr.earthdata.nasa.gov/search/collections.json" - response = requests.get(cmr_collections_url, params={"short_name": prod}) + response = requests.get(COLLECTION_SEARCH_BASE_URL, params={"short_name": prod}) results = json.loads(response.content) return results @@ -101,9 +101,7 @@ def _get_custom_options(session, product, version): "Don't forget to log in to Earthdata using query.earthdata_login()" ) - capability_url = ( - f"https://n5eil02u.ecs.nsidc.org/egi/capabilities/{product}.{version}.xml" - ) + capability_url = f"{EGI_BASE_URL}/capabilities/{product}.{version}.xml" response = session.get(capability_url) root = ET.fromstring(response.content) diff --git a/icepyx/core/query.py b/icepyx/core/query.py index a57806501..d547a959f 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -1,6 +1,7 @@ +import pprint + import geopandas as gpd import matplotlib.pyplot as plt -import pprint import icepyx.core.APIformatting as apifmt from icepyx.core.auth import EarthdataAuthMixin @@ -126,7 +127,7 @@ def __init__( **kwargs, ): # validate & init spatial extent - if "xdateline" in kwargs.keys(): + if "xdateline" in kwargs: self._spatial = spat.Spatial(spatial_extent, xdateline=kwargs["xdateline"]) else: self._spatial = spat.Spatial(spatial_extent) @@ -450,7 +451,7 @@ def __str__(self): @property def dataset(self): """ - Legacy property included to provide depracation warning. + Legacy property included to provide deprecation warning. See Also -------- @@ -637,7 +638,7 @@ def subsetparams(self, **kwargs): else: # If the user has supplied a subset list of variables, append the # icepyx required variables to the Coverage dict - if "Coverage" in kwargs.keys(): + if "Coverage" in kwargs: var_list = [ "orbit_info/sc_orient", "orbit_info/sc_orient_time", @@ -653,7 +654,7 @@ def subsetparams(self, **kwargs): ] # Add any variables from var_list to Coverage that are not already included for var in var_list: - if var not in kwargs["Coverage"].keys(): + if var not in kwargs["Coverage"]: kwargs["Coverage"][var.split("/")[-1]] = [var] if self._subsetparams is None: @@ -722,7 +723,7 @@ def order_vars(self): @property def granules(self): """ - Return the granules object, which provides the underlying funtionality for searching, ordering, + Return the granules object, which provides the underlying functionality for searching, ordering, and downloading granules for the specified product. Users are encouraged to use the built-in wrappers rather than trying to access the granules object themselves. @@ -741,9 +742,7 @@ def granules(self): """ - if not hasattr(self, "_granules"): - self._granules = Granules() - elif self._granules is None: + if not hasattr(self, "_granules") or self._granules is None: self._granules = Granules() return self._granules @@ -869,8 +868,8 @@ def show_custom_options(self, dictview=False): ] try: - all(key in self._cust_options.keys() for key in keys) - except AttributeError or KeyError: + all(key in self._cust_options for key in keys) + except (AttributeError, KeyError): self._cust_options = is2ref._get_custom_options( self.session, self.product, self._version ) @@ -999,7 +998,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): if self._reqparams._reqtype == "search": self._reqparams._reqtype = "download" - if "email" in self._reqparams.fmted_keys.keys() or email is False: + if "email" in self._reqparams.fmted_keys or email is False: self._reqparams.build_params(**self._reqparams.fmted_keys) elif email is True: user_profile = self.auth.get_user_profile() @@ -1022,7 +1021,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): self.granules # Place multiple orders, one per granule, if readable_granule_name is used. - if "readable_granule_name[]" in self.CMRparams.keys(): + if "readable_granule_name[]" in self.CMRparams: gran_name_list = self.CMRparams["readable_granule_name[]"] tempCMRparams = self.CMRparams if len(gran_name_list) > 1: @@ -1133,8 +1132,8 @@ def visualize_spatial_extent( gdf = self._spatial.extent_as_gdf try: - from shapely.geometry import Polygon # noqa: F401 import geoviews as gv + from shapely.geometry import Polygon # noqa: F401 gv.extension("bokeh") diff --git a/icepyx/core/read.py b/icepyx/core/read.py index e6bfc40b7..b3212aef2 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -120,7 +120,7 @@ def _parse_source(data_source, glob_kwargs={}) -> list: # if data_source is a directory glob search the directory and assign to _filelist data_source = os.path.join(data_source, "*") filelist = glob.glob(data_source, **glob_kwargs) - elif isinstance(data_source, str) or isinstance(data_source, Path): + elif isinstance(data_source, (Path, str)): if data_source.startswith("s3"): # if the string is an s3 path put it in the _filelist without globbing filelist = [data_source] @@ -164,7 +164,7 @@ def _confirm_proceed(): class Read(EarthdataAuthMixin): """ Data object to read ICESat-2 data into the specified formats. - Provides flexiblity for reading nested hdf5 files into common analysis formats. + Provides flexibility for reading nested hdf5 files into common analysis formats. Parameters ---------- @@ -432,7 +432,7 @@ def _add_vars_to_ds(is2ds, ds, grp_path, wanted_groups_tiered, wanted_dict): ] # handle delta_times with 1 or more dimensions - idx_range = range(0, len(ds.delta_time.data)) + idx_range = range(len(ds.delta_time.data)) try: photon_ids = ( idx_range @@ -440,7 +440,7 @@ def _add_vars_to_ds(is2ds, ds, grp_path, wanted_groups_tiered, wanted_dict): + 1 ) except AttributeError: - photon_ids = range(0, len(ds.delta_time.data)) + photon_ids = range(len(ds.delta_time.data)) hold_delta_times = ds.delta_time.data ds = ( @@ -661,11 +661,11 @@ def _build_dataset_template(self, file): """ is2ds = xr.Dataset( - coords=dict( - gran_idx=[np.uint64(999999)], - source_file=(["gran_idx"], [file]), - ), - attrs=dict(data_product=self.product), + coords={ + "gran_idx": [np.uint64(999999)], + "source_file": (["gran_idx"], [file]), + }, + attrs={"data_product": self.product}, ) return is2ds @@ -740,7 +740,7 @@ def _build_single_file_dataset(self, file, groups_list): "ATL23", ]: wanted_grouponly_set = set(wanted_groups_tiered[0]) - wanted_groups_list = list(sorted(wanted_grouponly_set)) + wanted_groups_list = sorted(wanted_grouponly_set) if len(wanted_groups_list) == 1: is2ds = self._read_single_grp(file, grp_path=wanted_groups_list[0]) else: diff --git a/icepyx/core/spatial.py b/icepyx/core/spatial.py index d810726b3..0bc066e78 100644 --- a/icepyx/core/spatial.py +++ b/icepyx/core/spatial.py @@ -1,10 +1,10 @@ -import geopandas as gpd -import numpy as np import os -from shapely.geometry import box, Polygon -from shapely.geometry.polygon import orient import warnings +import geopandas as gpd +import numpy as np +from shapely.geometry import Polygon, box +from shapely.geometry.polygon import orient # DevGoal: need to update the spatial_extent docstring to describe coordinate order for input @@ -496,7 +496,7 @@ def __init__(self, spatial_extent, **kwarg): self._spatial_ext = [float(i) for i in arrpoly] # check for cross dateline keyword submission - if "xdateline" in kwarg.keys(): + if "xdateline" in kwarg: self._xdateln = kwarg["xdateline"] assert self._xdateln in [ True, @@ -542,10 +542,7 @@ def extent_as_gdf(self): """ # TODO: test this - if hasattr(self, "_xdateln"): - xdateln = self._xdateln - else: - xdateln = None + xdateln = self._xdateln if hasattr(self, "_xdateln") else None if not hasattr(self, "_gdf_spat"): if self._geom_file is not None: diff --git a/icepyx/core/temporal.py b/icepyx/core/temporal.py index 67f59882a..c02326fbf 100644 --- a/icepyx/core/temporal.py +++ b/icepyx/core/temporal.py @@ -1,7 +1,6 @@ import datetime as dt import warnings - """ Helper functions for validation of dates """ diff --git a/icepyx/core/urls.py b/icepyx/core/urls.py new file mode 100644 index 000000000..8c5bc325b --- /dev/null +++ b/icepyx/core/urls.py @@ -0,0 +1,10 @@ +from typing import Final + +CMR_BASE_URL: Final = "https://cmr.earthdata.nasa.gov" +GRANULE_SEARCH_BASE_URL: Final = f"{CMR_BASE_URL}/search/granules" +COLLECTION_SEARCH_BASE_URL: Final = f"{CMR_BASE_URL}/search/collections.json" + +EGI_BASE_URL: Final = "https://n5eil02u.ecs.nsidc.org/egi" +ORDER_BASE_URL: Final = f"{EGI_BASE_URL}/request" + +DOWNLOAD_BASE_URL: Final = "https://n5eil02u.ecs.nsidc.org/esir" diff --git a/icepyx/core/validate_inputs.py b/icepyx/core/validate_inputs.py index e70a8f944..db5e44d05 100644 --- a/icepyx/core/validate_inputs.py +++ b/icepyx/core/validate_inputs.py @@ -1,5 +1,6 @@ import datetime as dt import warnings + import numpy as np diff --git a/icepyx/core/variables.py b/icepyx/core/variables.py index 87c2a94e8..b7b1c56b8 100644 --- a/icepyx/core/variables.py +++ b/icepyx/core/variables.py @@ -1,9 +1,10 @@ -import numpy as np import os +import numpy as np + from icepyx.core.auth import EarthdataAuthMixin -import icepyx.core.is2ref as is2ref from icepyx.core.exceptions import DeprecationError +import icepyx.core.is2ref as is2ref import icepyx.core.validate_inputs as val # DEVGOAL: use h5py to simplify some of these tasks, if possible! @@ -84,10 +85,7 @@ def __init__( self._path = val.check_s3bucket(path) # Set up auth - if self._path.startswith("s3"): - auth = self.auth - else: - auth = None + auth = self.auth if self._path.startswith("s3") else None # Read the product and version from the file self._product = is2ref.extract_product(self._path, auth=auth) self._version = is2ref.extract_version(self._path, auth=auth) @@ -111,11 +109,7 @@ def __init__( @property def path(self): - if self._path: - path = self._path - else: - path = None - return path + return self._path if self._path else None @property def product(self): @@ -271,7 +265,7 @@ def parse_var_list(varlist, tiered=True, tiered_vars=False): for vn in varlist: vpath, vkey = os.path.split(vn) # print('path '+ vpath + ', key '+vkey) - if vkey not in vgrp.keys(): + if vkey not in vgrp: vgrp[vkey] = [vn] else: vgrp[vkey].append(vn) @@ -321,7 +315,7 @@ def _check_valid_lists( # check if the list of variables, if specified, are available in the product if var_list is not None: for var_id in var_list: - if var_id not in vgrp.keys(): + if var_id not in vgrp: err_msg_varid = "Invalid variable name: " + var_id + ". " err_msg_varid = err_msg_varid + "Please select from this list: " err_msg_varid = err_msg_varid + ", ".join(vgrp.keys()) @@ -437,7 +431,7 @@ def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=Non ---------- defaults : boolean, default False Include the variables in the default variable list. Defaults are defined per-data product. - When specified in conjuction with a var_list, default variables not on the user- + When specified in conjunction with a var_list, default variables not on the user- specified list will be added to the order. var_list : list of strings, default None @@ -451,8 +445,8 @@ def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=Non For all other products, acceptable values are ['gt1l', 'gt1r', 'gt2l', 'gt2r', 'gt3l', 'gt3r']. keyword_list : list of strings, default None - A list of subdirectory names (keywords), from any heirarchy level within the data structure, to select variables within - the product that include that keyword in their path. A list of availble keywords can be obtained by + A list of subdirectory names (keywords), from any hierarchy level within the data structure, to select variables within + the product that include that keyword in their path. A list of available keywords can be obtained by entering `keyword_list=['']` into the function. Notes @@ -514,9 +508,9 @@ def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=Non ) # update the data object variables - for vkey in final_vars.keys(): + for vkey in final_vars: # add all matching keys and paths for new variables - if vkey not in self.wanted.keys(): + if vkey not in self.wanted: self.wanted[vkey] = final_vars[vkey] else: for vpath in final_vars[vkey]: @@ -545,7 +539,7 @@ def remove(self, all=False, var_list=None, beam_list=None, keyword_list=None): For all other products, acceptable values are ['gt1l', 'gt1r', 'gt2l', 'gt2r', 'gt3l', 'gt3r']. keyword_list : list of strings, default None - A list of subdirectory names (keywords), from any heirarchy level within the data structure, to select variables within + A list of subdirectory names (keywords), from any hierarchy level within the data structure, to select variables within the product that include that keyword in their path. Notes diff --git a/icepyx/core/visualization.py b/icepyx/core/visualization.py index bdbc6d2d9..0ddb9fd40 100644 --- a/icepyx/core/visualization.py +++ b/icepyx/core/visualization.py @@ -10,15 +10,15 @@ import dask.dataframe as dd import datashader as ds import holoviews as hv +from holoviews.operation.datashader import rasterize import numpy as np import pandas as pd import requests -from holoviews.operation.datashader import rasterize from tqdm import tqdm import icepyx as ipx -import icepyx.core.is2ref as is2ref import icepyx.core.granules as granules +import icepyx.core.is2ref as is2ref hv.extension("bokeh") @@ -312,7 +312,13 @@ def make_request(self, base_url, payload): -------- request_OA_data """ - return requests.get(base_url, params=payload) + response = requests.get(base_url, params=payload) + if not response.ok: + raise RuntimeError( + f"Status {response.status_code} requesting url {response.request.url}" + ) + + return response def request_OA_data(self, paras) -> da.array: """ @@ -331,9 +337,8 @@ def request_OA_data(self, paras) -> da.array: """ warnings.warn( - "NOTICE: visualizations requiring the OpenAltimetry API are currently (October 2023) " - "unavailable while hosting of OpenAltimetry transitions from UCSD to NSIDC." - "A ticket has been issued to restore programmatic API access." + "NOTICE: visualizations requiring the OpenAltimetry API are currently" + " (August 2024) unavailable until we can adapt to API changes." ) base_url = "http://openaltimetry.earthdatacloud.nasa.gov/data/api/icesat2" diff --git a/icepyx/quest/dataset_scripts/__init__.py b/icepyx/quest/dataset_scripts/__init__.py index 7834127ff..498059021 100644 --- a/icepyx/quest/dataset_scripts/__init__.py +++ b/icepyx/quest/dataset_scripts/__init__.py @@ -1 +1 @@ -from .dataset import * +from .dataset import * # noqa: F403 diff --git a/icepyx/quest/dataset_scripts/argo.py b/icepyx/quest/dataset_scripts/argo.py index b7f374bd6..b170feec0 100644 --- a/icepyx/quest/dataset_scripts/argo.py +++ b/icepyx/quest/dataset_scripts/argo.py @@ -45,10 +45,7 @@ def __init__(self, aoi, toi, params=["temperature"], presRange=None): self._apikey = "92259861231b55d32a9c0e4e3a93f4834fc0b6fa" def __str__(self): - if self.presRange is None: - prange = "All" - else: - prange = str(self.presRange) + prange = "All" if self.presRange is None else str(self.presRange) if self.argodata is None: df = "No data yet" @@ -297,7 +294,7 @@ def search_data(self, params=None, presRange=None, printURL=False) -> str: selectionProfiles = resp.json() # Consider any status other than 2xx an error - if not resp.status_code // 100 == 2: + if resp.status_code // 100 != 2: # check for the existence of profiles from query if selectionProfiles == []: msg = ( @@ -362,7 +359,7 @@ def _download_profile( print(resp.url) # Consider any status other than 2xx an error - if not resp.status_code // 100 == 2: + if resp.status_code // 100 != 2: return "Error: Unexpected response {}".format(resp) profile = resp.json() return profile @@ -477,7 +474,7 @@ def download(self, params=None, presRange=None, keep_existing=True) -> pd.DataFr profile_data = self._download_profile(i) profile_df = self._parse_into_df(profile_data[0]) merged_df = pd.concat([merged_df, profile_df], sort=False) - except: + except Exception: print("\tError processing profile {0}. Skipping.".format(i)) # now that we have a df from this round of downloads, we can add it to any existing dataframe diff --git a/icepyx/quest/quest.py b/icepyx/quest/quest.py index a7cf9be3c..c24029070 100644 --- a/icepyx/quest/quest.py +++ b/icepyx/quest/quest.py @@ -1,5 +1,4 @@ from icepyx.core.query import GenQuery, Query - from icepyx.quest.dataset_scripts.argo import Argo @@ -72,7 +71,7 @@ def __str__(self): if not self.datasets: str += "None" else: - for i in self.datasets.keys(): + for i in self.datasets: str += "{0}, ".format(i) str = str[:-2] # remove last ', ' @@ -157,7 +156,7 @@ def add_argo(self, params=["temperature"], presRange=None) -> None: # error handling? what happens when the user tries to re-query? def search_all(self, **kwargs): """ - Searches for requred dataset within platform (i.e. ICESat-2, Argo) of interest. + Searches for required dataset within platform (i.e. ICESat-2, Argo) of interest. Parameters ---------- @@ -187,7 +186,7 @@ def search_all(self, **kwargs): except KeyError: v.search_data() - except: + except Exception: dataset_name = type(v).__name__ print("Error querying data from {0}".format(dataset_name)) @@ -226,7 +225,7 @@ def download_all(self, path="", **kwargs): except KeyError: msg = v.download() print(msg) - except: + except Exception: dataset_name = type(v).__name__ print("Error downloading data from {0}".format(dataset_name)) diff --git a/icepyx/tests/conftest.py b/icepyx/tests/conftest.py index 9ce8e4081..5bc5eb870 100644 --- a/icepyx/tests/conftest.py +++ b/icepyx/tests/conftest.py @@ -1,7 +1,8 @@ import os -import pytest from unittest import mock +import pytest + # PURPOSE: mock environmental variables @pytest.fixture(scope="session", autouse=True) diff --git a/icepyx/tests/test_APIformatting.py b/icepyx/tests/test_APIformatting.py index 6dfe98353..0c7009d10 100644 --- a/icepyx/tests/test_APIformatting.py +++ b/icepyx/tests/test_APIformatting.py @@ -2,7 +2,6 @@ import icepyx.core.APIformatting as apifmt - # DevNote: is this a situation where you'd ideally build a test class, # since you're just repeating the test function with different inputs? # Especially for the _fmt_spaital, where there's >2 tests? diff --git a/icepyx/tests/test_Earthdata.py b/icepyx/tests/test_Earthdata.py index cfa2eb2c5..403159e04 100644 --- a/icepyx/tests/test_Earthdata.py +++ b/icepyx/tests/test_Earthdata.py @@ -1,13 +1,13 @@ -#!/usr/bin/env python """ test icepyx.core.query.Query.earthdata_login function """ import netrc import os -import pytest import shutil +import pytest + # PURPOSE: test different authentication methods @pytest.fixture(scope="module", autouse=True) @@ -65,11 +65,8 @@ def earthdata_login(uid=None, pwd=None, email=None, s3token=False) -> bool: try: url = "urs.earthdata.nasa.gov" mock_uid, _, mock_pwd = netrc.netrc(netrc).authenticators(url) - except: + except Exception: mock_uid = os.environ.get("EARTHDATA_USERNAME") mock_pwd = os.environ.get("EARTHDATA_PASSWORD") - if (uid == mock_uid) & (pwd == mock_pwd): - return True - else: - return False + return bool((uid == mock_uid) & (pwd == mock_pwd)) diff --git a/icepyx/tests/test_auth.py b/icepyx/tests/test_auth.py index 50ae1e6ca..97d40344d 100644 --- a/icepyx/tests/test_auth.py +++ b/icepyx/tests/test_auth.py @@ -1,8 +1,7 @@ +import earthaccess import pytest import requests -import earthaccess - from icepyx.core.auth import EarthdataAuthMixin @@ -23,9 +22,7 @@ def test_get_session(auth_instance): # Test that .s3login_credentials creates a dict with the correct keys def test_get_s3login_credentials(auth_instance): assert isinstance(auth_instance.s3login_credentials, dict) - expected_keys = set( - ["accessKeyId", "secretAccessKey", "sessionToken", "expiration"] - ) + expected_keys = {"accessKeyId", "secretAccessKey", "sessionToken", "expiration"} assert set(auth_instance.s3login_credentials.keys()) == expected_keys diff --git a/icepyx/tests/test_behind_NSIDC_API_login.py b/icepyx/tests/test_behind_NSIDC_API_login.py index 47d0a10d2..f9fb49077 100644 --- a/icepyx/tests/test_behind_NSIDC_API_login.py +++ b/icepyx/tests/test_behind_NSIDC_API_login.py @@ -1,11 +1,16 @@ +""" +Integration tests that require authentication to Earthdata login. +""" + +import glob import json import os + import pytest import icepyx as ipx import icepyx.core.is2ref as is2ref - # Misc notes and needed tests # test avail data and subsetting success for each input type # (kml, shp, list of coords, bbox) @@ -37,8 +42,8 @@ def test_get_custom_options_output(session): obs = is2ref._get_custom_options(session, "ATL06", "006") with open("./icepyx/tests/ATL06v06_options.json") as exp_json: exp = json.load(exp_json) - assert all(keys in obs.keys() for keys in exp.keys()) - assert all(obs[key] == exp[key] for key in exp.keys()) + assert all(keys in obs for keys in exp) + assert all(obs[key] == exp[key] for key in exp) ########## query module ########## @@ -49,8 +54,40 @@ def test_download_granules_with_subsetting(reg, session): reg.download_granules(path) -# def test_download_granules_without_subsetting(reg_a, session): -# path = './downloads' -# reg_a.order_granules(session, subset=False) -# reg_a.download_granules(session, path) -# #check that the max extent of the downloaded granules isn't subsetted +def test_download_granules_without_subsetting(reg, session, capsys): + """ + Test that granules can be ordered from NSIDC and downloaded with the `subset=False` + option. + """ + path = "./downloads" + + reg.order_granules(verbose=False, subset=False, email=False) + out, err = capsys.readouterr() # capture stdout and stderr + assert out.startswith( + "Total number of data order requests is 1 for 3 granules.\n" + "Data request 1 of 1 is submitting to NSIDC\n" + ) + assert err == "" + + assert reg.reqparams == { + "client_string": "icepyx", + "include_meta": "Y", + "page_num": 0, + "page_size": 2000, + "request_mode": "async", + "short_name": "ATL06", + "version": "006", + } + assert len(reg.granules.orderIDs) == 2 + assert int(reg.granules.orderIDs[0]) >= 5_000_000_000_000 + + reg.download_granules(path=path) + # check that there are the right number of files of the correct size + assert len(glob.glob(pathname=f"{path}/ATL06_201902*.iso.xml")) == 3 + h5_paths = sorted(glob.glob(pathname=f"{path}/ATL06_201902*.h5")) + assert len(h5_paths) == 3 + assert [os.path.getsize(filename=p) for p in h5_paths] == [ + 53228429, # 50.8 MiB + 65120027, # 62.1 MiB + 49749227, # 47.4 MiB + ] diff --git a/icepyx/tests/test_granules.py b/icepyx/tests/test_granules.py index 4e12c0eb3..90e3374d9 100644 --- a/icepyx/tests/test_granules.py +++ b/icepyx/tests/test_granules.py @@ -1,11 +1,12 @@ -import pytest import re + +import pytest import responses import icepyx as ipx from icepyx.core import granules as granules -from icepyx.core.granules import Granules as Granules from icepyx.core.exceptions import NsidcQueryError +from icepyx.core.granules import Granules as Granules # @pytest.fixture # def reg_a(): @@ -30,7 +31,7 @@ # region_a.avail_granules(ids=True) # add test that s3urls are gotten for ALL products (e.g. ATL15 was failing -# due to .nc extention instead of .h5)) +# due to .nc extension instead of .h5)) # DevNote: clearly there's a better way that doesn't make the function so long... diff --git a/icepyx/tests/is2class_query.py b/icepyx/tests/test_is2class_query.py similarity index 86% rename from icepyx/tests/is2class_query.py rename to icepyx/tests/test_is2class_query.py index 84c31cfa4..b05e0f654 100644 --- a/icepyx/tests/is2class_query.py +++ b/icepyx/tests/test_is2class_query.py @@ -1,5 +1,11 @@ +import pytest + import icepyx as ipx +# Skip the whole module. See: +# https://docs.pytest.org/en/stable/reference/reference.html#globalvar-pytestmark +pytestmark = pytest.mark.skip("Legacy tests -- not sure if they ever passed!") + def test_CMRparams(): reg_a = ipx.Query("ATL06", [-64, 66, -55, 72], ["2019-02-22", "2019-02-28"]) diff --git a/icepyx/tests/test_quest.py b/icepyx/tests/test_quest.py index 2270bfa8b..1b8259aaa 100644 --- a/icepyx/tests/test_quest.py +++ b/icepyx/tests/test_quest.py @@ -15,7 +15,7 @@ def quest_instance(scope="module", autouse=True): ########## PER-DATASET ADDITION TESTS ########## -# Paramaterize these add_dataset tests once more datasets are added +# Parameterize these add_dataset tests once more datasets are added def test_add_is2(quest_instance): # Add ATL06 as a test to QUEST @@ -26,9 +26,9 @@ def test_add_is2(quest_instance): obs = quest_instance.datasets - assert type(obs) == dict - assert exp_key in obs.keys() - assert type(obs[exp_key]) == exp_type + assert type(obs) is dict + assert exp_key in obs + assert type(obs[exp_key]) is exp_type assert quest_instance.datasets[exp_key].product == prod @@ -40,9 +40,9 @@ def test_add_argo(quest_instance): obs = quest_instance.datasets - assert type(obs) == dict - assert exp_key in obs.keys() - assert type(obs[exp_key]) == exp_type + assert type(obs) is dict + assert exp_key in obs + assert type(obs[exp_key]) is exp_type assert set(quest_instance.datasets[exp_key].params) == set(params) @@ -54,7 +54,7 @@ def test_add_multiple_datasets(quest_instance): # print(quest_instance.datasets["icesat2"].product) exp_keys = ["argo", "icesat2"] - assert set(exp_keys) == set(quest_instance.datasets.keys()) + assert set(exp_keys) == set(quest_instance.datasets) ########## ALL DATASET METHODS TESTS ########## diff --git a/icepyx/tests/test_quest_argo.py b/icepyx/tests/test_quest_argo.py index a31b52f78..e11e0cbe1 100644 --- a/icepyx/tests/test_quest_argo.py +++ b/icepyx/tests/test_quest_argo.py @@ -1,7 +1,7 @@ import os +import re import pytest -import re from icepyx.quest.quest import Quest @@ -244,4 +244,4 @@ def test_replace_presRange_download(argo_quest_instance): assert "salinity" in df.columns -# second pres range test where does have a higher max pressure because only the new data was presRange limited? +# second pressure range test where does have a higher max pressure because only the new data was presRange limited? diff --git a/icepyx/tests/test_read.py b/icepyx/tests/test_read.py index 20807c410..90efe13f9 100644 --- a/icepyx/tests/test_read.py +++ b/icepyx/tests/test_read.py @@ -29,12 +29,12 @@ def test_parse_source_no_files(): ( # check list input [ "./icepyx/core/is2ref.py", - "./icepyx/tests/is2class_query.py", + "./icepyx/tests/test_is2class_query.py", ], sorted( [ "./icepyx/core/is2ref.py", - "./icepyx/tests/is2class_query.py", + "./icepyx/tests/test_is2class_query.py", ] ), ), @@ -45,11 +45,12 @@ def test_parse_source_no_files(): ], ), ( # check filename string with glob pattern input - "./icepyx/**/is2*.py", + "./icepyx/**/*is2*.py", sorted( [ "./icepyx/core/is2ref.py", - "./icepyx/tests/is2class_query.py", + "./icepyx/tests/test_is2class_query.py", + "./icepyx/tests/test_is2ref.py", ] ), ), diff --git a/icepyx/tests/test_spatial.py b/icepyx/tests/test_spatial.py index dc71cdac9..2243c0674 100644 --- a/icepyx/tests/test_spatial.py +++ b/icepyx/tests/test_spatial.py @@ -1,13 +1,13 @@ +from pathlib import Path +import re + import geopandas as gpd import numpy as np -from pathlib import Path import pytest -import re from shapely.geometry import Polygon import icepyx.core.spatial as spat - # ######### "Bounding Box" input tests ################################################################################ # (Note that these ALSO test the @property functions for the class for bounding boxes) diff --git a/icepyx/tests/test_temporal.py b/icepyx/tests/test_temporal.py index cd24deda4..52ec947c3 100644 --- a/icepyx/tests/test_temporal.py +++ b/icepyx/tests/test_temporal.py @@ -1,9 +1,9 @@ import datetime as dt + import pytest import icepyx.core.temporal as tp - # DevNote: this test suite needs to be parameterized (and fixtured) to include ALL acceptable input types # Currently it tests most cases for lists and dicts where the input type is str # A couple of tests were added for datetime.datetime type inputs, but they are incomplete diff --git a/pyproject.toml b/pyproject.toml index 4f4c0a88c..f44ea450a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ description = "Python tools for obtaining and working with ICESat-2 data" license = {file = "LICENSE"} readme = "README.rst" -requires-python = "~=3.7" +requires-python = ">=3.9" dynamic = ["version", "dependencies"] authors = [ @@ -20,8 +20,6 @@ classifiers=[ "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -61,14 +59,45 @@ version_file = "_icepyx_version.py" version_file_template = 'version = "{version}"' local_scheme = "node-and-date" fallback_version = "unknown" + +[tool.codespell] +ignore-words-list = "aas,socio-economic,toi" + +[tool.ruff] +# DevGoal: Lint and format all Jupyter Notebooks, remove below. +extend-exclude = ["*.ipynb"] + # [tool.ruff.format] # docstring-code-format = true # docstring-code-line-length = "dynamic" + [tool.ruff.lint] +# DevGoal: Enable "ARG" and "B" rulesets ASAP! select = [ + # "ARG", # flake8-unused-arguments + # "B", # flake8-bugbear + "C4", # flake8-comprehensions "E", # pycodestyle + # "EM", # flake8-errmsg + "EXE", # flake8-executable "F", # pyflakes + "G", # flake8-logging-format + "I", # isort + "ICN", # flake8-import-conventions + "NPY", # NumPy specific rules + # "PD", # pandas-vet + "PGH", # pygrep-hooks + "PIE", # flake8-pie + # "PL", # pylint + # "PT", # flake8-pytest-style + # "PTH", # flake8-use-pathlib + # "RET", # flake8-return + # "RUF", # Ruff-specific + "SIM", # flake8-simplify + # "T20", # flake8-print + # "UP", # pyupgrade + "YTT", # flake8-2020 ] ignore = [ # Line too long @@ -78,13 +107,7 @@ ignore = [ # overlong comments. # See: https://github.com/psf/black/issues/1713#issuecomment-1357045092 "E501", - # TODO: remove ignores below this line - # comparison syntax in tests - "E721", - # bare except - "E722", - # unable to detect undefined names - "F403", + "SIM105", # suppressible-exception ] [tool.ruff.lint.per-file-ignores] @@ -98,3 +121,6 @@ ignore = [ # Ignore too many leading '#' for block comment "*/tests/*" = ["E266"] + +[tool.ruff.lint.isort] +force-sort-within-sections = true