././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739319944.1234832 ndcube-2.3.1/0000755000175100001660000000000014752765210012371 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739319944.099483 ndcube-2.3.1/.circleci/0000755000175100001660000000000014752765210014224 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.circleci/codecov_upload.sh0000644000175100001660000000067014752765177017565 0ustar00runnerdocker#!/bin/bash -e curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import 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 "$@" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.circleci/config.yml0000644000175100001660000000727514752765177016243 0ustar00runnerdockerversion: 2.1 no-backports: &no-backports name: Skip any branches called cherry-pick command: | if [[ "${CIRCLE_BRANCH}" == *"cherry-pick"* || "${CIRCLE_BRANCH}" == *"backport"* ]]; then circleci step halt fi skip-check: &skip-check name: Check for [ci skip] command: bash .circleci/early_exit.sh merge-check: &merge-check name: Check if we need to merge upstream main command: | if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then git fetch origin --tags git fetch origin +refs/pull/$CIRCLE_PR_NUMBER/merge:pr/$CIRCLE_PR_NUMBER/merge git checkout -qf pr/$CIRCLE_PR_NUMBER/merge fi apt-run: &apt-install name: Install apt packages command: | sudo apt update sudo apt install -y libopenjp2-7 jobs: figure: parameters: jobname: type: string docker: - image: cimg/python:3.12 environment: TOXENV=<< parameters.jobname >> steps: - run: *no-backports - checkout - run: *skip-check - run: *merge-check - run: *apt-install - run: pip install --user -U tox tox-pypi-filter - run: tox -v - run: name: Running codecov command: bash -e .circleci/codecov_upload.sh -f ".tmp/${TOXENV}/coverage.xml" - store_artifacts: path: .tmp/<< parameters.jobname >>/figure_test_images - run: name: "Image comparison page is available at: " command: echo "${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/.tmp/${TOXENV}/figure_test_images/fig_comparison.html" deploy-reference-images: parameters: jobname: type: string docker: - image: cimg/python:3.12 environment: TOXENV: << parameters.jobname >> GIT_SSH_COMMAND: ssh -i ~/.ssh/id_rsa_b1c8b094a8ec67162b0f18a949a6b1db steps: - checkout - run: *skip-check - run: *merge-check - run: *apt-install # Clear out all the ssh keys so that it always uses the write deploy key - run: ssh-add -D # Add private key for deploying to the figure tests repo - add_ssh_keys: fingerprints: "b1:c8:b0:94:a8:ec:67:16:2b:0f:18:a9:49:a6:b1:db" - run: ssh-keyscan github.com >> ~/.ssh/known_hosts - run: git config --global user.email "ndcube@circleci" && git config --global user.name "ndcube Circle CI" - run: git clone git@github.com:sunpy/sunpy-figure-tests.git --depth 1 -b ndcube-${CIRCLE_BRANCH} ~/sunpy-figure-tests/ # Generate Reference images - run: pip install --user -U tox tox-pypi-filter - run: rm -rf /home/circleci/sunpy-figure-tests/figures/$TOXENV/* - run: tox -v -- --mpl-generate-path=/home/circleci/sunpy-figure-tests/figures/$TOXENV | tee toxlog - run: | hashlib=$(grep "^figure_hashes.*\.json$" toxlog) cp ./ndcube/visualization/tests/$hashlib /home/circleci/sunpy-figure-tests/figures/$TOXENV/ - run: | cd ~/sunpy-figure-tests/ git pull git status git add . git commit -m "Update reference figures from ndcube ${CIRCLE_BRANCH}" || echo "No changes to reference images to deploy" git push workflows: version: 2 figure-tests: jobs: - figure: name: << matrix.jobname >> matrix: parameters: jobname: - "py312-figure" - "py312-figure-devdeps" - deploy-reference-images: name: baseline-<< matrix.jobname >> matrix: parameters: jobname: - "py312-figure" - "py312-figure-devdeps" requires: - << matrix.jobname >> filters: branches: only: - main ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.circleci/early_exit.sh0000644000175100001660000000035314752765177016742 0ustar00runnerdocker#!/bin/bash commitmessage=$(git log --pretty=%B -n 1) if [[ $commitmessage = *"[ci skip]"* ]] || [[ $commitmessage = *"[skip ci]"* ]]; then echo "Skipping build because [ci skip] found in commit message" circleci step halt fi ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.codespellrc0000644000175100001660000000043014752765177014702 0ustar00runnerdocker[codespell] skip = *.asdf,*.fits,*.fts,*.header,*.json,*.xsh,*cache*,*egg*,*extern*,.git,.idea,.tox,_build,*truncated,*.svg,.asv_env,.history,*.bib ignore-words-list = alog, aas, nd, nin, observ, ot, te, upto, afile, precessed, precess ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.coveragerc0000644000175100001660000000142414752765177014527 0ustar00runnerdocker[run] omit = ndcube/conftest.py ndcube/*setup_package* ndcube/extern/* ndcube/version* */ndcube/conftest.py */ndcube/*setup_package* */ndcube/extern/* */ndcube/version* [report] exclude_lines = # Have to re-enable the standard pragma pragma: no cover # Don't complain about packages we have installed except ImportError # Don't complain if tests don't hit assertions raise AssertionError raise NotImplementedError # Don't complain about script hooks def main(.*): # Ignore branches that don't pertain to this version of Python pragma: py{ignore_python_version} # Don't complain about IPython completion helper def _ipython_key_completions_ # typing.TYPE_CHECKING is False at runtime if TYPE_CHECKING: # Ignore typing overloads @overload ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.cruft.json0000644000175100001660000000304214752765177014500 0ustar00runnerdocker{ "template": "https://github.com/sunpy/package-template", "commit": "4f11e366c6efc9dcb5658ca952ec4196e201212b", "checkout": null, "context": { "cookiecutter": { "package_name": "ndcube", "module_name": "ndcube", "short_description": "A package for multi-dimensional contiguous and non-contiguous coordinate aware arrays.", "author_name": "The SunPy Community", "author_email": "sunpy@googlegroups.com", "project_url": "https://docs.sunpy.org/projects/ndcube", "github_repo": "sunpy/ndcube", "sourcecode_url": "https://github.com/sunpy/ndcube", "download_url": "https://pypi.org/project/ndcube", "documentation_url": "https://docs.sunpy.org/projects/ndcube", "changelog_url": "https://docs.sunpy.org/projects/ndcube/en/stable/whatsnew/changelog.html", "issue_tracker_url": "https://github.com/sunpy/ndcube/issues", "license": "BSD 2-Clause", "minimum_python_version": "3.10", "use_compiled_extensions": "n", "enable_dynamic_dev_versions": "y", "include_example_code": "n", "include_cruft_update_github_workflow": "y", "use_extended_ruff_linting": "y", "_sphinx_theme": "sunpy", "_parent_project": "", "_install_requires": "", "_copy_without_render": [ "docs/_templates", "docs/_static", ".github/workflows/sub_package_update.yml" ], "_template": "https://github.com/sunpy/package-template", "_commit": "4f11e366c6efc9dcb5658ca952ec4196e201212b" } }, "directory": null } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.flake80000644000175100001660000000101614752765177013556 0ustar00runnerdocker[flake8] ignore = # missing-whitespace-around-operator E225 # missing-whitespace-around-arithmetic-operator E226 # line-too-long E501 # unused-import F401 # undefined-local-with-import-star F403 # redefined-while-unused F811 # Line break occurred before a binary operator W503, # Line break occurred after a binary operator W504 max-line-length = 110 exclude = .git __pycache__ docs/conf.py build ndcube/__init__.py rst-directives = plot ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739319944.100483 ndcube-2.3.1/.github/0000755000175100001660000000000014752765210013731 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.github/stale.yml0000644000175100001660000000316614752765177015606 0ustar00runnerdocker# Configuration for probot-stale - https://github.com/probot/stale # Probot is a bot that is run via GitHub integrations, and probot-stale is # a specific plugin that will comment on issues or pull requests that are # inactive for a certain amount of time, and add a 'stale' label. If an # issue or pull request is stale for more than a certain amount of time, # then the issue or pull request is closed. For Astropy, we use this only for # pull requests. # Number of days of inactivity before a pull request becomes stale daysUntilStale: 150 # Number of days of inactivity before a stale pull request is closed daysUntilClose: 30 # Pull requests with these labels will never be considered stale exemptLabels: [] # Label to use when marking as stale staleLabel: stale # Comment to post when marking as stale. Set to `false` to disable markComment: > This pull request has been automatically marked as stale because it has not had any activity for the past five months. It will be closed if no further activity occurs. If the ideas in this pull request are still worth implementing, please make sure you open an issue to keep track of that idea! # Comment to post when removing the stale label. Set to `false` to disable unmarkComment: false # Comment to post when closing a stale pull request. Set to `false` to disable closeComment: > This pull request has been automatically closed since there was no activity for a month since it was marked as stale. If the ideas in this pull request are still worth implementing, please make sure you open an issue to keep track of that idea! # Limit to only `issues` or `pulls` only: pulls ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739319944.100483 ndcube-2.3.1/.github/workflows/0000755000175100001660000000000014752765210015766 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.github/workflows/ci.yml0000644000175100001660000000671014752765177017124 0ustar00runnerdocker# Main CI Workflow name: CI on: push: branches: - 'main' - '*.*' - '!*backport*' tags: - 'v*' - '!*dev*' - '!*pre*' - '!*post*' pull_request: # Allow manual runs through the web UI workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: core: uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: submodules: false coverage: codecov toxdeps: tox-pypi-filter envs: | - linux: py312 secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} sdist_verify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' - run: python -m pip install -U --user build - run: python -m build . --sdist - run: python -m pip install -U --user twine - run: python -m twine check dist/* test: needs: [core, sdist_verify] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: submodules: false coverage: codecov toxdeps: tox-pypi-filter posargs: -n auto envs: | - windows: py311 - macos: py310 - linux: py310-oldestdeps secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} docs: needs: [core] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: default_python: '3.12' submodules: false pytest: false toxdeps: tox-pypi-filter libraries: | apt: - graphviz envs: | - linux: build_docs posargs: '' pytest: false libraries: apt: - libopenjp2-7 - graphviz cron: if: | github.event_name == 'workflow_dispatch' || ( github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'Run cron CI') ) uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 with: default_python: '3.12' submodules: false coverage: codecov toxdeps: tox-pypi-filter envs: | - linux: py311-devdeps secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} publish: # Build wheels on PRs only when labelled. Releases will only be published if tagged ^v.* # see https://github-actions-workflows.openastronomy.org/en/latest/publish.html#upload-to-pypi if: | github.event_name != 'pull_request' || ( github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'Run publish') ) needs: [test, docs] uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@v1 with: python-version: '3.12' test_extras: 'all,tests' test_command: 'pytest -p no:warnings --doctest-rst --pyargs ndcube' submodules: false secrets: pypi_token: ${{ secrets.pypi_token }} notify: if: always() && github.event_name == 'workflow_dispatch' needs: [publish, cron] runs-on: ubuntu-latest steps: - uses: Cadair/matrix-notify-action@main with: matrix_token: ${{ secrets.matrix_access_token }} github_token: ${{ secrets.GITHUB_TOKEN }} homeserver: ${{ secrets.matrix_homeserver }} roomid: '!TWSJXVpyflnZOzmSQz:matrix.org' ignore_pattern: '.*Load tox.*' ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.github/workflows/label_sync.yml0000644000175100001660000000147014752765177020642 0ustar00runnerdockername: Label Sync on: workflow_dispatch: schedule: # ┌───────── minute (0 - 59) # │ ┌───────── hour (0 - 23) # │ │ ┌───────── day of the month (1 - 31) # │ │ │ ┌───────── month (1 - 12 or JAN-DEC) # │ │ │ │ ┌───────── day of the week (0 - 6 or SUN-SAT) - cron: '0 0 * * *' # run every day at midnight UTC # Give permissions to write issue labels permissions: issues: write jobs: label_sync: runs-on: ubuntu-latest name: Label Sync steps: - uses: srealmoreno/label-sync-action@850ba5cef2b25e56c6c420c4feed0319294682fd with: config-file: https://raw.githubusercontent.com/sunpy/.github/main/labels.yml ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.github/workflows/scheduled_builds.yml0000644000175100001660000000142414752765177022030 0ustar00runnerdockername: Scheduled builds on: # Allow manual runs through the web UI workflow_dispatch: schedule: # ┌───────── minute (0 - 59) # │ ┌───────── hour (0 - 23) # │ │ ┌───────── day of the month (1 - 31) # │ │ │ ┌───────── month (1 - 12 or JAN-DEC) # │ │ │ │ ┌───────── day of the week (0 - 6 or SUN-SAT) - cron: '0 7 * * 1' # Every day at 07:00 UTC jobs: dispatch_workflows: runs-on: ubuntu-latest steps: - run: gh workflow run ci.yml --repo sunpy/ndcube --ref main - run: gh workflow run ci.yml --repo sunpy/ndcube --ref 2.1 env: GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }} ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.github/workflows/stale_bot.yml0000644000175100001660000000342714752765177020507 0ustar00runnerdockername: Stale Bot on: schedule: # ┌───────── minute (0 - 59) # │ ┌───────── hour (0 - 23) # │ │ ┌───────── day of the month (1 - 31) # │ │ │ ┌───────── month (1 - 12 or JAN-DEC) # │ │ │ │ ┌───────── day of the week (0 - 6 or SUN-SAT) - cron: '0 5 * * *' # Every day at 05:00 UTC jobs: stale: runs-on: ubuntu-latest steps: - uses: actions/stale@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} operations-per-run: 50 days-before-issue-stale: 99999999 # Never mark issues as stale days-before-pr-stale: 150 days-before-close: 30 stale-pr-label: 'Stale' stale-pr-message: >- Hello :wave:, Thanks for your contribution to ndcube! I have marked this pull request as stale because there hasn't had any activity in five months. If you are still working on this, or if it's waiting on a maintainer to look at it then please let us know and we will keep it open. Please add a comment with: @sunpy/ndcube-developers to get someone's attention. If nobody comments on this pull request for another month, it will be closed. close-pr-message: >- Hello again :wave:, We want to thank you again for your contribution to ndcube! This pull request has had no activity since my last reminder, so I am going to close it. If at any time you want to come back to this please feel free to reopen it! If you want to discuss this, please add a comment with: @sunpy/ndcube-developers and someone will get back to you soon. exempt-pr-labels: 'Keep Open' ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.github/workflows/sub_package_update.yml0000644000175100001660000000665014752765177022342 0ustar00runnerdocker# This template is taken from the cruft example code, for further information please see: # https://cruft.github.io/cruft/#automating-updates-with-github-actions name: Automatic Update from package template permissions: contents: write pull-requests: write on: # Allow manual runs through the web UI workflow_dispatch: schedule: # ┌───────── minute (0 - 59) # │ ┌───────── hour (0 - 23) # │ │ ┌───────── day of the month (1 - 31) # │ │ │ ┌───────── month (1 - 12 or JAN-DEC) # │ │ │ │ ┌───────── day of the week (0 - 6 or SUN-SAT) - cron: '0 7 * * 1' # Every Monday at 7am UTC jobs: update: runs-on: ubuntu-latest strategy: fail-fast: true steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install Cruft run: python -m pip install git+https://github.com/Cadair/cruft@patch-p1 - name: Check if update is available continue-on-error: false id: check run: | CHANGES=0 if [ -f .cruft.json ]; then if ! cruft check; then CHANGES=1 fi else echo "No .cruft.json file" fi echo "has_changes=$CHANGES" >> "$GITHUB_OUTPUT" - name: Run update if available id: cruft_update if: steps.check.outputs.has_changes == '1' run: | git config --global user.email "${{ github.actor }}@users.noreply.github.com" git config --global user.name "${{ github.actor }}" cruft_output=$(cruft update --skip-apply-ask --refresh-private-variables) echo $cruft_output git restore --staged . if [[ "$cruft_output" == *"Failed to cleanly apply the update, there may be merge conflicts."* ]]; then echo merge_conflicts=1 >> $GITHUB_OUTPUT else echo merge_conflicts=0 >> $GITHUB_OUTPUT fi - name: Check if only .cruft.json is modified id: cruft_json if: steps.check.outputs.has_changes == '1' run: | git status --porcelain=1 if [[ "$(git status --porcelain=1)" == " M .cruft.json" ]]; then echo "Only .cruft.json is modified. Exiting workflow early." echo "has_changes=0" >> "$GITHUB_OUTPUT" else echo "has_changes=1" >> "$GITHUB_OUTPUT" fi - name: Create pull request if: steps.cruft_json.outputs.has_changes == '1' uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.GITHUB_TOKEN }} add-paths: "." commit-message: "Automatic package template update" branch: "cruft/update" delete-branch: true draft: ${{ steps.cruft_update.outputs.merge_conflicts == '1' }} title: "Updates from the package template" labels: | No Changelog Entry Needed body: | This is an autogenerated PR, which will applies the latest changes from the [SunPy Package Template](https://github.com/sunpy/package-template). If this pull request has been opened as a draft there are conflicts which need fixing. **To run the CI on this pull request you will need to close it and reopen it.** ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.isort.cfg0000644000175100001660000000063214752765177014305 0ustar00runnerdocker[settings] balanced_wrapping = true skip = docs/conf.py ndcube/__init__.py default_section = THIRDPARTY include_trailing_comma = true known_astropy = astropy, asdf known_sunpy = sunpy known_first_party = ndcube length_sort = false length_sort_sections = stdlib line_length = 110 multi_line_output = 3 no_lines_before = LOCALFOLDER sections = STDLIB, THIRDPARTY, ASTROPY, SUNPY, FIRSTPARTY, LOCALFOLDER ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.readthedocs.yaml0000644000175100001660000000074314752765177015640 0ustar00runnerdockerversion: 2 build: os: ubuntu-lts-latest tools: python: "mambaforge-latest" jobs: post_checkout: - git fetch --unshallow || true pre_install: - git update-index --assume-unchanged .rtd-environment.yml docs/conf.py conda: environment: .rtd-environment.yml sphinx: builder: html configuration: docs/conf.py fail_on_warning: false formats: - htmlzip python: install: - method: pip extra_requirements: - docs path: . ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.rtd-environment.yml0000644000175100001660000000015314752765177016340 0ustar00runnerdockername: ndcube channels: - conda-forge dependencies: - python=3.12 - pip - graphviz!=2.42.*,!=2.43.* ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.ruff.toml0000644000175100001660000000403514752765177014324 0ustar00runnerdockertarget-version = "py310" line-length = 120 exclude = [ ".git,", "__pycache__", "build", "ndcube/version.py", ] [lint] select = [ "E", "F", "W", "UP", "PT", "BLE", "A", "C4", "INP", "PIE", "T20", "RET", "TID", "PTH", "PD", "PLC", "PLE", "FLY", "NPY", "PERF", "RUF", ] extend-ignore = [ # pycodestyle (E, W) "E501", # ignore line length will use a formatter instead # pyupgrade (UP) "UP038", # Use | in isinstance - not compatible with models and is slower # numpy "NPY002", # TODO: migrate from np.random.rand to np.random.Generator # pytest (PT) "PT001", # Always use pytest.fixture() # TODO FIX "PT011", # TODO: except(ValueRaises) is too broad "PT012", # TODO: except statement is too lengthy # "PT023", # Always use () on pytest decorators # flake8-pie (PIE) "PIE808", # Disallow passing 0 as the first argument to range # flake8-use-pathlib (PTH) "PTH123", # open() should be replaced by Path.open() # Ruff (RUF) "RUF003", # Ignore ambiguous quote marks, doesn't allow ' in comments "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` "RUF013", # PEP 484 prohibits implicit `Optional` "RUF015", # Prefer `next(iter(...))` over single element slice ] [lint.per-file-ignores] "setup.py" = [ "INP001", # File is part of an implicit namespace package. ] "conftest.py" = [ "INP001", # File is part of an implicit namespace package. ] "docs/conf.py" = [ "E402" # Module imports not at top of file ] "docs/*.py" = [ "INP001", # File is part of an implicit namespace package. ] "examples/**.py" = [ "T201", # allow use of print in examples "INP001", # File is part of an implicit namespace package. ] "__init__.py" = [ "E402", # Module level import not at top of cell "F401", # Unused import "F403", # from {name} import * used; unable to detect undefined names "F405", # {name} may be undefined, or defined from star imports ] "test_*.py" = [ "E402", # Module level import not at top of cell ] [lint.pydocstyle] convention = "numpy" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.sunpy-template.yml0000644000175100001660000000072214752765177016176 0ustar00runnerdockerdefault_context: package_name: ndcube module_name: ndcube short_description: A package for multi-dimensional contiguous and non-contiguous coordinate aware arrays. author_name: The SunPy Community author_email: sunpy@googlegroups.com license: BSD 2-Clause project_url: http://docs.sunpy.org/projects/ndcube/ github_repo: sunpy/ndcube minimum_python_version: 3.9 use_compiled_extensions: n include_example_code: n _provide_setuppy_fallback: y ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/.zenodo.json0000644000175100001660000001107214752765177014655 0ustar00runnerdocker{ "description": "ndcube is an open-source SunPy affiliated package for manipulating, inspecting and visualizing multi-dimensional contiguous and non-contiguous coordinate-aware data arrays.", "license": "BSD-2-Clause", "title": "ndcube", "upload_type": "software", "creators": [ { "name": "Daniel F. Ryan", "orcid": "0000-0001-8661-3825", "affiliation": "University College London, Mullard Space Science Laboratory (UCL/MSSL)" }, { "name": "Stuart J. Mumford", "orcid": "0000-0003-4217-4642", "affiliation": "Aperio Software Ltd." }, { "name": "Nabil Freij", "orcid": "0000-0002-6253-082X", "affiliation": "SETI Institute & Lockheed Martin Solar and Astrophysics Laboratory" }, { "name": "Yash Sharma", "orcid": "0000-0002-7861-9677", "affiliation": "Meta Platforms Inc., UK" }, { "name": "Ankit Baruah", "affiliation": "Workato Gmbh, Germany" }, { "name": "Adwait Bhope", "orcid": "0000-0002-7133-8776", "affiliation": "Uptycs India Pvt. Ltd., India" }, { "name": "Samuel Bennett", "orcid": "0000-0001-6420-4422", "affiliation": "Aperio Software Ltd." }, { "name": "Laura Hayes", "orcid": "0000-0002-6835-2390", "affiliation": "Dublin Institute of Advanced Studies (DIAS)" }, { "name": "Ricky O'Steen", "orcid": "A0000-0002-2432-8946", "affiliation": "Space Telescope Science Institute, USA" }, { "name": "Baptiste Pellorce", "affiliation": "1 - Claude Bernard Lyon 1 University, France 2 - Institute of Theoretical Astrophysics, Norway" }, { "name": "Will Barnes", "orcid": "0000-0001-9642-6089", "affiliation": "1 - NASA Goddard Space Flight Center, USA 2 - American University, USA" }, { "name": "Drew Leonard", "orcid": "0000-0001-5270-7487", "affiliation": "Aperio Software Ltd." }, { "name": "Mateo Inchaurrandieta" }, { "name": "Derek Homeier", "orcid": "0000-0002-8546-9128", "affiliation": "Aperio Software Ltd." }, { "name": "Junyan Huo", "orcid": "0000-0002-5469-7697", "affiliation": "University College London" }, { "name": "David Stansby", "orcid": "0000-0002-1365-1908", "affiliation": "Advanced Research Computing Centre, University College London, UK" }, { "name": "Shane Maloney", "orcid": "0000-0002-4715-1805", "affiliation": "Dublin Institute for Advanced Studies" }, { "name": "J. Marcus Hughes", "orcid": "0000-0003-3410-7650", "affiliation": "Southwest Research Institute, USA" }, { "name": "Kris Akira Stern", "orcid": "0000-0003-1613-8947", "affiliation": "University of Hong Kong & University of London" }, { "name": "Andrew Robbertz", "orcid": "0009-0008-6857-0882", "affiliation": "General Dynamics Mission Systems, USA" }, { "name": "Aoife Maria Ryan" }, { "name": "Gabe Shafiq" }, { "name": "Roy Smart" }, { "name": "Mihail Bankov" }, { "name": "P. L. Lim", "orcid": "0000-0003-0079-4114", "affiliation": "Space Telescope Science Institute, USA" }, { "name": "Samuel J. Van Kooten", "orcid": "0000-0002-4472-8517", "affiliation": "Southwest Research Institute" }, { "name": "Sanvi Sharma" }, { "name": "Dan F-M" }, { "name": "Kritika Ranjan", "orcid": "0000-0001-5638-016X", "affiliation": "Jain (Deemed-to-be University), Bangalore" }, { "name": "Matthew J. West", "orcid": "0000-0002-0631-2393", "affiliation": "Southwest Research Institute, USA" }, { "name": "Shelbe Timothy" } ], "access_right": "open" } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/CHANGELOG.rst0000644000175100001660000007366414752765177014446 0ustar00runnerdocker2.3.1 (2025-02-11) ================== Documentation ------------- - Fixed a typo in the docstring of `~ndcube.NDCube.data`. 2.3.0 (2025-01-14) ================== Breaking Changes ---------------- - "dimensions" property on ~ndcube.NDCube` and `~ndcube.NDCubeSequence` have been deprecated and replaced by "shape" (`#684 `__) Removals -------- - The ability to create an `.NDCollection` object with numerical keys is deprecated as it leads to ambiguous behavior when slicing the collection. (`#778 `__) New Features ------------ - Add Sliceable `~ndcube.meta.NDMeta` class for axis-associated metadata. (`#455 `__) - Added a new `~ndcube.NDCube.squeeze` method to `ndcube.NDCube`. It will remove all axes of length 1. (`#669 `__) - Added `~ndcube.NDCube.quantity` attribute to `~ndcube.NDCube` to return the data array with in the cube with the physical units stored in the `~ndcube.NDCube.unit` attribute. (`#677 `__) - Enable `~ndcube.NDCube` to be raised to a power. (`#678 `__) - Added `ndcube.NDCube.shape` as a replacement for "dimensions". (`#684 `__) - Enable rtruediv on `~ndcube.NDCube` such that a user can now do 1/ `~ndcube.NDCube`. (`#685 `__) - Add a ``keepdims=False`` kwarg to `~ndcube.NDCube.crop` and `~ndcube.NDCube.crop_by_values` setting to true keeps length-1 dimensions default behavior drops these dimensions. (`#732 `__) - When calling :meth:`ndcube.NDCubeBase.axis_world_coords` or :meth:`ndcube.NDCubeBase.axis_world_coords_values` with a specific axis or axes specified, the methods now avoid doing calculations for any other uncorrelated axes, offering significant speedups when those other axes are large. (`#767 `__) - Add support for passing ``-1`` as an element of the ``bin_shape`` argument to `.NDCube.rebin` which will not rebin along that dimension (sets the bin shape to equal the data shape). (`#777 `__) - It is now possible to set the ``NDCube.data`` property of a cube with an array of the same shape and unit as the current cube. (`#795 `__) Bug Fixes --------- - :meth:`ndcube.NDCube.rebin` ``bin_shape`` argument now accepts a `astropy.units.Quantity` as input if the units are convertible to pixels. (`#744 `__) - Fix support for astropy 7.0, this involved a change to ``CompoundLowLevelWCS`` so that in handles ``pixel_bounds`` if only one component WCS sets a pixel bound. (`#772 `__) - Fixed a bug which caused ``NDCubeSequence.cube_like_dimensions`` to break. (`#788 `__) - Added an internal code to shortcut non-correlated axes avoiding the creation of a full coordinate grid, reducing memory use in specific circumstances. (`#798 `__) Documentation ------------- - Added a gallery example (:ref:`sphx_glr_generated_gallery_creating_even_spaced_wavelength_visualisation.py`) showcasing how to create a visualisation of unevenly spaced wavelength data cube using AIA data. (`#691 `__) - Added a gallery example (:ref:`sphx_glr_generated_gallery_creating_a_gwcs_from_quantities.py`) showcasing how to create a GWCS from quantities. (`#695 `__) Internal Changes ---------------- - Move code creating a masked array for `ndcube.NDCube.rebin` to a private function which is then called by `ndcube.NDCube.rebin`. (`#705 `__) - Added explicit support for numpy 2.0. (`#729 `__) 2.2.0 (2023-11-16) ================== Backwards Incompatible Changes ------------------------------ - `ndcube.NDCollection.aligned_axes` attribute is now property. (`#607 `__) - Dropped Python 3.8 support - Increased minimum required for ``astropy`` to 5.0 - Increased minimum required for ``numpy`` to 1.21 - Increased minimum required for ``gwcs`` to 0.18. (`#636 `__) Features -------- - Provides `~ndcube.wcs.tools.unwrap_wcs_to_fitswcs`, a function to create a `astropy.wcs.WCS` instance equivalent to a sliced and/or resampled WCS instance. Only valid if the underlying implementation of the wrapped WCS instance is also an `astropy.wcs.WCS` instance. (`#649 `__) Bug Fixes --------- - Fix docstring causing doc build problems for some users. (`#600 `__) - Fixes a bug where passing a string representation of a unit to `ndcube.NDCube.to` raised a `TypeError`. (`#605 `__) - Keywords for ``sequence_axis_coords`` and ``sequence_axis_unit`` were not passed to the ``SequenceAnimator`` constructor. This is now fixed. (`#607 `__) - Adds ``None`` check on ``self.aligned_axes`` to ``NDCollection.copy()`` and ``NDCollection.pop()`` which raised a ``AttributeError`` (`#646 `__) Trivial/Internal Changes ------------------------ - Updated the error messages when missing either ``matplotlib`` or ``mpl_animators`` when creating a plot. (`#651 `__) v2.1.0 (2023-03-01) =================== Backwards Incompatible Changes ------------------------------ - To support compatibility with reproject 0.9, the API of `.NDCube.reproject_to` has been tweaked so that any keyword argument to the underlying reprojection function can be passed through. This has the effect of being a breaking change if you were specifying any arguments after ``shape_out=`` as positional rather than keyword arguments. (Note that in a future release we will probably change to require keyword arguments to ``reproject_to``. (`#552 `__) Features -------- - Implement new property, `ndcube.ExtraCoords.is_empty` that returns ``True`` if the object has got extra coords. Otherwise return ``False``. (`#450 `__) - Add `ndcube.ExtraCoords.resample` method to resample extra coordinates by a certain factor in each array dimension. (`#450 `__) - Implement a new :meth:`ndcube.NDCube.rebin` method to combine integer numbers of pixels along each axis into larger pixels. (`#450 `__) - Add new methods to interpolate lookup table coordinates: ``ndcube.extra_coords.table_coord.QuantityTableCoordinate.interpolate``, ``ndcube.extra_coords.table_coord.SkyCoordTableCoordinate.interpolate``, ``ndcube.extra_coords.table_coord.TimeTableCoordinate.interpolate``, `ndcube.extra_coords.table_coord.MultipleTableCoordinate.interpolate` (`#450 `__) - Add `ndcube.NDCubeSequence.crop` and `ndcube.NDCubeSequence.crop_by_values` methods which crop the `~ndcube.NDCubeSequence` based on input world coordinate ranges. (`#466 `__) - Add basic arithmetic methods between `~ndcube.NDCube` objects and broadcastable arrays, scalars, and `~astropy.units.Quantity` objects. Operations between two `~ndcube.NDCube` objects are not supported. (`#541 `__) - Add `ndcube.NDCube.to` to convert cube to new unit. (`#586 `__) - Created `~ndcube.GlobalCoordsABC` and updated `~ndcube.ndcube.NDCubeABC`, and `~ndcube.ExtraCoordsABC` to reflect official NDCube 2 API definition in SEP. (`#592 `__) Bug Fixes --------- - Fix bug #535 where `~ndcube.NDCollection` could not update when ``aligned_axes`` is `None` (`#538 `__) - Fix a bug where ``aligned_axis_physical_types`` caused ``__str__`` to error when ``aligned_axes`` was `None`. (`#539 `__) - Fix a bug where ``data_unit`` was not being correctly passed through to the underlying plotting function when animating a cube. (`#578 `__) Improved Documentation ---------------------- - Add example to example gallery of how to create an NDCube from a FITS file. (`#544 `__) v2.0.3 (2022-09-23) =================== Bug Fixes --------- - Dynamically copy docstring and function signature from ``ndcube.NDCube.plotter.plot`` to :meth:`ndcube.NDCube.plot`. (`#534 `__) - Fixed a bug where the ``plot_axes`` key was not respected when passing ``axes`` to ``plot`` for 2D cubes. (`#551 `__) - Limit maximum reproject version to 0.9 due to API changes. ndcube 2.1 will support the new reproject keyword arguments. (`#564 `__) v2.0.2 (2022-05-10) =================== Bug Fixes --------- - Fix a bug in the ``NDCube._as_mpl_axes`` implementation, allowing cubes with compatible dimensions to be passed as the ``projection=`` keyword argument to certain matplotlib functions again. (`#509 `__) Trivial/Internal Changes ------------------------ - Remove use of deprecated ``distutils`` module. (`#520 `__) 2.0.1 (2021-11-19) ================== Bug Fixes --------- - Enable `~ndcube.NDCollection` to accept aligned axes inputs in any integer type. (`#495 `__) - Patch to convert quantity objects passed to ``crop_by_coords`` to the units given in the ``wcs.world_axis_units``. (`#497 `__) - Fix a bug which prevented the ``axes_units=`` kwarg from working when using the matplotlib animators. (`#498 `__) - Add support for length-1 lookup table coords within extra coords. (`#499 `__) - Bump the minimum version of astropy to 4.2 to correctly support capturing dropped world dimensions into global coords when slicing the WCS. (`#500 `__) 2.0.0 (2021-10-29) ================== Backwards Incompatible Changes ------------------------------ - Remove unused util functions and the ndcube WCS class. Refactor util functions for converting between between data and WCS indices to reflect the APE14 nomenclature that distinguishes between array, pixel and world axes. (`#280 `__) - NDCubeSequence animation axes can no longer be set by extra coords. (`#294 `__) - ImageAnimatorNDCubeSequence, ImageAnimatorCubeLikeNDCubeSequence, LineAnimatorNDCubeSequence and LineAnimatorCubeLikeNDCubeSequence have been removed and replaced by NDCubeSequenceAnimator. (`#294 `__) - Change type of output of ``ndcube.NDCollection.aligned_world_axis_physical_types`` from tuple to list. This is to be consistent with output of `astropy.wcs.WCS.world_axis_physical_types`. (`#302 `__) - Change output type when common axis item is a slice that covers only one subcube. Previously this would return an NDCube. Now an NDCubeSequence is always returned unless the common axis item is an integer. Also, refactor NDCubeSequence.index_as_cube so codebase is simpler. (`#311 `__) - Replace NDCube.crop_by_coords and NDCube.crop_by_extra_coords with new method, NDCube.crop (`#316 `__) - Remove NDCubeSequence plotting. (`#322 `__) - Update `.NDCube.array_axis_physical_types` return physical types from extra coords as well as the WCS. (`#338 `__) - Rename `ndcube.ExtraCoords.add` method from previous name "add_coordinate". (`#394 `__) - The `~ndcube.NDCube` object no longer inherits from `astropy.nddata.NDArithmeticMixin` as the methods were not coordinate aware. (`#457 `__) Deprecations and Removals ------------------------- - Remove ``NDCube.pixel_to_world`` and ``NDCube.world_to_pixel``. (`#300 `__) - Remove ``world_axis_physical_types`` methods from `~ndcube.NDCube` and `~ndcube.NDCubeSequence`. (`#302 `__) - Remove ``NDCubeSequence.sequence_axis_extra_coords``. This is replaced by ``NDCubeSequence.sequence_axis_coords``. (`#335 `__) - Remove ``ndcube.NDCubeSequence.common_axis_extra_coords``. Will be replaced by `ndcube.NDCubeSequence.common_axis_coords`. (`#344 `__) - Remove ``NDCollection.aligned_world_axis_physical_types``. It will be replaced by `~ndcube.NDCollection.aligned_axis_physical_types`. (`#347 `__) Features -------- - Implement a new `ndcube.ExtraCoords` class which allows the specification of extra coordinates via lookup tables or WCS. This class exposes the extra coords as an APE 14 WCS object. (`#271 `__) - Add new method, ``ndcube.NDCube.axis_world_coord_values``, to return world coords for all pixels for all axes in WCS as quantity objects. (`#279 `__) - Added a new method `ndcube.NDCube.array_axis_physical_types` to show which physical types are associated with each array axis. (`#281 `__) - Add properties to NDCubeSequence giving the world physical types for each array axis. (`#301 `__) - Add as_mpl_axes method to NDCube plotting mixin so the an NDCube can be provided to astropy WCSAxes as a projection. (`#314 `__) - Make pyplot colorbar work with the output on NDCube.plot when it is a 2D image. (`#314 `__) - Introduce a new class, `~ndcube.global_coords.GlobalCoords`, for holding scalar coordinates that don't apply to any pixel axes. (`#323 `__) - Implement `ndcube.NDCube.axis_world_coords` which returns high level coordinate objects for all, or a subset of, axes. (`#327 `__) - New property, NDCubeSequence.sequence_axis_coords creates lists of GlobalCoords from each NDCube in the sequence. This replaces NDCubeSequence.sequence_axis_extra_coords, but because it uses the GlobaCoords infrastructure, can handle more than just coords that began as extra coords. (`#335 `__) - Implement `ndcube.NDCubeSequence.common_axis_coords` to replace ``~ndcube.NDCubeSequence.common_axis_extra_coords``. In contrast to old property, this new property collates coordinates from the wcs as well as extra_coords. (`#344 `__) - New property, `ndcube.NDCollection.aligned_axis_physical_types`. This replaces ``~ndcube.NDCollection.aligned_world_axis_physical_types`` and returns a list of tuples, where each tuple gives the physical types common between all members of the collection for a given aligned axis. (`#347 `__) - Allow `ndcube.NDCubeSequence.explode_along_axis` to explode sequence along any axis, not just the common axis. (`#358 `__) - Plotting functionality on `~ndcube.NDCube` has been refactored to use pluggable "plotter" classes. All plotting functionality can now be accessed via the `ndcube.NDCube.plotter` attribute, with `ndcube.NDCube.plot` becoming an alias for ``ndcube.NDCube.plotter.plot``. Advanced users, or package maintainers that which to customise the plotting functionality of an `~ndcube.NDCube` instance can set the ``.plotter`` attribute of a cube to be a subclass of `ndcube.visualization.BasePlotter` which then customises the behaviour of the :meth:`ndcube.NDCube.plot` method and provides any other methods implemented on the plotter. (`#401 `__) - Preserve sliced-out coordinates from WCS in the GlobalCoords instance. (`#402 `__) - Enable instantiating an NDCube from an existing NDCube by copying extra/global coords. (`#404 `__) - Support exposing dropped dimensions when `~ndcube.ExtraCoords` is sliced. (`#411 `__) - `~ndcube.ExtraCoords` is now explicitly limited to one dimensional tables because of a limitation in our use of `astropy.modeling`. (`#414 `__) - Adds functionality to reproject an `~.NDCube` object to coordinates described by another WCS or FITS Header by calling the new `~.NDCube.reproject_to` method. (`#434 `__) - Change the ``edges=`` keyword to ``pixel_corners=`` in :meth:`ndcube.NDCube.axis_world_coords` and `ndcube.NDCube.axis_world_coords_values` to make its meaning clearer based on SEP feedback. (`#437 `__) - `~.NDCube.axis_world_coords` and `~.NDCube.axis_world_coords_values` now use a different, substantially faster and more memory efficient algorithm to generate the coordinates along all axes. (`#442 `__) - Extends `ndcube.NDCube.reproject_to` functionality by supporting ``adaptive`` and ``exact`` algorithms for an `~ndcube.NDCube` with 2D celestial WCS. (`#448 `__) - Introduce optional offset between old and new pixel grids in `ndcube.wcs.wrappers.resampled_wcs.ResampledLowLevelWCS`. (`#449 `__) - `ndcube.ExtraCoords.from_lookup_tables` accepts (a sequence of) ``physical_types`` as kwarg to set the types of its ``lookup_tables``. (`#451 `__) - Create new plotter class for animating `~ndcube.NDCubeSequence` is the 2.0 framework. This class always sets the sequence axis as a slider and leverages `ndcube.NDCube.plot`. (`#456 `__) - Add ``__len__`` method to `~ndcube.NDCubeSequence` which makes ``len(sequence)`` return the number of cubes in the sequence. (`#464 `__) - Add ``__iter__`` method to `~ndcube.NDCubeSequence` which iterates through the cubes within the sequence. (`#465 `__) - Add property to `~ndcube.ExtraCoords` that returns a WCS of extra coords that describes all axes of associated cube. (`#472 `__) Bug Fixes --------- - Fix `ndcube.NDCollection.aligned_dimensions` so it does not crash when components of collection are NDCubeSequences. (`#264 `__) - Generalize int type checking so it is independent of the bit-type of the OS. (`#269 `__) - Fix ``axis_world_coord_values`` when the WCS is 1D and ensure it always returns Quantities (`#287 `__) - Change name of ``NDCube.axis_world_coord_values`` to ``NDCube.axis_world_coords_values`` to be consistent with NDCube.axis_world_coords (`#293 `__) - Remove NDCubeSequence animation dependence of deprecated sunpy ImageAnimator and LineAnimator classes in favour of ArrayAnimatorWCS class. (`#294 `__) - Fix bug whereby common axis was not updated appropriately when slicing an NDCubeSequence. (`#310 `__) - Fix bug in ``NDCube.axis_world_coords_values`` when number of pixel and world dimensions differ. (`#319 `__) - Fixes bug in `~ndcube.utils.wcs.array_indices_for_world_objects` when the WCS input does not have a world_axis_object_components attribute. The fix causes the low_level_wcs version is tried before the code fails. This enables `ndcube.NDCube.combined_wcs` to be used with this function. (`#344 `__) - Fixes IndexError in `~ndcube.utils.wcs.array_indices_for_world_objects` which occurred when some of the world axes are dependent. (`#344 `__) - Stop `ndcube.NDCube.explode_along_axis` setting a common axis to the output `~ndcube.NDCubeSequence`. The output sequence should have no common axis. (`#358 `__) - Enable 2-D NDCubes to be visualized as a 1-D animated line. (`#381 `__) - Ensure corner inputs to :meth:`ndcube.NDCube.crop` are converted to units stored in WCS as `~astropy.wcs.WCS.world_to_array_index_values` does not handle units. (`#382 `__) - updated ndcube github repository link in "ndcube.docs.installation.rst". (`#392 `__) - Fix bug in NDCube.axis_world_coords_values when axes_coords is initially a bare astropy coordinate object rather than a list/tuple of coordinate objects. (`#400 `__) - Change the implementation of `.NDCube.crop` so that it takes into account all the corners of the world region specified by the upper and lower corners, not just those two points. (`#438 `__) - Ensure `~ndcube.NDCube` init forces WCS to become high level. This patches a bug in astropy. (`#447 `__) - Fix bug in `~ndcube.NDCube.axis_world_coords_values` which caused the units to be stripped when an ``axes`` input was given. (`#461 `__) - Fix bug in `~ndcube.utils.wcs.get_dependent_world_axes` where an erroneous matrix transpose caused an error for non-square axis correlation matrices and wrong results for diagonally non-symmetric ones. (`#471 `__) - Extend support for cropping an `~ndcube.NDCube` using an `~ndcube.ExtraCoords` instance as the wcs. (`#472 `__) - Fix check as to whether user inputs to `ndcube.wcs.wrappers.compound_wcs.CompoundLowLevelWCS.world_to_pixel_values` result in consistent pixel values when world dimensions share pixel dimensions. Previously this check was unreliable when non-trivial mapping between world and pixel dimensions was used. (`#472 `__) - Fix slicing `~ndcube.ExtraCoords` made of lookup tables. This bug meant that mapping of coords to arrays axes was not adjusted when an axis was dropped. (`#482 `__) Improved Documentation ---------------------- - Document accepted input to ``lookup_table`` in `~ndcube.ExtraCoords` setting its ``physical_types``. (`#451 `__) - Improved information and formatting of ``__str__`` methods. (`#453 `__) Trivial/Internal Changes ------------------------ - Simplify and speed up implementation of NDCubeSequence slicing. (`#251 `__) - Fix docstring formatting to help docs build. (`#262 `__) - Use pytest-mpl for figure tests. (`#312 `__) - Port the tests for NDCube to use pytest fixtures (`#318 `__) - Allow corner inputs to :meth:`~ndcube.NDCube.crop` to not be wrapped in a `tuple` is only one high level coordinate objects required. (`#380 `__) - Make sunpy an optional dependence. Without it, the _animate_cube plotting functionality will be disabled. (`#393 `__) - Adds a function to compare the physical types of two WCS objects. (`#433 `__) - Propagate reference to NDCube object through `~ndcube.ExtraCoords` string slicing. (`#454 `__) - Adds a function to identify invariant axes between two WCS objects. (`#459 `__) - The matplotlib animators code has been moved from `sunpy` to a new package `mpl_animators` so ndcube no longer has an optional dependency on sunpy. (`#484 `__) 1.3.0 (2020-03-27) ================== Features -------- - Add new NDCollection class for linking and manipulating partially or non-aligned NDCubes or NDCubeSequences. (`#238 `__) Bug Fixes --------- - Fixed the files included and excluded from the tarball. (`#212 `__) - Fix crashing bug when an NDCube axis after the first is sliced with a numpy.int64. (`#223 `__) - Raises error if NDCube is sliced with an Ellipsis. (`#224 `__) - Changes behavior of NDCubeSequence slicing. Previously, a slice item of interval length 1 would cause an NDCube object to be returned. Now an NDCubeSequence made up of 1 NDCube is returned. This is consistent with how interval length 1 slice items slice arrays. (`#241 `__) 1.2.0 (2019-09-10) ================== Features -------- - Changed all instances of "missing_axis" to "missing_axes" (`#157 `__) - Added a feature to get the pixel_edges from :meth:`ndcube.NDCube.axis_world_coords` (`#174 `__) Bug Fixes --------- - `ndcube.NDCube.wcs.world_axis_physical_types ` now sets the axis label to the WCS CTYPE if no corresponding IVOA name can be found. (`#164 `__) - Fixed the bug of using ``pixel_edges`` instead of ``pixel_values`` in plotting (`#176 `__) - Fix 2D plotting from crashing when both data and WCS are 2D. (`#182 `__) - Fix the ability to pass a custom Axes to `ndcube.NDCube.plot` for a 2D cube. (`#204 `__) Trivial/Internal Changes ------------------------ - Include more helpful error when invalid item type is used to slice an `~ndcube.NDCube`. (`#158 `__) 1.1 === API-Breaking Changes -------------------- - ``~ndcube.NDCubeBase.crop_by_extra_coord`` API has been broken and replaced. Old version: ``crop_by_extra_coord(min_coord_value, interval_width, coord_name)``. New version: ``crop_by_extra_coord(coord_name, min_coord_value, max_coord_value)``. [#142] New Features ------------ - Created a new `~ndcube.NDCubeBase` which has all the functionality of `~ndcube.NDCube` except the plotting. The old ``NDCubeBase`` which outlined the `ndcube.NDCube` API was renamed ``NDCubeABC``. ``~ndcube.NDCube`` has all the same functionality as before except is now simply inherits from ``~ndcube.NDCubeBase`` and ``~ndcube.mixins.plotting.NDCubePlotMixin``. [#101] - Moved NDCubSequence plotting to a new mixin class, NDCubSequencePlotMixin, making the plotting an optional extra. All the non-plotting functionality now lives in the NDCubeSequenceBase class. [#98] - Created a new ``~ndcube.NDCubeBase.explode_along_axis`` method that breaks an NDCube out into an NDCubeSequence along a chosen axis. It is equivalent to `~ndcube.NDCubeSequenceBase.explode_along_axis`. [#118] - NDCubeSequence plot mixin can now animate a cube as a 1-D line if a single axis number is supplied to plot_axis_indices kwarg. API Changes ----------- - Replaced API of what was previously ``utils.wcs.get_dependent_axes``, with two new functions, ``utils.wcs.get_dependent_data_axes`` and ``utils.wcs.get_dependent_wcs_axes``. This was inspired by a new implementation in ``glue-viz`` which is intended to be merged into ``astropy`` in the future. This API change helped fix the ``NDCube.world_axis_physical_type`` bug listed below. [#80] - Give users more control in plotting both for NDCubePlotMixin and NDCubeSequencePlotMixin. In most cases the axes coordinates, axes units, and data unit can be supplied manually or via supplying the name of an extra coordinate if it is wanted to describe an axis. In the case of NDCube, the old API is currently still supported by will be removed in future versions. [#98 #103] Bug Fixes --------- - Allowed `~ndcube.NDCubeBase.axis_world_coords` to accept negative axis indices as arguments. [#106] - Fixed bug in ``NDCube.crop_by_coords`` in case where real world coordinate system was rotated relative to pixel grid. [#113]. - ``~ndcube.NDCubeBase.world_axis_physical_types`` is now not case-sensitive to the CTYPE values in the WCS. [#109] - ``~ndcube.NDCubeBase.plot`` now generates a 1-D line animation when image_axis is an integer. 1.0.1 ===== New Features ------------ - Added installation instructions to docs. [#77] Bug Fixes --------- - Fixed bugs in ``NDCubeSequence`` slicing and ``NDCubeSequence.dimensions`` in cases where sub-cubes contain scalar ``.data``. [#79] - Fixed ``NDCube.world_axis_physical_types`` in cases where there is a ``missing`` WCS axis. [#80] - Fixed bugs in converting between negative data and WCS axis numbers. [#91] - Add installation instruction to docs. [#77] - Fix function name called within NDCubeSequence.plot animation update plot. [#95] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/LICENSE.rst0000644000175100001660000000241314752765177014221 0ustar00runnerdockerCopyright (c) 2019-2022, The SunPy Community Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/MANIFEST.in0000644000175100001660000000070214752765177014142 0ustar00runnerdocker# Exclude specific files # All files which are tracked by git and not explicitly excluded here are included by setuptools_scm exclude .codecov.yaml exclude .mailmap exclude .gitignore exclude .pre-commit-config.yaml exclude .readthedocs.yml # Prune folders prune build prune docs/_build prune docs/api global-exclude *.pyc *.o # This subpackage is only used in development checkouts # and should not be included in built tarballs prune ndcube/_dev ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739319944.1234832 ndcube-2.3.1/PKG-INFO0000644000175100001660000001653214752765210013475 0ustar00runnerdockerMetadata-Version: 2.2 Name: ndcube Version: 2.3.1 Summary: A package for multi-dimensional contiguous and non-contiguous coordinate aware arrays. Author-email: The SunPy Community License: Copyright (c) 2024, The SunPy Community Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Project-URL: Homepage, https://docs.sunpy.org/projects/ndcube Project-URL: Source Code, https://github.com/sunpy/ndcube Project-URL: Download, https://pypi.org/project/ndcube Project-URL: Documentation, https://docs.sunpy.org/projects/ndcube Project-URL: Changelog, https://docs.sunpy.org/projects/ndcube/en/stable/whatsnew/changelog.html Project-URL: Issue Tracker, https://github.com/sunpy/ndcube/issues Requires-Python: >=3.10 Description-Content-Type: text/x-rst License-File: LICENSE.rst Requires-Dist: astropy!=5.1.0,>=5.0.6 Requires-Dist: gwcs>=0.18 Requires-Dist: numpy>=1.23.0 Requires-Dist: scipy>=1.8.0 Provides-Extra: tests Requires-Dist: dask; extra == "tests" Requires-Dist: pytest-astropy; extra == "tests" Requires-Dist: pytest-cov; extra == "tests" Requires-Dist: pytest-doctestplus; extra == "tests" Requires-Dist: pytest-mpl>=0.12; extra == "tests" Requires-Dist: pytest-xdist; extra == "tests" Requires-Dist: pytest; extra == "tests" Requires-Dist: pytest-memray; sys_platform != "win32" and extra == "tests" Requires-Dist: scipy; extra == "tests" Requires-Dist: specutils; extra == "tests" Requires-Dist: sunpy>=5.0.0; extra == "tests" Provides-Extra: docs Requires-Dist: sphinx; extra == "docs" Requires-Dist: sphinx-automodapi; extra == "docs" Requires-Dist: sunpy-sphinx-theme; extra == "docs" Requires-Dist: packaging; extra == "docs" Requires-Dist: matplotlib; extra == "docs" Requires-Dist: mpl-animators>=1.0; extra == "docs" Requires-Dist: sphinx-changelog>=1.1.0; extra == "docs" Requires-Dist: sphinx-gallery; extra == "docs" Requires-Dist: sphinxext-opengraph; extra == "docs" Requires-Dist: sunpy>=5.0.0; extra == "docs" Provides-Extra: plotting Requires-Dist: matplotlib>=3.5.0; extra == "plotting" Requires-Dist: mpl_animators>=1.0; extra == "plotting" Provides-Extra: reproject Requires-Dist: reproject>=0.7.1; extra == "reproject" Provides-Extra: all Requires-Dist: ndcube[plotting,reproject]; extra == "all" Provides-Extra: dev Requires-Dist: ndcube[docs,plotting,reproject,tests]; extra == "dev" ****** ndcube ****** |Latest Version| |codecov| |matrix| |Powered by NumFOCUS| |Powered by SunPy| .. |Latest Version| image:: https://img.shields.io/pypi/v/ndcube.svg :target: https://pypi.python.org/pypi/ndcube/ :alt: It is up to date, we promise .. |matrix| image:: https://img.shields.io/matrix/ndcube:openastronomy.org.svg?colorB=%23FE7900&label=Chat&logo=matrix&server_fqdn=openastronomy.modular.im :target: https://app.element.io/#/room/#ndcube:openastronomy.org :alt: join us on #ndcube:openastronom.org on matrix .. |codecov| image:: https://codecov.io/gh/sunpy/ndcube/branch/main/graph/badge.svg :target: https://codecov.io/gh/sunpy/sunpy :alt: Best code cov this side of mars .. |Powered by NumFOCUS| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A :target: https://numfocus.org :alt: Go give them money .. |Powered by SunPy| image:: http://img.shields.io/badge/powered%20by-SunPy-orange.svg?style=flat :target: http://www.sunpy.org :alt: SunPy .. image:: https://joss.theoj.org/papers/10.21105/joss.05296/status.svg :target: https://doi.org/10.21105/joss.05296 :alt: JOSS ``ndcube`` is an open-source SunPy affiliated package for manipulating, inspecting and visualizing multi-dimensional contiguous and non-contiguous coordinate-aware data arrays. It combines data, uncertainties, units, metadata, masking, and coordinate transformations into classes with unified slicing and generic coordinate transformations and plotting/animation capabilities. It is designed to handle data of any number of dimensions and axis types (e.g. spatial, temporal, spectral, etc.) whose relationship between the array elements and the real world can be described by World Coordinate System (WCS) translations. Usage of Generative AI ====================== We expect authentic engagement in our community. Be wary of posting output from Large Language Models or similar generative AI as comments on GitHub or any other platform, as such comments tend to be formulaic and low quality content. If you use generative AI tools as an aid in developing code or documentation changes, ensure that you fully understand the proposed changes and can explain why they are the correct approach and an improvement to the current state. Acknowledging ndcube ==================== If you use ``ndcube`` is your work, we kindly ask you to `acknowledge ndcube`_ in your publications and presentations. .. _acknowledge ndcube: https://docs.sunpy.org/projects/ndcube/en/stable/acknowledging.html Installation ============ For detailed installation instructions, see the `installation guide`_ in the ndcube docs. .. _installation guide: https://docs.sunpy.org/projects/ndcube/en/stable/installation.html Getting Help ============ For more information or to ask questions about ndcube, check out: - `ndcube Documentation`_ - `ndcube Element Channel`_ .. _ndcube Documentation: https://docs.sunpy.org/projects/ndcube/ .. _ndcube Element Channel: https://app.element.io/#/room/#ndcube:openastronomy.org Contributing ============ If you would like to get involved, check out the `Newcomers Guide`_ section of the sunpy docs. This shows how to get setup with a "sunpy" workflow but the same applies for ndcube, you will just need to replace sunpy with ndcube. Help is always welcome so let us know what you like to work on, or check out the `issues page`_ for the list of known outstanding items. .. _Newcomers Guide: https://docs.sunpy.org/en/latest/dev_guide/contents/newcomers.html .. _issues page: https://github.com/sunpy/ndcube/issues Code of Conduct =============== When you are interacting with the SunPy community you are asked to follow our `Code of Conduct`_. .. _Code of Conduct: https://sunpy.org/coc ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/README.rst0000644000175100001660000000733114752765177014100 0ustar00runnerdocker****** ndcube ****** |Latest Version| |codecov| |matrix| |Powered by NumFOCUS| |Powered by SunPy| .. |Latest Version| image:: https://img.shields.io/pypi/v/ndcube.svg :target: https://pypi.python.org/pypi/ndcube/ :alt: It is up to date, we promise .. |matrix| image:: https://img.shields.io/matrix/ndcube:openastronomy.org.svg?colorB=%23FE7900&label=Chat&logo=matrix&server_fqdn=openastronomy.modular.im :target: https://app.element.io/#/room/#ndcube:openastronomy.org :alt: join us on #ndcube:openastronom.org on matrix .. |codecov| image:: https://codecov.io/gh/sunpy/ndcube/branch/main/graph/badge.svg :target: https://codecov.io/gh/sunpy/sunpy :alt: Best code cov this side of mars .. |Powered by NumFOCUS| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A :target: https://numfocus.org :alt: Go give them money .. |Powered by SunPy| image:: http://img.shields.io/badge/powered%20by-SunPy-orange.svg?style=flat :target: http://www.sunpy.org :alt: SunPy .. image:: https://joss.theoj.org/papers/10.21105/joss.05296/status.svg :target: https://doi.org/10.21105/joss.05296 :alt: JOSS ``ndcube`` is an open-source SunPy affiliated package for manipulating, inspecting and visualizing multi-dimensional contiguous and non-contiguous coordinate-aware data arrays. It combines data, uncertainties, units, metadata, masking, and coordinate transformations into classes with unified slicing and generic coordinate transformations and plotting/animation capabilities. It is designed to handle data of any number of dimensions and axis types (e.g. spatial, temporal, spectral, etc.) whose relationship between the array elements and the real world can be described by World Coordinate System (WCS) translations. Usage of Generative AI ====================== We expect authentic engagement in our community. Be wary of posting output from Large Language Models or similar generative AI as comments on GitHub or any other platform, as such comments tend to be formulaic and low quality content. If you use generative AI tools as an aid in developing code or documentation changes, ensure that you fully understand the proposed changes and can explain why they are the correct approach and an improvement to the current state. Acknowledging ndcube ==================== If you use ``ndcube`` is your work, we kindly ask you to `acknowledge ndcube`_ in your publications and presentations. .. _acknowledge ndcube: https://docs.sunpy.org/projects/ndcube/en/stable/acknowledging.html Installation ============ For detailed installation instructions, see the `installation guide`_ in the ndcube docs. .. _installation guide: https://docs.sunpy.org/projects/ndcube/en/stable/installation.html Getting Help ============ For more information or to ask questions about ndcube, check out: - `ndcube Documentation`_ - `ndcube Element Channel`_ .. _ndcube Documentation: https://docs.sunpy.org/projects/ndcube/ .. _ndcube Element Channel: https://app.element.io/#/room/#ndcube:openastronomy.org Contributing ============ If you would like to get involved, check out the `Newcomers Guide`_ section of the sunpy docs. This shows how to get setup with a "sunpy" workflow but the same applies for ndcube, you will just need to replace sunpy with ndcube. Help is always welcome so let us know what you like to work on, or check out the `issues page`_ for the list of known outstanding items. .. _Newcomers Guide: https://docs.sunpy.org/en/latest/dev_guide/contents/newcomers.html .. _issues page: https://github.com/sunpy/ndcube/issues Code of Conduct =============== When you are interacting with the SunPy community you are asked to follow our `Code of Conduct`_. .. _Code of Conduct: https://sunpy.org/coc ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/RELEASE.rst0000644000175100001660000000127514752765177014224 0ustar00runnerdocker This release of ndcube contains 518 commits in 21 merged pull requests closing 5 issues from 12 people, 6 of which are first-time contributors to ndcube. * 518 commits have been added since 2.2 * 5 issues have been closed since 2.2 * 21 pull requests have been merged since 2.2 * 12 people have contributed since 2.2 * 6 of which are new contributors The people who have contributed to the code for this release are: - Daniel Ryan - Junyan Huo * - Laura Hayes - Mihail Bankov * - Nabil Freij - Sam Van Kooten * - Samuel Bennett * - Sanvi Sharma * - Shane Maloney * - Stuart Mumford - Will Barnes Where a * indicates that this release contains their first contribution to ndcube. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739319944.100483 ndcube-2.3.1/changelog/0000755000175100001660000000000014752765210014320 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/changelog/README.rst0000644000175100001660000000353614752765177016032 0ustar00runnerdocker========= Changelog ========= .. note:: This README was adapted from the pytest changelog readme under the terms of the MIT licence. This directory contains "news fragments" which are short files that contain a small **ReST**-formatted text that will be added to the next ``CHANGELOG``. The ``CHANGELOG`` will be read by users, so this description should be aimed at SunPy users instead of describing internal changes which are only relevant to the developers. Make sure to use full sentences with correct case and punctuation, for example:: Add support for Helioprojective coordinates in `sunpy.coordinates.frames`. Please try to use Sphinx intersphinx using backticks. Each file should be named like ``.[.].rst``, where ```` is a pull request number, ``COUNTER`` is an optional number if a PR needs multiple entries with the same type and ```` is one of: * ``breaking``: A change which requires users to change code and is not backwards compatible. (Not to be used for removal of deprecated features.) * ``feature``: New user facing features and any new behavior. * ``bugfix``: Fixes a reported bug. * ``doc``: Documentation addition or improvement, like rewording an entire session or adding missing docs. * ``removal``: Feature deprecation and/or feature removal. * ``trivial``: A change which has no user facing effect or is tiny change. So for example: ``123.feature.rst``, ``456.bugfix.rst``. If you are unsure what pull request type to use, don't hesitate to ask in your PR. Note that the ``towncrier`` tool will automatically reflow your text, so it will work best if you stick to a single paragraph, but multiple sentences and links are OK and encouraged. You can install ``towncrier`` and then run ``towncrier --draft`` if you want to get a preview of how your change will look in the final release notes. ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1739319944.102483 ndcube-2.3.1/docs/0000755000175100001660000000000014752765210013321 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/docs/1_to_2_transition_guide.rst0000644000175100001660000002236514752765177020611 0ustar00runnerdocker.. _ndcube_20_migration: ********************************* Upgrading from ``1.x`` to ``2.x`` ********************************* Why 2.0? ======== ndcube 2.0 is a major API-breaking rewrite of ndcube. It has been written to take advantage of many new features not available when ndcube 1.0 was written. Some of these have been made possible by the moving some of the functionalities of ndcube into astropy. Others are due to the fruition of long running projects such as the implementation of astropy's `WCS API (APE 14) `__ and the maturing of the `gWCS `__ package. These developments encouraged the reassessment of the state of ndcube, leading to the development of ndcube 2.0. The main feature of ndcube 2.0 is the removal and migration of almost all specific WCS handling code to astropy and the use of the astropy's WCS (APE-14) API. This has the consequence of bringing high-level coordinate objects into the realm of ndcube. This includes astropy's `~astropy.coordinates.SkyCoord` object which combines coordinate and reference frame information to give users a full description of their coordinates. However users can continue to deal with raw coordinate values without reference frame information if they so choose. ndcube's visualization code has been rewritten to exclusively use `~astropy.visualization.wcsaxes.WCSAxes`, tremendously simplifying it's implementation, at the expense of some flexibility. However, it also allows for a more complete and accurate representation of coordinates along plot axes and animations. `~ndcube.NDCube.extra_coords` has been completely re-written to serve as an extra WCS, which can be readily constructed from lookup tables. This enables users to easily include the extra coordinates when visualizing the data. Finally, a new `~ndcube.GlobalCoords` class can hold coordinates that do not refer to any axis. This is particularly useful when the dimensionality of an `~ndcube.NDCube` is reduced by slicing. The value of a coordinate at the location along the dropped axis at which the `~ndcube.NDCube` was sliced can be retained. As discussed above, the ``ndcube`` 2.0 package aims to be a framework for data with an APE-14-compliant World Coordinate System object. This large refactor and associated API changes means that if you are familiar with ``ndcube`` 1.x there is a lot which will be different. This section aims to cover the main points, if you notice anything we have forgotten please `open an issue `__. Coordinates and WCS =================== The type of the ``.wcs`` object ------------------------------- In ``ndcube`` 1.x the ``NDCube.wcs`` property was always an instance of `astropy.wcs.WCS`. This is no longer true **even if you pass such an instance to NDCube**. The reason for this is that operations like slicing may change the type of the ``.wcs`` object to represent different views into the original WCS. The ``.wcs`` property will always be an instance of `astropy.wcs.wcsapi.BaseHighLevelWCS`. You should therefore adjust any code which needs to work with any `~ndcube.NDCube` object to only use this (and associated `~astropy.wcs.wcsapi.BaseLowLevelWCS`) APIs. Future work in astropy or ndcube may increase the chances that the original WCS type be preserved, but it is highly unlikely that it will ever be possible to always carry the type of the WCS through all slicing operations. No more ``.missing_axes`` ------------------------- As a corollary to the above, there is no longer a ``.missing_axes`` property on `~ndcube.NDCube` as all the slicing operations now happen inside the ``.wcs`` property inside astropy. Dropped dimensions moved from ``.wcs`` to ``.global_coords`` ------------------------------------------------------------ As another consequence of the WCS slicing, when dimensions are dropped those world coordinates are no longer accessible through the ``.wcs``. To overcome this, and also to provide a structured place for future or custom cube-wide scalar coordinates, the ``.global_coords`` property was added. ``.global_coords`` will automatically be populated by any dimensions dropped via slicing the `~ndcube.NDCube`, via functionality in `~astropy.wcs.wcsapi.SlicedLowLevelWCS`. Scalar coordinates can also be added to the ``.global_coords`` object explicitly using the :meth:`~ndcube.GlobalCoords.add` method. The saga of ``extra_coords`` ---------------------------- As part of the transition to using APE 14 compliant WCS objects everywhere we have transitioned ``.extra_coords`` to use ``gWCS`` underneath to provide a APE-14 compliant API to the extra coords lookup tables. Due to the extra functionality and therefore complexity of the `~ndcube.ExtraCoords` object (over the previous `dict` implementation) the ``extra_coords=`` keyword argument has been removed from the `ndcube.NDCube` constructor. Extra coordinates can be added individually using the :meth:`~ndcube.ExtraCoords.add` method on the ``.extra_coords`` property. If you wish to build an `~ndcube.NDCube` object from lookup tables without a WCS object you might find the extra coords infrastructure useful. This is documented in :ref:`tabular_coordinates`. ``.wcs``, ``.extra_coords`` and ``.combined_wcs`` ------------------------------------------------- There are now three different WCS-like properties on `~ndcube.NDCube`: * ``.wcs``: The WCS object passed in through the constructor or a wrapper around it. * ``.extra_coords``: A coordinate object that can be used in place of a WCS object in `~ndcube.NDCube` methods. * ``.combined_wcs``: A WCS wrapper that combines the coordinates described by ``.wcs`` and ``.extra_coords`` into a single APE-14-compliant WCS object. Various methods on `~ndcube.NDCube` now accept a ``wcs=`` keyword argument, which allows the use of any of these attributes, the default is still ``.wcs``. In the future the default may change to ``.combined_wcs``. However, there are various technical reasons why this hasn't been done in the initial release, such as a significant performance penalty of using ``.combined_wcs``. `~ndcube.NDCube` Methods ======================== ``crop_by_coords`` is now ``crop`` and ``crop_by_values`` --------------------------------------------------------- The old ``NDCube.crop_by_coords`` method has been replaced with two new methods `ndcube.NDCube.crop` and `ndcube.NDCube.crop_by_values`. The new methods accept high-level (e.g. `~astropy.coordinates.SkyCoord`) objects and quantities respectively. The new methods also use a different algorithm to ``crop_by_coords``, which has been selected to work with data of all dimensionality and coordinates. Both the crop methods take N points as positional arguments where each point must have an entry for each world axis. The cube will then be cropped to the smallest pixel box containing the input points. Note that in this algorithm the input points are not interpreted as corners of a bounding box, although is some cases the result will be equivalent to that interpretation. For more information see :ref:`ndcube_crop`. ``.world_to_pixel`` and ``.pixel_to_world`` removed --------------------------------------------------- As part of the transition to relying on APE-14-compliant WCS objects ``NDCube.world_to_pixel`` and ``pixel_to_world`` are now redundant as the APE-14-WCS API specifies that the WCS object must provide these methods with equivalent functionality. Therefore you should now use ``NDCube.wcs.pixel_to_world`` and ``NDCube.wcs.world_to_pixel``; in addition to this you can also make use of the ``_values`` or ``array_index`` variants of these methods (see `~astropy.wcs.wcsapi.BaseLowLevelWCS`). Removed Arithmetic Operations ----------------------------- During the rewrite the decision was taken for `ndcube.NDCube` not inherit the `astropy.nddata.NDArithmeticMixin` class. The primary reason for this is that the operations supported by this mixin are not coordinate aware. It is intended that in the future, `~ndcube.NDCube` will support operations such as add and subtract with scalars and array-like objects. Future support for arithmetic operations between coordinate-aware objects will involve first checking that pixel grids are aligned. Visualization Changes ===================== The final major change in 2.0 is a rework of the built in visualization tooling in ndcube. While the visualization code in 1.x was very powerful, that power came with a very high level of complexity, which made maintaining that functionality difficult. When we were migrating ndcube to use the new WCS APIs we needed to modify large amounts of the existing visualization code, which just became untenable with the amount of time available. We therefore took the decision to significantly reduce the scope of the built in visualization functionality. The visualization code included in 2.0 only uses `~astropy.visualization.wcsaxes`, which means that **all plots are made in pixel space** with ticks and gridlines overplotted to show world coordinates. This has dramatically simplified the code in ndcube, as almost all the complexity is now delegated to ``wcsaxes``. In addition to this we have made it easier for users and developers to replace, customize, or disable the built in functionality by use of the ``.plotter`` attribute. Learn more in :ref:`customizing_plotter`. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/docs/Makefile0000644000175100001660000000117214752765177014776 0ustar00runnerdocker# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/docs/acknowledging.rst0000644000175100001660000000217114752765177016704 0ustar00runnerdocker.. _acknowledging: ************************ Acknowledging ``ndcube`` ************************ If you use ``ndcube``, we kindly ask you to cite the following references in you publications: * Ryan, Mumford et al., ndcube: Manipulating N-dimensional Astronomical Data in Python, Journal of Open Source Software, 2023a, DOI: https://doi.org/10.21105/joss.05296 * Ryan, Mumford et al., A Unified Framework for Manipulating N-dimensional Astronomical Data and Coordinate Transformations in Python: The NDCube 2 & Astropy APE-14 WCS APIs, Astrophysical Journal, 2023b, DOI: https://doi.org/10.3847/1538-4357/ace0bd Citing these references helps to spread awareness of ``ndcube``'s capabilities and philosophy and gives some credit to those who have volunteered their time in making ``ndcube`` possible. To learn how to become part of the ``ndcube`` project, see :ref:`contributing`. You may also like to include the `ndcube logo`_ in your presentations. This helps to publicise ``ndcube`` to others who might find it helpful in their work. .. _ndcube logo: https://github.com/sunpy/ndcube/tree/ee94395cda5c8348a33bd1f9ff75fab976bdc66f/docs/logo ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/docs/conf.py0000644000175100001660000001407014752765177014636 0ustar00runnerdocker# # Configuration file for the Sphinx documentation builder. import os import warnings import datetime from pathlib import Path from astropy.utils.exceptions import AstropyDeprecationWarning from matplotlib import MatplotlibDeprecationWarning from packaging.version import Version # -- Read the Docs Specific Configuration ------------------------------------ on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if on_rtd: os.environ['HIDE_PARFIVE_PROGESS'] = 'True' # -- Project information ----------------------------------------------------- # The full version, including alpha/beta/rc tags from ndcube import __version__ _version = Version(__version__) version = release = str(_version) # Avoid "post" appearing in version string in rendered docs if _version.is_postrelease: version = release = _version.base_version # Avoid long githashes in rendered Sphinx docs elif _version.is_devrelease: version = release = f"{_version.base_version}.dev{_version.dev}" is_development = _version.is_devrelease is_release = not (_version.is_prerelease or _version.is_devrelease) project = "ndcube" author = "The SunPy Community" copyright = f'{datetime.datetime.now().year}, {author}' # noqa: A001 warnings.filterwarnings("error", category=MatplotlibDeprecationWarning) warnings.filterwarnings("error", category=AstropyDeprecationWarning) # -- General configuration --------------------------------------------------- extensions = [ 'matplotlib.sphinxext.plot_directive', 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.inheritance_diagram', 'sphinx.ext.viewcode', 'sphinx.ext.napoleon', 'sphinx.ext.doctest', 'ndcube.utils.sphinx.code_context', 'sphinx_gallery.gen_gallery', "sphinxext.opengraph", "sphinx.ext.mathjax", "sphinx_automodapi.automodapi", "sphinx_automodapi.smart_resolver", "sphinx_changelog", ] # Add any paths that contain templates here, relative to this directory. # templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: source_suffix = ".rst" # The master toctree document. master_doc = "index" # Treat everything in single ` as a Python reference. default_role = "py:obj" # -- Options for intersphinx extension --------------------------------------- intersphinx_mapping = { 'python': ('https://docs.python.org/3/', (None, 'http://data.astropy.org/intersphinx/python3.inv')), 'numpy': ('https://docs.scipy.org/doc/numpy/', (None, 'http://data.astropy.org/intersphinx/numpy.inv')), 'matplotlib': ('https://matplotlib.org/', (None, 'http://data.astropy.org/intersphinx/matplotlib.inv')), 'astropy': ('http://docs.astropy.org/en/stable/', None), 'sunpy': ('https://docs.sunpy.org/en/stable/', None), 'mpl_animators': ('https://docs.sunpy.org/projects/mpl-animators/en/stable/', None), 'gwcs': ('https://gwcs.readthedocs.io/en/stable/', None), 'reproject': ("https://reproject.readthedocs.io/en/stable/", None) } # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = "sunpy" html_logo = png_icon = 'logo/ndcube.png' html_favicon = 'logo/favicon.png' # Render inheritance diagrams in SVG graphviz_output_format = "svg" graphviz_dot_args = [ "-Nfontsize=10", "-Nfontname=Helvetica Neue, Helvetica, Arial, sans-serif", "-Efontsize=10", "-Efontname=Helvetica Neue, Helvetica, Arial, sans-serif", "-Gfontsize=10", "-Gfontname=Helvetica Neue, Helvetica, Arial, sans-serif", ] # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ["_static"] # By default, when rendering docstrings for classes, sphinx.ext.autodoc will # make docs with the class-level docstring and the class-method docstrings, # but not the __init__ docstring, which often contains the parameters to # class constructors across the scientific Python ecosystem. The option below # will append the __init__ docstring to the class-level docstring when rendering # the docs. For more options, see: # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autoclass_content autoclass_content = "both" # -- Other options ---------------------------------------------------------- napoleon_use_rtype = False napoleon_google_docstring = False napoleon_use_param = False nitpicky = True # This is not used. See docs/nitpick-exceptions file for the actual listing. nitpick_ignore = [] for line in open('nitpick-exceptions'): if line.strip() == "" or line.startswith("#"): continue dtype, target = line.split(None, 1) target = target.strip() nitpick_ignore.append((dtype, target)) # -- Sphinx Gallery --------------------------------------------------------- sphinx_gallery_conf = { 'backreferences_dir': Path('generated/modules'), 'filename_pattern': '^((?!skip_).)*$', 'examples_dirs': Path('../examples'), 'within_subsection_order': "ExampleTitleSortKey", 'gallery_dirs': Path('generated/gallery'), 'matplotlib_animations': True, "default_thumb_file": png_icon, 'abort_on_example_error': False, 'plot_gallery': 'True', 'remove_config_comments': True, 'doc_module': ('ndcube'), 'only_warn_on_example_error': True, } # -- Sphinxext Opengraph ---------------------------------------------------- ogp_image = "https://github.com/sunpy/ndcube/raw/main/docs/logo/ndcube.png" ogp_use_first_image = True ogp_description_length = 160 ogp_custom_meta_tags = [ '', ] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1739319944.1044831 ndcube-2.3.1/docs/explaining_ndcube/0000755000175100001660000000000014752765210016777 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1739319935.0 ndcube-2.3.1/docs/explaining_ndcube/coordinates.rst0000644000175100001660000006036414752765177022070 0ustar00runnerdocker.. _coordinates: ************************** Coordinate transformations ************************** Introduction to WCS =================== To describe the mapping between array elements/pixels and real world coordinates, `ndcube` heavily leverages the World Coordinate System (WCS) framework, specifically the tools written by Astropy that implement this framework in Python. WCS allows a wide variety of projections, rotations and transformations be stored and executed. Because it allows coordinates transformations to be stored functionally, rather than in memory-heavy lookup tables, and because it caters for both astronomy-specific coordinate systems (e.g. RA & Dec.) as well as simpler, more common ones (e.g. wavelength), WCS has become the most common coordinate transformation framework in astronomy. The most commonly used WCS implementation in Python is the `astropy.wcs.WCS` object, which stores critical information describing the coordinate transformations as required by the FITS data model (e.g. the reference pixel and its corresponding coordinate values, ``CRPIX`` and ``CRVAL``, and the projection type, ``CTYPE`` etc.). It also executes these transformations via methods like `~astropy.wcs.WCS.world_to_pixel` and `~astropy.wcs.WCS.pixel_to_world` which convert between pixel indices and world coordinate values. However, these methods are independent of the data array and the `~astropy.wcs.WCS` object carries little or no information about the data itself. That is why the `ndcube` package is needed. Nonetheless, astropy's WCS implementation is a crucial pillar of `ndcube`, as is the more generalized offshoot, `gWCS `__, which provides greater generalization outside of the FITS data model. Crucially though for `ndcube`, both implementations adhere to the `Astropy WCS API `__. A familiarity with WCS and the Astropy and gWCS Python implementations will be helpful (although hopefully not essential) in understanding this guide. We therefore encourage users to read `Astropy's WCS guide `__ and the `gWCS documentation `__ to learn more. In this section we will discuss the features `ndcube` has built upon these implementations to support the integration of data and coordinates. .. _cube_coordinates: NDCube coordinates ================== Although WCS objects are a powerful and concise way of storing complex functional coordinate transformations, their API can be cumbersome when the coordinates along a whole axis are desired. Making this process easy and intuitive is the purpose of the :meth:`ndcube.NDCube.axis_world_coords` method. Using the attached WCS object, information on the data dimensions, and optional inputs from the user, this method returns high level coordinate objects --- e.g. `~astropy.coordinates.SkyCoord`, `~astropy.time.Time`, `~astropy.coordinates.SpectralCoord`, `~astropy.units.Quantity` --- containing the coordinates for each array element. Say we have a 3-D `~ndcube.NDCube` with a shape of ``(4, 4, 5)`` and physical types of space, space, wavelength. Now let's say we want the wavelength values along the spectral axis. We can do this in a couple ways. First we can provide :meth:`~ndcube.NDCube.axis_world_coords` with the array axis number of the spectral axis. .. expanding-code-block:: python :summary: Click to reveal/hide instantiation of the NDCube. >>> import astropy.wcs >>> import numpy as np >>> from ndcube import NDCube >>> # Define data array. >>> data = np.random.rand(4, 4, 5) >>> # Define WCS transformations in an astropy WCS object. >>> wcs = astropy.wcs.WCS(naxis=3) >>> wcs.wcs.ctype = 'WAVE', 'HPLT-TAN', 'HPLN-TAN' >>> wcs.wcs.cunit = 'Angstrom', 'deg', 'deg' >>> wcs.wcs.cdelt = 0.2, 0.5, 0.4 >>> wcs.wcs.crpix = 0, 2, 2 >>> wcs.wcs.crval = 10, 0.5, 1 >>> # Now instantiate the NDCube >>> my_cube = NDCube(data, wcs=wcs) .. code-block:: python >>> my_cube.axis_world_coords(2) (,) Alternatively we can provide a unique substring of the physical type of the coordinate, stored in `ndcube.NDCube.wcs.world_axis_physical_types `: .. code-block:: python >>> my_cube.wcs.world_axis_physical_types ['em.wl', 'custom:pos.helioprojective.lat', 'custom:pos.helioprojective.lon'] >>> # Since 'wl' is unique to the wavelength axis name, let's use that. >>> my_cube.axis_world_coords('wl') (,) As discussed above, some WCS axes are not independent. For those axes, :meth:`~ndcube.NDCube.axis_world_coords` returns objects with the same number of dimensions as dependent axes. For example, helioprojective longitude and latitude are dependent. Therefore if we ask for longitude, we will get back a `~astropy.coordinates.SkyCoord` containing 2-D latitude and longitude arrays with the same shape as the array axes to which they correspond. For example: .. code-block:: python >>> celestial = my_cube.axis_world_coords('lon')[0] # Must extract object from returned tuple with [0] >>> my_cube.shape (4, 4, 5) >>> celestial.shape (4, 4) >>> celestial It is also possible to request more than one axis's world coordinates by setting ``axes`` to an iterable of data axis number and/or axis type strings. The coordinate objects are returned in world axis order. .. code-block:: python >>> my_cube.axis_world_coords(2, 'lon') (, ) If the user wants the world coordinates for all the axes, the ``axes`` arg can set to `None` or simply omitted. .. code-block:: python >>> my_cube.axis_world_coords() (, ) By default :meth:`~ndcube.NDCube.axis_world_coords` returns the coordinates at the center of each pixel. However, the coordinates at the edges of each pixel can be obtained by setting the ``pixel_corners`` keyword argument to `True`. For example: .. code-block:: python >>> my_cube.axis_world_coords(pixel_corners=True) (, ) Working with raw coordinates ---------------------------- If users would prefer not to deal with high level coordinate objects, they can elect to use `ndcube.NDCube.axis_world_coords_values`. The API for this method is the same as :meth:`~ndcube.NDCube.axis_world_coords`. The only difference is that a `~collections.namedtuple` of `~astropy.units.Quantity` objects are returned, one for each physical type requested. In the above case this means that there would be separate `~astropy.units.Quantity` objects for latitude and longitude, but they would both have the same 2-D shape. The `~astropy.units.Quantity` objects are returned in world order and correspond to the physical types in the `astropy.wcs.WCS.world_axis_physical_types`. The `~astropy.units.Quantity` objects do not contain important contextual information, such as reference frame, which is needed to fully interpret the coordinate values. However for some use cases this level of completeness is not needed. .. code-block:: python >>> my_cube.axis_world_coords_values() CoordValues(custom_pos_helioprojective_lon=, custom_pos_helioprojective_lat=, em_wl=) .. _extra_coords: ExtraCoords =========== So far we have seen how `~ndcube.NDCube` uses its WCS object (``NDCube.wcs``) to store and perform coordinates transformations. But what if we have alternative or additional coordinates that are not represented by the WCS? For example, say we have a raster scan from a scanning slit spectrograph whose x-axis is folded in with time. This occurs because the x-axis is built up over sequential exposures taken at different slit positions. Our ``NDCube.wcs`` might describe latitude and longitude, but omit time. So how can we represent time without having to construct a whole new custom WCS object? One way is to use the `ndcube.ExtraCoords` class located at `ndcube.NDCube.extra_coords`. It provides a mechanism of attaching coordinates to `~ndcube.NDCube` instances in addition to those in the primary WCS object. This may be desired because, as above, the primary WCS omits a physical type. Or it may be that the users have an alternative set of coordinates to the primary set at ``.wcs``. To demonstrate how to use `~ndcube.ExtraCoords`, let's start by creating a `~astropy.time.Time` object representing the time at each location along the first axis of ``my_cube``. .. code-block:: python >>> from astropy.time import Time, TimeDelta >>> base_time = Time('2000-01-01', format='fits', scale='utc') >>> timestamps = Time([base_time + TimeDelta(60 * i, format='sec') for i in range(data.shape[0])]) By default an `~ndcube.NDCube` is instantiated with an empty `~ndcube.ExtraCoords` object. So let's add a time coordinate to the `~ndcube.ExtraCoords` instance at ``my_cube.extra_coords``. To do this we need to supply the physical type of the coordinate, the array axis to which is corresponds, and the values of the coordinate. The number of values should equal the axis's length (or shape if it corresponds to more than one axis) and the physical type must be a valid `IVOA UCD1+ controlled words `__ word. If one does not exist for your coordinate, prepend the type with ``custom:``. .. code-block:: python >>> my_cube.extra_coords.add('time', (0,), timestamps) An indefinite number of coordinates can be added in this way. The names of the coordinates can be accessed via the `~ndcube.ExtraCoords.keys` method. .. code-block:: python >>> my_cube.extra_coords.keys() ('time',) The physical types of extra coordinates are also returned by `~ndcube.NDCube.array_axis_physical_types`. .. code-block:: python >>> my_cube.array_axis_physical_types [('custom:pos.helioprojective.lat', 'custom:pos.helioprojective.lon', 'time'), ('custom:pos.helioprojective.lat', 'custom:pos.helioprojective.lon'), ('em.wl',)] The values of the extra coordinates at each array index can be retrieved using and combination of :meth:`ndcube.NDCube.axis_world_coords` and `ndcube.NDCube.combined_wcs`. See :ref:`combined_wcs` below. .. _combined_wcs: Combined WCS ------------ The `~ndcube.NDCube.combined_wcs` generates a WCS that combines the extra coords with those stored in the primary WCS. Unlike `ndcube.ExtraCoords.wcs`, `~ndcube.NDCube.combined_wcs` is a valid WCS for describing the `~ndcube.NDCube` data array and so can be used with the `~ndcube.NDCube` coordinate transformation and plotting features, e.g: .. code-block:: python >>> my_cube.axis_world_coords(wcs=my_cube.combined_wcs) (, ,