diff --git a/.github/workflows/ci_cron_weekly.yml b/.github/workflows/ci_cron_weekly.yml index f705f708c..2293e3085 100644 --- a/.github/workflows/ci_cron_weekly.yml +++ b/.github/workflows/ci_cron_weekly.yml @@ -1,7 +1,7 @@ # GitHub Actions workflow that runs on a cron schedule. # Check URLs and run latest deps with remote tests -# Remove -numpy126 when we support testing with numpy 2.0 +# Restore testing with pyoorb when it supports Python 3.12+ name: Weekly CI Tests @@ -19,10 +19,10 @@ env: IS_CRON: "true" jobs: - oorb-data: - uses: ./.github/workflows/oorb_data.yml + # oorb-data: + # uses: ./.github/workflows/oorb_data.yml tests: - needs: [oorb-data] + # needs: [oorb-data] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -31,16 +31,16 @@ jobs: ARCH_ON_CI: "normal" IS_CRON: "true" OORB_DATA: "$GITHUB_WORKSPACE/oorb-data/" - cache-path: oorb-data/ - cache-key: oorb-data + # cache-path: oorb-data/ + # cache-key: oorb-data submodules: false coverage: "" envs: | - name: Link check linux: linkcheck - - name: Python 3.13 with dev versions of key dependencies - linux: py313-test-devdeps-cov + - name: Python 3.14 with dev versions of key dependencies + linux: py314-test-devdeps-cov posargs: --verbose allowed_failures: @@ -48,6 +48,6 @@ jobs: with: submodules: false envs: | - - name: Python 3.11 with all optional dependencies and remote data - linux: py311-test-numpy126-alldeps + - name: Python 3.14 with all optional dependencies and remote data + linux: py314-test-alldeps posargs: --remote-data --verbose diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 3128e411c..024f038d3 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -2,8 +2,7 @@ # # This file performs testing using tox and tox.ini to define and configure the test environments. -# Remove -numpy126 when we support testing with numpy 2.0 -# Allow testing of optional dependencies on Python 3.12+ when pyoorb is updated. +# Restore testing with pyoorb when it supports Python 3.12+ name: CI Tests @@ -26,10 +25,10 @@ env: IS_CRON: "false" jobs: - oorb-data: - uses: ./.github/workflows/oorb_data.yml + # oorb-data: + # uses: ./.github/workflows/oorb_data.yml tests: - needs: [oorb-data] + # needs: [oorb-data] uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1 secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -38,47 +37,47 @@ jobs: ARCH_ON_CI: "normal" IS_CRON: "false" OORB_DATA: "$GITHUB_WORKSPACE/oorb-data/" - cache-path: oorb-data/ - cache-key: oorb-data + # cache-path: oorb-data/ + # cache-key: oorb-data submodules: false coverage: "" envs: | - name: Code style checks linux: codestyle - - name: Python 3.13 with minimal dependencies, measuring coverage - linux: py313-test-cov + - name: Python 3.14 with minimal dependencies, measuring coverage + linux: py314-test-cov coverage: codecov - - name: Python 3.11 with all optional dependencies, measuring coverage - linux: py311-test-numpy126-alldeps-cov + - name: Python 3.14 with all optional dependencies, measuring coverage + linux: py314-test-alldeps-cov coverage: codecov - - name: Python 3.9 with oldest supported versions, measuring coverage - linux: py39-test-oldestdeps-cov + - name: Python 3.10 with oldest supported versions, measuring coverage + linux: py310-test-oldestdeps-cov coverage: codecov macos-test: - name: Python 3.11 with all optional dependencies (MacOS) - needs: [oorb-data] - runs-on: macos-13 + name: Python 3.14 with all optional dependencies (MacOS) + # needs: [oorb-data] + runs-on: macos-latest steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Restore cached files - uses: actions/cache/restore@v4 - with: - path: oorb-data/ - key: oorb-data - - name: Set environment - run: | - echo "OORB_DATA=$GITHUB_WORKSPACE/oorb-data" >> "$GITHUB_ENV" + # - name: Restore cached files + # uses: actions/cache/restore@v4 + # with: + # path: oorb-data/ + # key: oorb-data + # - name: Set environment + # run: | + # echo "OORB_DATA=$GITHUB_WORKSPACE/oorb-data" >> "$GITHUB_ENV" - name: Set up Python uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: 3.14 - name: Install tox run: | pip install tox - name: Run tests run: | - tox -e py311-test-numpy126-alldeps + tox -e py314-test-alldeps diff --git a/.gitignore b/.gitignore index 2c6f41447..6b6a97d47 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ __pycache__ *.c # Other generated files -sbpy/version.py sbpy/_version.py */cython_version.py htmlcov diff --git a/.readthedocs.yaml b/.readthedocs.yaml index abbfa242d..3ecd8b97a 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,9 +5,9 @@ version: 2 build: - os: ubuntu-20.04 + os: ubuntu-24.04 tools: - python: "3.10" + python: "3.13" apt_packages: - graphviz jobs: diff --git a/CHANGES.rst b/CHANGES.rst index 1fc5b0f55..e94b8da28 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,10 @@ +v0.7.0 (unreleased) +=================== + +Update supported versions [#427]: +- Python >= 3.10 + + v0.6.0 (2025-12-02) =================== diff --git a/LICENSE.rst b/LICENSE.rst index 0317b051b..ec2cabb4c 100644 --- a/LICENSE.rst +++ b/LICENSE.rst @@ -1,4 +1,4 @@ -Copyright (c) 2017-2024, sbpy team +Copyright (c) 2017-2025, sbpy team All rights reserved. sbpy uses a 3-Clause BSD License: diff --git a/MANIFEST.in b/MANIFEST.in index 9df0d3f83..8be1f6f92 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ include README.rst include CHANGES.rst -include setup.cfg include LICENSE.rst include pyproject.toml @@ -12,6 +11,7 @@ recursive-include docs * recursive-include licenses * recursive-include scripts * +prune sbpy/_dev prune build prune docs/_build prune docs/api diff --git a/docs/_static/sbpy_banner_96.png b/docs/_static/sbpy_banner_96.png new file mode 120000 index 000000000..97456b24b --- /dev/null +++ b/docs/_static/sbpy_banner_96.png @@ -0,0 +1 @@ +../../logo/sbpy_banner_96.png \ No newline at end of file diff --git a/docs/_static/sbpy_banner_dark_96.png b/docs/_static/sbpy_banner_dark_96.png new file mode 120000 index 000000000..a6319c91b --- /dev/null +++ b/docs/_static/sbpy_banner_dark_96.png @@ -0,0 +1 @@ +../../logo/sbpy_banner_dark_96.png \ No newline at end of file diff --git a/docs/_static/sbpy_logo.ico b/docs/_static/sbpy_logo.ico new file mode 120000 index 000000000..26e77a3f3 --- /dev/null +++ b/docs/_static/sbpy_logo.ico @@ -0,0 +1 @@ +../../logo/sbpy_logo.ico \ No newline at end of file diff --git a/docs/_static/sbpy_logo.png b/docs/_static/sbpy_logo.png new file mode 120000 index 000000000..77af27f10 --- /dev/null +++ b/docs/_static/sbpy_logo.png @@ -0,0 +1 @@ +../../logo/sbpy_logo.png \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 85b64215a..2ff364cd6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,6 @@ -# -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst # -# Astropy documentation build configuration file. +# Based on Astropy documentation build configuration file. # # This file is execfile()d with the current directory set to its containing dir. # @@ -26,41 +25,113 @@ # be accessible, and the documentation will not build correctly. import datetime -import os import sys +import tomllib +from importlib import metadata +from packaging.requirements import Requirement +from packaging.specifiers import SpecifierSet +from pathlib import Path import matplotlib +from sphinx.util import logging matplotlib.use("agg") -try: - from sphinx_astropy.conf.v1 import * -except ImportError: - print( - "ERROR: the documentation requires the sphinx-astropy package to be" - " installed" +logger = logging.getLogger(__name__) + +# Get configuration information from pyproject.toml +with (Path(__file__).parents[1] / "pyproject.toml").open("rb") as f: + pyproject = tomllib.load(f) + +# -- Check for missing dependencies ------------------------------------------- + +missing_requirements = {} +for line in metadata.requires("sbpy"): + if 'extra == "docs"' in line: + req = Requirement(line.split(";")[0]) + req_package = req.name.lower() + req_specifier = str(req.specifier) + + try: + version = metadata.version(req_package) + except metadata.PackageNotFoundError: + missing_requirements[req_package] = req_specifier + + if version not in SpecifierSet(req_specifier, prereleases=True): + missing_requirements[req_package] = req_specifier + +if missing_requirements: + msg = ( + "The following packages could not be found and are required to " + "build the documentation:\n" + "%s" + '\nPlease install the "docs" requirements.', + "\n".join([f" * {key} {val}" for key, val in missing_requirements.items()]), ) + logger.error(msg) sys.exit(1) -# Get configuration information from setup.cfg -from configparser import ConfigParser # noqa: E402 -conf = ConfigParser() +from sphinx_astropy.conf.v1 import ( # noqa: E402 + exclude_patterns, + extensions, + intersphinx_mapping, + numpydoc_xref_aliases, + numpydoc_xref_astropy_aliases, + numpydoc_xref_ignore, + rst_epilog, +) -conf.read([os.path.join(os.path.dirname(__file__), "..", "setup.cfg")]) -setup_cfg = dict(conf.items("metadata")) +# -- Plot configuration ------------------------------------------------------- +plot_rcparams = { + "axes.labelsize": "large", + "figure.figsize": (6, 6), + "figure.subplot.hspace": 0.5, + "savefig.bbox": "tight", + "savefig.facecolor": "none", +} +plot_apply_rcparams = True +plot_html_show_source_link = False +plot_formats = ["png", "svg", "pdf"] +# Don't use the default - which includes a numpy and matplotlib import +plot_pre_code = "" # -- General configuration ---------------------------------------------------- +# The intersphinx_mapping in sphinx_astropy.sphinx refers to astropy for +# the benefit of other packages who want to refer to objects in the +# astropy core. However, we don't want to cyclically reference astropy in its +# own build so we remove it here. +del intersphinx_mapping["astropy"] + +# add any custom intersphinx for astropy +intersphinx_mapping.update( + { + "sbpy-dev": ("https://docs.astropy.org/en/latest/", None), + "astroquery": ("https://astroquery.readthedocs.io/en/stable/", None), + "synphot": ("https://synphot.readthedocs.io/en/stable/", None), + "astropy": ("https://docs.astropy.org/en/stable/", None), + } +) + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# .inc.rst mean *include* files, don't have sphinx process them +exclude_patterns += ["_templates", "changes", "_pkgtemplate.rst", "**/*.inc.rst"] + +# Add any paths that contain templates here, relative to this directory. +if "templates_path" not in locals(): # in case parent conf.py defines it + templates_path = [] +templates_path.append("_templates") + +extensions += ["sphinx_changelog"] + # By default, highlight as Python 3. highlight_language = "python3" +highlight_language = "python3" # If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.2' - -# To perform a Sphinx version check that needs to be more specific than -# major.minor, call `check_sphinx_version("x.y.z")` here. -# check_sphinx_version("1.2.1") +needs_sphinx = "3.0" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -76,6 +147,11 @@ "sphinx_automodapi.smart_resolver", "sphinx.ext.autosectionlabel", ] +extensions += [ + "sphinx.ext.intersphinx", + "sphinx_automodapi.smart_resolver", + "sphinx.ext.autosectionlabel", +] # For example, index:Introduction for a section called Introduction that # appears in document index.rst. @@ -86,25 +162,78 @@ autodoc_inherit_docstrings = False +# Whether to create cross-references for the parameter types in the +# Parameters, Other Parameters, Returns and Yields sections of the docstring. +numpydoc_xref_param_type = True + +# Words not to cross-reference. Most likely, these are common words used in +# parameter type descriptions that may be confused for classes of the same +# name. The base set comes from sphinx-astropy. We add more here. +numpydoc_xref_ignore.update( + { + "mixin", + "Any", # aka something that would be annotated with `typing.Any` + # needed in subclassing numpy # TODO! revisit + "Arguments", + "Path", + # TODO! not need to ignore. + "flag", + "bits", + } +) + +# Mappings to fully qualified paths (or correct ReST references) for the +# aliases/shortcuts used when specifying the types of parameters. +# Numpy provides some defaults +# https://github.com/numpy/numpydoc/blob/b352cd7635f2ea7748722f410a31f937d92545cc/numpydoc/xref.py#L62-L94 +# and a base set comes from sphinx-astropy. +# so here we mostly need to define Astropy-specific x-refs +numpydoc_xref_aliases.update( + { + # python & adjacent + "Any": "`~typing.Any`", + "file-like": ":term:`python:file-like object`", + "file": ":term:`python:file object`", + "path-like": ":term:`python:path-like object`", + "module": ":term:`python:module`", + "buffer-like": ":term:buffer-like", + "hashable": ":term:`python:hashable`", + # for matplotlib + "color": ":term:`color`", + # for numpy + "ints": ":class:`python:int`", + # for astropy + "number": ":term:`number`", + "Representation": ":class:`~astropy.coordinates.BaseRepresentation`", + "writable": ":term:`writable file-like object`", + "readable": ":term:`readable file-like object`", + "BaseHDU": ":doc:`HDU `", + } +) +# Add from sphinx-astropy 1) glossary aliases 2) physical types. +numpydoc_xref_aliases.update(numpydoc_xref_astropy_aliases) + +numpydoc_show_class_members = False + # -- Project information ------------------------------------------------------ # This does not *have* to match the package name, but typically does -project = setup_cfg["package_name"] -author = setup_cfg["author"] -copyright = "{0}, {1}".format(datetime.datetime.now().year, setup_cfg["author"]) +project = pyproject["project"]["name"] +authors = ",".join([author["name"] for author in pyproject["project"]["authors"]]) +copyright = "{0}, {1}".format(datetime.datetime.now().year, authors) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. -__import__(setup_cfg["package_name"]) -package = sys.modules[setup_cfg["package_name"]] - -# The short X.Y version. -version = package.__version__.split("-", 1)[0] # The full version, including alpha/beta/rc tags. -release = package.__version__ +release = metadata.version(project) +# The short X.Y version. +version = ".".join(release.split(".")[:2]) + +# -- Options for the module index --------------------------------------------- +modindex_common_prefix = ["sbpy."] # -- Options for HTML output -------------------------------------------------- @@ -115,91 +244,82 @@ # variables set in the global configuration. The variables set in the # global configuration are listed below, commented out. - # Add any paths that contain custom themes here, relative to this directory. # To use a different custom theme, add the directory containing the theme. # html_theme_path = [] +# html_theme_path = [] # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. To override the custom theme, set this to the # name of a builtin theme or the name of a custom theme in html_theme_path. -# html_theme = 'sphinx_rtd_theme' +html_theme = "bootstrap-astropy" # Please update these texts to match the name of your package. html_theme_options = { "logotext1": "sb", # white, semi-bold "logotext2": "py", # orange, light "logotext3": ":docs", # white, light + "logotext1": "sb", # white, semi-bold + "logotext2": "py", # orange, light + "logotext3": ":docs", # white, light } - # Custom sidebar templates, maps document names to template names. # html_sidebars = {} +# html_sidebars = {} # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = '' +# html_logo = '' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -# html_favicon = '' +html_favicon = "_static/sbpy_logo.ico" # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '' +# html_last_updated_fmt = '' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = "{0} v{1}".format(project, release) +html_title = "{0} v{1}".format(project, release) # Output file base name for HTML help builder. htmlhelp_basename = project + "doc" +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +html_extra_path = ["robots.txt"] + # -- Options for LaTeX output ------------------------------------------------- # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ("index", project + ".tex", project + " Documentation", author, "manual") + ("index", project + ".tex", project + " Documentation", authors, "manual") ] +latex_logo = "_static/sbpy_logo.png" + # -- Options for manual page output ------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [("index", project.lower(), project + " Documentation", [author], 1)] +man_pages = [("index", project.lower(), project + " Documentation", [authors], 1)] # -- Options for the edit_on_github extension --------------------------------- -if eval(setup_cfg.get("edit_on_github")): - extensions += ["sphinx_astropy.ext.edit_on_github"] - - versionmod = __import__(setup_cfg["package_name"] + ".version") - edit_on_github_project = setup_cfg["github_project"] - if versionmod.version.release: - edit_on_github_branch = "v" + versionmod.version.version - else: - edit_on_github_branch = "main" - - edit_on_github_source_root = "" - edit_on_github_doc_root = "docs" - -# -- Resolving issue number to links in changelog ----------------------------- -github_issues_url = "https://github.com/{0}/issues/".format(setup_cfg["github_project"]) - -# -- compile list of field names -# import compile_fieldnames - -# --- intersphinx setup -intersphinx_mapping["astroquery"] = ( - "https://astroquery.readthedocs.io/en/stable/", - None, -) - -intersphinx_mapping["synphot"] = ("https://synphot.readthedocs.io/en/stable/", None) +extensions += ["sphinx_astropy.ext.edit_on_github"] +edit_on_github_project = "NASA-Planetary-Science/sbpy" +github_issues_url = "https://github.com/astropy/astropy/issues/" +edit_on_github_branch = "main" -intersphinx_mapping["astropy"] = ("https://docs.astropy.org/en/stable/", None) +# -- Other items -------------------------------------------------------------- diff --git a/docs/robots.txt b/docs/robots.txt new file mode 100644 index 000000000..18d83dc23 --- /dev/null +++ b/docs/robots.txt @@ -0,0 +1,6 @@ +User-agent: * +Allow: /*/latest/ +Allow: /en/latest/ # Fallback for bots that don't understand wildcards +Allow: /*/stable/ +Allow: /en/stable/ # Fallback for bots that don't understand wildcards +Disallow: / \ No newline at end of file diff --git a/docs/sbpy/data/fieldnames.rst b/docs/sbpy/data/fieldnames.rst index e2e944ab0..e1a48e803 100644 --- a/docs/sbpy/data/fieldnames.rst +++ b/docs/sbpy/data/fieldnames.rst @@ -1,9 +1,8 @@ .. _field name list: -=================================== -Data Container Field Name Reference -=================================== +sbpy Field Names +================ The following table lists field names that are recognized by `sbpy` when accessing `~sbpy.data.DataClass` objects, i.e., @@ -60,152 +59,153 @@ time be provided as `~astropy.time.Time` objects. Field Name List --------------- -======================================================= =================================================================================================================== =========================================================================== ==================== - Description Field Names Provenance Dimension -======================================================= =================================================================================================================== =========================================================================== ==================== - **Target Identifier** ``targetname``, ``id``, ``Object`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs`, `~sbpy.data.Phys` None - **Target Designation** ``desig``, ``designation`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs`, `~sbpy.data.Phys` None - **Target Number** ``number`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs`, `~sbpy.data.Phys` None - **Target Name** ``name`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs`, `~sbpy.data.Phys` None - **Epoch** ``epoch``, ``datetime``, ``Date``, ``date``, ``Time``, ``time`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` `~astropy.time.Time` - **Semi-Major Axis** ``a``, ``sma`` `~sbpy.data.Orbit` length - **Eccentricity** ``e``, ``ecc`` `~sbpy.data.Orbit` None - **Inclination** ``i``, ``inc``, ``incl`` `~sbpy.data.Orbit` angle - **Perihelion Distance** ``q``, ``periheldist`` `~sbpy.data.Orbit` length - **Aphelion Distance** ``Q``, ``apheldist`` `~sbpy.data.Orbit` length - **Longitude of the Ascending Node** ``Omega``, ``longnode``, ``node`` `~sbpy.data.Orbit` angle - **Argument of the Periapsis** ``w``, ``argper`` `~sbpy.data.Orbit` angle - **Mean Anomaly** ``M``, ``mean_anom`` `~sbpy.data.Orbit` angle - **True Anomaly** ``v``, ``true_anom``, ``true_anomaly`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Arc Length** ``arc``, ``arc_length`` `~sbpy.data.Orbit` angle - **Delta-v** ``delta_v``, ``delta-v`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` velocity - **Minimum Orbit Intersection Distance wrt Mercury** ``moid_mercury`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Minimum Orbit Intersection Distance wrt Earth** ``moid_earth`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Minimum Orbit Intersection Distance wrt Venus** ``moid_venus`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Minimum Orbit Intersection Distance wrt Mars** ``moid_mars`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Minimum Orbit Intersection Distance wrt Jupiter** ``moid_jupiter`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Minimum Orbit Intersection Distance wrt Saturn** ``moid_saturn`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Minimum Orbit Intersection Distance wrt Uranus** ``moid_uranus`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Minimum Orbit Intersection Distance wrt Neptune** ``moid_neptune`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length - **Tisserand Parameter wrt Jupiter** ``Tj``, ``tj`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` None - **MPC Orbit Type** ``mpc_orb_type`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` None - **Epoch of Perihelion Passage** ``Tp`` `~sbpy.data.Orbit` `~astropy.time.Time` - **Orbital Period** ``P``, ``period`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` time - **Heliocentric Distance** ``r``, ``rh``, ``r_hel``, ``heldist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **Heliocentric Radial Velocity** ``r_rate``, ``rh_rate``, ``rdot``, ``r-dot``, ``rhdot``, ``rh-dot`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **Distance to the Observer** ``delta``, ``Delta``, ``obsdist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **Observer-Target Radial Velocity** ``delta_rate``, ``deltadot``, ``delta-dot``, ``deldot``, ``del-dot`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **Right Ascension** ``ra``, ``RA`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Declination** ``dec``, ``DEC``, ``Dec`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Right Ascension Rate** ``ra_rate``, ``RA_rate``, ``ra_rates``, ``RA_rates``, ``dRA``, ``dra`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angular velocity - **RA*cos(Dec) Rate** ``RA*cos(Dec)_rate``, ``dra cos(dec)``, ``dRA cos(Dec)``, ``dra*cos(dec)``, ``dRA*cos(Dec)`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angular velocity - **Declination Rate** ``dec_rate``, ``DEC_rate``, ``Dec_rate``, ``dec_rates``, ``DEC_rates``, ``Dec_rates``, ``dDec``, ``dDEC``, ``ddec`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angular velocity - **Proper Motion** ``mu``, ``Proper motion`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angular velocity - **Proper Motion Direction** ``Direction``, ``direction`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Solar Phase Angle** ``alpha``, ``phaseangle``, ``Phase``, ``phase`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Solar Elongation Angle** ``elong``, ``solarelong``, ``solarelongation``, ``elongation``, ``Elongation`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **V-band Magnitude** ``V``, ``Vmag`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude - **Heliocentric Ecliptic Longitude** ``hlon``, ``EclLon``, ``ecllon``, ``HelEclLon``, ``helecllon`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Heliocentric Ecliptic Latitude** ``hlat``, ``EclLat``, ``ecllat``, ``HelEclLat``, ``helecllat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Horizontal Elevation** ``el``, ``EL``, ``elevation``, ``alt``, ``altitude``, ``Altitude`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Horizontal Azimuth** ``az``, ``AZ``, ``azimuth`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Lunar Elongation** ``lunar_elong``, ``elong_moon``, ``elongation_moon``, ``lunar_elongation``, ``lunarelong`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **X State Vector Component** ``x``, ``X``, ``x_vec`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **Y State Vector Component** ``y``, ``Y``, ``y_vec`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **Z State Vector Component** ``z``, ``Z``, ``z_vec`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **X Velocity Vector Component** ``vx``, ``dx``, ``dx/dt`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **Y Velocity Vector Component** ``vy``, ``dy``, ``dy/dt`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **Z Velocity Vector Component** ``vz``, ``dz``, ``dz/dt`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **X heliocentric position vector** ``x_h``, ``X_h`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **Y heliocentric position vector** ``y_h``, ``Y_h`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **Z heliocentric position vector** ``z_h``, ``Z_h`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **Comet Total Absolute Magnitude** ``m1``, ``M1`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude - **Comet Nuclear Absolute Magnitude** ``m2``, ``M2`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude - **Total Magnitude Scaling Factor** ``k1``, ``K1`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Nuclear Magnitude Scaling Factor** ``k2``, ``K2`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Phase Coefficient** ``phase_coeff``, ``Phase_coeff`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Information on Solar Presence** ``solar_presence``, ``Solar_presence`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Information on Moon and target status** ``status_flag``, ``Status_flag`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Apparent Right Ascension** ``RA_app``, ``ra_app`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Apparent Declination** ``DEC_app``, ``dec_app`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Azimuth Rate (dAZ*cosE)** ``az_rate``, ``AZ_rate`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angular velocity - **Elevation Rate (d(ELV)/dt)** ``el_rate``, ``EL_rate`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angular velocity - **Satellite Position Angle** ``sat_pang``, ``Sat_pang`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Local Sidereal Time** ``siderealtime``, ``Siderealtime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time - **Target Optical Airmass** ``airmass``, ``Airmass`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **V Magnitude Extinction** ``vmagex``, ``Vmagex`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude - **Surface Brightness** ``Surfbright``, ``surfbright`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude/angle^2 - **Fraction of Illumination** ``frac_illum``, ``Frac_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` percent - **Illumination Defect** ``defect_illum``, ``Defect_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Target-primary angular separation** ``targ_sep``, ``Targ_sep`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Target-primary visibility** ``targ_vis``, ``Targ_vis`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Angular width of target** ``targ_width``, ``Targ_width`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Apparent planetodetic longitude** ``pldetic_long``, ``Pldetic_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Apparent planetodetic latitude** ``pldetic_lat``, ``Pldetic_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Apparent planetodetic Solar longitude** ``pltdeticSol_long``, ``PltdeticSol_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Apparent planetodetic Solar latitude** ``pltdeticSol_lat``, ``PltdeticSol_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Target sub-solar point position angle** ``subsol_ang``, ``Subsol_ang`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Target sub-solar point angle distance** ``subsol_dist``, ``Subsol_dist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Target North pole position angle** ``npole_angle``, ``Npole_angle`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Target North pole position distance** ``npole_dist``, ``Npole_dist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Observation centric ecliptic longitude** ``obs_ecl_long``, ``Obs_ecl_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Observation centric ecliptic latitude** ``obs_ecl_lat``, ``Obs_ecl_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **One-way light time** ``lighttime``, ``Lighttime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time - **Target center velocity wrt Sun** ``vel_sun``, ``Vel_sun`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **Target center velocity wrt Observer** ``vel_obs``, ``Vel_obs`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **Lunar illumination** ``lun_illum``, ``Lun_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` percent - **Apparent interfering body elongation wrt observer** ``ib_elong``, ``IB_elong`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Interfering body illumination** ``ib_illum``, ``IB_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` percent - **Observer primary target angle** ``targ_angle_obs``, ``Targ_angle_obs`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Orbital plane angle** ``orbangle_plane``, ``Orbangle_plane`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` deg - **Constellation ID containing target** ``constellation``, ``Constellation`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Target North Pole RA** ``targ_npole_ra``, ``targ_npole_RA`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Target North Pole DEC** ``targ_npole_dec``, ``targ_npole_DEC`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Galactic Longitude** ``glx_long``, ``Glx_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Galactic Latitude** ``glx_lat``, ``Glx_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Local apparent solar time** ``solartime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Observer light time from Earth** ``earthlighttime``, ``Earthlighttime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time - **3 sigma positional uncertainty RA** ``RA_3sigma``, ``ra_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **3 sigma positional uncertainty DEC** ``DEC_3sigma``, ``dec_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **3 sigma positional uncertainty semi-major axis** ``sma_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **3 sigma positional uncertainty semi-minor axis** ``smi_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **3 sigma positional uncertainty position angle** ``posangle_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **3 sigma positional uncertainty ellipse area** ``area_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angular area - **3 sigma positional uncertainty root sum square** ``rss_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **3 sigma range uncertainty** ``r_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length - **3 sigma range rate uncertainty** ``r_rate_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` velocity - **3 sigma doppler radar uncertainty at S-band** ``sband_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` frequency - **3 sigma doppler radar uncertainty at X-band** ``xband_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` frequency - **3 sigma doppler round-trip delay uncertainty** ``dopdelay_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time - **Local apparent hour angle** ``locapp_hourangle`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time - **True phase angle** ``true_phaseangle`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Phase angle bisector longitude** ``pab_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Phase angle bisector latitude** ``pab_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Absolute V-band Magnitude** ``abs_V``, ``abs_Vmag`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude - **Satellite X-position** ``sat_X``, ``sat_x`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Satellite Y-position** ``sat_y``, ``sat_Y`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Atmospheric Refraction** ``atm_refraction``, ``refraction`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle - **Infrared Beaming Parameter** ``eta``, ``Eta`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None - **Temperature** ``temp``, ``Temp``, ``temperature``, ``Temperature`` `~sbpy.data.Phys`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` temperature - **Effective Diameter** ``d``, ``D``, ``diam``, ``diameter``, ``Diameter`` `~sbpy.data.Phys` length - **Effective Radius** ``R``, ``radius`` `~sbpy.data.Phys` length - **Geometric Albedo** ``pv``, ``pV``, ``p_v``, ``p_V``, ``geomalb`` `~sbpy.data.Phys` None - **Bond Albedo** ``A``, ``bondalbedo`` `~sbpy.data.Phys` None - **Emissivity** ``emissivity``, ``Emissivity`` `~sbpy.data.Phys` None - **Absolute Magnitude** ``absmag``, ``H`` `~sbpy.data.Phys`, `~sbpy.data.Ephem`, `~sbpy.data.Orbit` magnitude - **Photometric Phase Slope Parameter** ``G``, ``slope`` `~sbpy.data.Phys`, `~sbpy.data.Ephem`, `~sbpy.data.Orbit` None - **Molecule Identifier** ``mol_tag``, ``mol_name`` `~sbpy.data.Phys` None - **Transition frequency** ``t_freq`` `~sbpy.data.Phys` frequency - **Integrated line intensity at 300 K** ``lgint300`` `~sbpy.data.Phys` intensity -**Integrated line intensity at designated Temperature** ``intl``, ``lgint`` `~sbpy.data.Phys` intensity - **Partition function at 300 K** ``partfn300`` `~sbpy.data.Phys` None - **Partition function at designated temperature** ``partfn`` `~sbpy.data.Phys` None - **Upper state degeneracy** ``dgup`` `~sbpy.data.Phys` None - **Upper level energy in Joules** ``eup_j``, ``eup_J`` `~sbpy.data.Phys` energy - **Lower level energy in Joules** ``elo_j``, ``elo_J`` `~sbpy.data.Phys` energy - **Degrees of freedom** ``degfr``, ``ndf``, ``degfreedom`` `~sbpy.data.Phys` None - **Einstein Coefficient** ``au``, ``eincoeff`` `~sbpy.data.Phys` 1/time - **Timescale * r^2** ``beta``, ``beta_factor`` `~sbpy.data.Phys` time * length^2 - **Total Number** ``totnum``, ``total_number_nocd`` `~sbpy.data.Phys` None - **Column Density from Bockelee Morvan et al. 2004** ``cdensity``, ``col_density`` `~sbpy.data.Phys` 1/length^2 -======================================================= =================================================================================================================== =========================================================================== ==================== +=============================================================== =================================================================================================================== =========================================================================== ========================= + Description Field Names Provenance Dimension +=============================================================== =================================================================================================================== =========================================================================== ========================= + **Target Name** ``targetname``, ``Targetname``, ``target``, ``Target``, ``name``, ``Name``, ``id``, ``ID``, ``Object``, ``object`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs`, `~sbpy.data.Phys` None + **Target Designation** ``desig``, ``designation`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs`, `~sbpy.data.Phys` None + **Target Number** ``number``, ``target number`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs`, `~sbpy.data.Phys` None + **Epoch** ``epoch``, ``datetime``, ``Date``, ``date``, ``Time``, ``time`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` `~astropy.time.Time` + **relative time** ``t_relative``, ``t_rel``, ``dt`` `~sbpy.data.Ephem` time + **Semi-Major Axis** ``a``, ``sma`` `~sbpy.data.Orbit` length + **Eccentricity** ``e``, ``ecc`` `~sbpy.data.Orbit` + **Inclination** ``i``, ``inc``, ``incl`` `~sbpy.data.Orbit` angle + **Perihelion Distance** ``q``, ``periheldist`` `~sbpy.data.Orbit` length + **Aphelion Distance** ``Q``, ``apheldist`` `~sbpy.data.Orbit` length + **Longitude of the Ascending Node** ``Omega``, ``longnode``, ``node`` `~sbpy.data.Orbit` angle + **Argument of the Periapsis** ``w``, ``argper`` `~sbpy.data.Orbit` angle + **Mean Anomaly** ``M``, ``mean_anom`` `~sbpy.data.Orbit` angle + **True Anomaly** ``v``, ``true_anom``, ``true_anomaly`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Arc Length** ``arc``, ``arc_length`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem` time + **Delta-v** ``delta_v``, ``delta-v`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length per time + **Minimum Orbit Intersection Distance wrt Mercury** ``moid_mercury`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Minimum Orbit Intersection Distance wrt Earth** ``moid_earth`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Minimum Orbit Intersection Distance wrt Venus** ``moid_venus`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Minimum Orbit Intersection Distance wrt Mars** ``moid_mars`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Minimum Orbit Intersection Distance wrt Jupiter** ``moid_jupiter`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Minimum Orbit Intersection Distance wrt Saturn** ``moid_saturn`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Minimum Orbit Intersection Distance wrt Uranus** ``moid_uranus`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Minimum Orbit Intersection Distance wrt Neptune** ``moid_neptune`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` length + **Tisserand Parameter wrt Jupiter** ``Tj``, ``tj`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` None + **MPC Orbit Type** ``mpc_orb_type`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` None + **Epoch of Perihelion Passage** ``Tp`` `~sbpy.data.Orbit` `~astropy.time.Time` + **Orbital Period** ``P``, ``period`` `~sbpy.data.Orbit`, `~sbpy.data.Phys` time + **Heliocentric Distance** ``r``, ``rh``, ``r_hel``, ``heldist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **Heliocentric Radial Velocity** ``r_rate``, ``rh_rate``, ``rdot``, ``r-dot``, ``rhdot``, ``rh-dot`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **Distance to the Observer** ``delta``, ``Delta``, ``obsdist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **Observer-Target Radial Velocity** ``delta_rate``, ``deltadot``, ``delta-dot``, ``deldot``, ``del-dot`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **Right Ascension** ``ra``, ``RA`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Declination** ``dec``, ``DEC``, ``Dec`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Right Ascension Rate** ``ra_rate``, ``RA_rate``, ``ra_rates``, ``RA_rates``, ``dRA``, ``dra`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle per time + **RA*cos(Dec) Rate** ``RA*cos(Dec)_rate``, ``dra cos(dec)``, ``dRA cos(Dec)``, ``dra*cos(dec)``, ``dRA*cos(Dec)`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle per time + **Declination Rate** ``dec_rate``, ``DEC_rate``, ``Dec_rate``, ``dec_rates``, ``DEC_rates``, ``Dec_rates``, ``dDec``, ``dDEC``, ``ddec`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle per time + **Proper Motion** ``mu``, ``Proper motion`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle per time + **Proper Motion Direction** ``Direction``, ``direction`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Solar Phase Angle** ``alpha``, ``phaseangle``, ``Phase``, ``phase`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Solar Elongation Angle** ``elong``, ``solarelong``, ``solarelongation``, ``elongation``, ``Elongation`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **V-band Magnitude** ``V``, ``Vmag`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude + **Heliocentric Ecliptic Longitude** ``hlon``, ``EclLon``, ``ecllon``, ``HelEclLon``, ``helecllon`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Heliocentric Ecliptic Latitude** ``hlat``, ``EclLat``, ``ecllat``, ``HelEclLat``, ``helecllat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Horizontal Elevation** ``el``, ``EL``, ``elevation``, ``alt``, ``altitude``, ``Altitude`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Horizontal Azimuth** ``az``, ``AZ``, ``azimuth`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Lunar Elongation** ``lunar_elong``, ``elong_moon``, ``elongation_moon``, ``lunar_elongation``, ``lunarelong`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **X State Vector Component** ``x``, ``X``, ``x_vec`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **Y State Vector Component** ``y``, ``Y``, ``y_vec`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **Z State Vector Component** ``z``, ``Z``, ``z_vec`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **X Velocity Vector Component** ``vx``, ``dx``, ``dx/dt`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **Y Velocity Vector Component** ``vy``, ``dy``, ``dy/dt`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **Z Velocity Vector Component** ``vz``, ``dz``, ``dz/dt`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **X heliocentric position vector** ``x_h``, ``X_h`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **Y heliocentric position vector** ``y_h``, ``Y_h`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **Z heliocentric position vector** ``z_h``, ``Z_h`` `~sbpy.data.Orbit`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **Comet Total Absolute Magnitude** ``m1``, ``M1`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude + **Comet Nuclear Absolute Magnitude** ``m2``, ``M2`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude + **Total Magnitude Scaling Factor** ``k1``, ``K1`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` + **Nuclear Magnitude Scaling Factor** ``k2``, ``K2`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` + **Phase Coefficient** ``phase_coeff``, ``Phase_coeff`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` + **Information on Solar Presence** ``solar_presence``, ``Solar_presence`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None + **Information on Moon and target status** ``status_flag``, ``Status_flag`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None + **Apparent Right Ascension** ``RA_app``, ``ra_app`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Apparent Declination** ``DEC_app``, ``dec_app`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Azimuth Rate (dAZ*cosE)** ``az_rate``, ``AZ_rate`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle per time + **Elevation Rate (d(ELV)/dt)** ``el_rate``, ``EL_rate`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle per time + **Satellite Position Angle** ``sat_pang``, ``Sat_pang`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Local Sidereal Time** ``siderealtime``, ``Siderealtime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time + **Target Optical Airmass** ``airmass``, ``Airmass`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` + **V Magnitude Extinction** ``vmagex``, ``Vmagex`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude + **Surface Brightness** ``Surfbright``, ``surfbright`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude per solid angle + **Fraction of Illumination** ``frac_illum``, ``Frac_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` percent + **Illumination Defect** ``defect_illum``, ``Defect_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Target-primary angular separation** ``targ_sep``, ``Targ_sep`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Target-primary visibility** ``targ_vis``, ``Targ_vis`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None + **Angular width of target** ``targ_width``, ``Targ_width`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Apparent planetodetic longitude** ``pldetic_long``, ``Pldetic_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Apparent planetodetic latitude** ``pldetic_lat``, ``Pldetic_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Apparent planetodetic Solar longitude** ``pltdeticSol_long``, ``PltdeticSol_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Apparent planetodetic Solar latitude** ``pltdeticSol_lat``, ``PltdeticSol_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Target sub-solar point position angle** ``subsol_ang``, ``Subsol_ang`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Target sub-solar point angle distance** ``subsol_dist``, ``Subsol_dist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Target North pole position angle** ``npole_angle``, ``Npole_angle`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Target North pole position distance** ``npole_dist``, ``Npole_dist`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Observation centric ecliptic longitude** ``obs_ecl_long``, ``Obs_ecl_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Observation centric ecliptic latitude** ``obs_ecl_lat``, ``Obs_ecl_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **One-way light time** ``lighttime``, ``Lighttime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time + **Target center velocity wrt Sun** ``vel_sun``, ``Vel_sun`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **Target center velocity wrt Observer** ``vel_obs``, ``Vel_obs`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **Lunar illumination** ``lun_illum``, ``Lun_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` percent + **Apparent interfering body elongation wrt observer** ``ib_elong``, ``IB_elong`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Interfering body illumination** ``ib_illum``, ``IB_illum`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` percent + **Observer primary target angle** ``targ_angle_obs``, ``Targ_angle_obs`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Orbital plane angle** ``orbangle_plane``, ``Orbangle_plane`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Constellation ID containing target** ``constellation``, ``Constellation`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None + **Target North Pole RA** ``targ_npole_ra``, ``targ_npole_RA`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Target North Pole DEC** ``targ_npole_dec``, ``targ_npole_DEC`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Galactic Longitude** ``glx_long``, ``Glx_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Galactic Latitude** ``glx_lat``, ``Glx_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Local apparent solar time** ``solartime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time + **Observer light time from Earth** ``earthlighttime``, ``Earthlighttime`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time + **3 sigma positional uncertainty RA** ``RA_3sigma``, ``ra_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **3 sigma positional uncertainty DEC** ``DEC_3sigma``, ``dec_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **3 sigma positional uncertainty semi-major axis** ``sma_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **3 sigma positional uncertainty semi-minor axis** ``smi_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **3 sigma positional uncertainty position angle** ``posangle_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **3 sigma positional uncertainty ellipse area** ``area_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` solid angle + **3 sigma positional uncertainty root sum square** ``rss_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **3 sigma range uncertainty** ``r_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length + **3 sigma range rate uncertainty** ``r_rate_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` length per time + **3 sigma doppler radar uncertainty at S-band** ``sband_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` frequency + **3 sigma doppler radar uncertainty at X-band** ``xband_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` frequency + **3 sigma doppler round-trip delay uncertainty** ``dopdelay_3sigma`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time + **Local apparent hour angle** ``locapp_hourangle`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` time + **True phase angle** ``true_phaseangle`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Phase angle bisector longitude** ``pab_long`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Phase angle bisector latitude** ``pab_lat`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Absolute V-band Magnitude** ``abs_V``, ``abs_Vmag`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` magnitude + **Satellite X-position** ``sat_X``, ``sat_x`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Satellite Y-position** ``sat_y``, ``sat_Y`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Atmospheric Refraction** ``atm_refraction``, ``refraction`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` angle + **Infrared Beaming Parameter** ``eta``, ``Eta`` `~sbpy.data.Ephem`, `~sbpy.data.Obs` None + **Temperature** ``temp``, ``Temp``, ``temperature``, ``Temperature`` `~sbpy.data.Phys`, `~sbpy.data.Ephem`, `~sbpy.data.Obs` temperature + **Effective Diameter** ``d``, ``D``, ``diam``, ``diameter``, ``Diameter`` `~sbpy.data.Phys` length + **Effective Radius** ``R``, ``radius`` `~sbpy.data.Phys` length + **Geometric Albedo** ``pv``, ``pV``, ``p_v``, ``p_V``, ``geomalb`` `~sbpy.data.Phys` + **Bond Albedo** ``A``, ``bondalbedo`` `~sbpy.data.Phys` + **Emissivity** ``emissivity``, ``Emissivity`` `~sbpy.data.Phys` + **Absolute Magnitude** ``absmag``, ``H`` `~sbpy.data.Phys`, `~sbpy.data.Ephem`, `~sbpy.data.Orbit` magnitude + **Photometric Phase Slope Parameter** ``G``, ``slope`` `~sbpy.data.Phys`, `~sbpy.data.Ephem`, `~sbpy.data.Orbit` + **Molecule Identifier** ``mol_tag``, ``mol_name`` `~sbpy.data.Phys` None + **Transition frequency** ``t_freq`` `~sbpy.data.Phys` frequency + **Integrated line intensity at 300 K** ``lgint300`` `~sbpy.data.Phys` None + **Integrated line intensity at designated Temperature** ``intl``, ``lgint`` `~sbpy.data.Phys` None + **Partition function at 300 K** ``partfn300`` `~sbpy.data.Phys` + **Partition function at designated temperature** ``partfn`` `~sbpy.data.Phys` + **Upper state degeneracy** ``dgup`` `~sbpy.data.Phys` + **Upper level energy in Joules** ``eup_j``, ``eup_J`` `~sbpy.data.Phys` energy + **Lower level energy in Joules** ``elo_j``, ``elo_J`` `~sbpy.data.Phys` energy + **Degrees of freedom** ``degfr``, ``ndf``, ``degfreedom`` `~sbpy.data.Phys` + **Einstein Coefficient** ``au``, ``eincoeff`` `~sbpy.data.Phys` inverse time + **Timescale * r^2** ``beta``, ``beta_factor`` `~sbpy.data.Phys` time-area + **Total Number** ``totnum``, ``total_number_nocdtotal_number`` `~sbpy.data.Phys` + **Column Density from Bockelee Morvan et al. 2004** ``cdensity``, ``col_density`` `~sbpy.data.Phys` inverse area +**Ratio of the force from radiation to the force from gravity** ``beta_rad`` `~sbpy.data.Phys` +=============================================================== =================================================================================================================== =========================================================================== ========================= diff --git a/docs/sbpy/dynamics.rst b/docs/sbpy/dynamics.rst index 1b3c1d7c6..60549fc2b 100644 --- a/docs/sbpy/dynamics.rst +++ b/docs/sbpy/dynamics.rst @@ -475,7 +475,7 @@ Generally, we are interested in plotting syndynes and synchrones on an image of ax, synchrone.coords, ls="--", - label=f"$\Delta t={synchrone.age.to(u.d):.2g}$", + label=f"$\\Delta t={synchrone.age.to(u.d):.2g}$", ) # and plot the orbit @@ -487,8 +487,8 @@ Generally, we are interested in plotting syndynes and synchrones on an image of plt.setp(ax, xlim=[100, -10], ylim=[-10, 100], - xlabel="$\Delta$RA (arcsec)", - ylabel="$\Delta$Dec (arcsec)", + xlabel="$\\Delta$RA (arcsec)", + ylabel="$\\Delta$Dec (arcsec)", ) plt.legend() plt.tight_layout() diff --git a/docs/sbpy/units.rst b/docs/sbpy/units.rst index 5a676d9b7..69b00aef9 100644 --- a/docs/sbpy/units.rst +++ b/docs/sbpy/units.rst @@ -50,11 +50,11 @@ Unit conversions between flux density and Vega-based magnitudes use the `astropy >>> wave = 5500 * u.AA >>> m = 0 * VEGAmag >>> fluxd = m.to('erg/(cm2 s AA)', spectral_density_vega(wave)) - >>> fluxd.value # doctest: +FLOAT_CMP - 3.5469235179497687e-09 + >>> print(fluxd) # doctest: +FLOAT_CMP + 3.5469235114856157e-09 erg / (Angstrom s cm2) >>> m = fluxd.to(VEGAmag, spectral_density_vega(wave)) - >>> m.value # doctest: +FLOAT_CMP - 0.0 + >>> print(m) # doctest: +FLOAT_CMP + -0.0 mag(VEGA) To use a bandpass, define and pass a `synphot.spectrum.SpectralElement`. A limited set of bandpasses are distributed with sbpy (see :ref:`filter-bandpasses`): @@ -65,8 +65,8 @@ To use a bandpass, define and pass a `synphot.spectrum.SpectralElement`. A limi >>> V = bandpass('Johnson V') >>> m = 0.0 * VEGAmag >>> fluxd = m.to('erg/(cm2 s AA)', spectral_density_vega(V)) - >>> fluxd.value # doctest: +FLOAT_CMP - 3.5469235114856157e-09 + >>> print(fluxd) # doctest: +FLOAT_CMP + 3.5469235114856157e-09 erg / (Angstrom s cm2) .. _reflectance-equivalencies: diff --git a/docs/status.rst b/docs/status.rst index c682eee36..fb66d92b8 100644 --- a/docs/status.rst +++ b/docs/status.rst @@ -4,9 +4,9 @@ Status Page =========== This page indicates the development status of `sbpy`. The initial development is -expected to conclude in 2025. +expected to conclude in 2026. -The current development version is **v0.6.dev**; its status is as follows: +The current development version is **v0.7.dev**; its status is as follows: .. image:: https://github.com/NASA-Planetary-Science/sbpy/actions/workflows/ci_cron_weekly.yml/badge.svg :target: https://github.com/NASA-Planetary-Science/sbpy/actions diff --git a/licenses/LICENSE.rst b/licenses/ASTROPY_LICENSE.rst similarity index 96% rename from licenses/LICENSE.rst rename to licenses/ASTROPY_LICENSE.rst index d31d3ae3e..f339ff01d 100644 --- a/licenses/LICENSE.rst +++ b/licenses/ASTROPY_LICENSE.rst @@ -1,4 +1,5 @@ -Copyright (c) 2017-2019, sbpy team +Copyright (c) 2011-2025, Astropy Developers + All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/logo/LICENSE b/logo/LICENSE index 75a9fdf2a..6acffa33d 100644 --- a/logo/LICENSE +++ b/logo/LICENSE @@ -1,354 +1,427 @@ -Copyright (c) 2018, Michael Mommert - -The sbpy logo is a modified version of the astropy logo available -under https://github.com/astropy/astropy-logo (copyright Kyle Barbary, -2013). Both logos are released under the Creative Commons -Attribution-ShareAlike license which is given in full below and at -http://creativecommons.org/licenses/by-sa/3.0/ - -THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE -COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY -COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS -AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. - -BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE -TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY -BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS -CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND -CONDITIONS. - -1. Definitions - - a. "Adaptation" means a work based upon the Work, or upon the Work and - other pre-existing works, such as a translation, adaptation, - derivative work, arrangement of music or other alterations of a - literary or artistic work, or phonogram or performance and includes - cinematographic adaptations or any other form in which the Work may be - recast, transformed, or adapted including in any form recognizably - derived from the original, except that a work that constitutes a - Collection will not be considered an Adaptation for the purpose of - this License. For the avoidance of doubt, where the Work is a musical - work, performance or phonogram, the synchronization of the Work in - timed-relation with a moving image ("synching") will be considered an - Adaptation for the purpose of this License. - b. "Collection" means a collection of literary or artistic works, such as - encyclopedias and anthologies, or performances, phonograms or - broadcasts, or other works or subject matter other than works listed - in Section 1(f) below, which, by reason of the selection and - arrangement of their contents, constitute intellectual creations, in - which the Work is included in its entirety in unmodified form along - with one or more other contributions, each constituting separate and - independent works in themselves, which together are assembled into a - collective whole. A work that constitutes a Collection will not be - considered an Adaptation (as defined below) for the purposes of this - License. - c. "Creative Commons Compatible License" means a license that is listed - at http://creativecommons.org/compatiblelicenses that has been - approved by Creative Commons as being essentially equivalent to this - License, including, at a minimum, because that license: (i) contains - terms that have the same purpose, meaning and effect as the License - Elements of this License; and, (ii) explicitly permits the relicensing - of adaptations of works made available under that license under this - License or a Creative Commons jurisdiction license with the same - License Elements as this License. - d. "Distribute" means to make available to the public the original and - copies of the Work or Adaptation, as appropriate, through sale or - other transfer of ownership. - e. "License Elements" means the following high-level license attributes - as selected by Licensor and indicated in the title of this License: - Attribution, ShareAlike. - f. "Licensor" means the individual, individuals, entity or entities that - offer(s) the Work under the terms of this License. - g. "Original Author" means, in the case of a literary or artistic work, - the individual, individuals, entity or entities who created the Work - or if no individual or entity can be identified, the publisher; and in - addition (i) in the case of a performance the actors, singers, - musicians, dancers, and other persons who act, sing, deliver, declaim, - play in, interpret or otherwise perform literary or artistic works or - expressions of folklore; (ii) in the case of a phonogram the producer - being the person or legal entity who first fixes the sounds of a - performance or other sounds; and, (iii) in the case of broadcasts, the - organization that transmits the broadcast. - h. "Work" means the literary and/or artistic work offered under the terms - of this License including without limitation any production in the - literary, scientific and artistic domain, whatever may be the mode or - form of its expression including digital form, such as a book, - pamphlet and other writing; a lecture, address, sermon or other work - of the same nature; a dramatic or dramatico-musical work; a - choreographic work or entertainment in dumb show; a musical - composition with or without words; a cinematographic work to which are - assimilated works expressed by a process analogous to cinematography; - a work of drawing, painting, architecture, sculpture, engraving or - lithography; a photographic work to which are assimilated works - expressed by a process analogous to photography; a work of applied - art; an illustration, map, plan, sketch or three-dimensional work - relative to geography, topography, architecture or science; a - performance; a broadcast; a phonogram; a compilation of data to the - extent it is protected as a copyrightable work; or a work performed by - a variety or circus performer to the extent it is not otherwise - considered a literary or artistic work. - i. "You" means an individual or entity exercising rights under this - License who has not previously violated the terms of this License with - respect to the Work, or who has received express permission from the - Licensor to exercise rights under this License despite a previous - violation. - j. "Publicly Perform" means to perform public recitations of the Work and - to communicate to the public those public recitations, by any means or - process, including by wire or wireless means or public digital - performances; to make available to the public Works in such a way that - members of the public may access these Works from a place and at a - place individually chosen by them; to perform the Work to the public - by any means or process and the communication to the public of the - performances of the Work, including by public digital performance; to - broadcast and rebroadcast the Work by any means including signs, - sounds or images. - k. "Reproduce" means to make copies of the Work by any means including - without limitation by sound or visual recordings and the right of - fixation and reproducing fixations of the Work, including storage of a - protected performance or phonogram in digital form or other electronic - medium. - -2. Fair Dealing Rights. Nothing in this License is intended to reduce, -limit, or restrict any uses free from copyright or rights arising from -limitations or exceptions that are provided for in connection with the -copyright protection under copyright law or other applicable laws. - -3. License Grant. Subject to the terms and conditions of this License, -Licensor hereby grants You a worldwide, royalty-free, non-exclusive, -perpetual (for the duration of the applicable copyright) license to -exercise the rights in the Work as stated below: - - a. to Reproduce the Work, to incorporate the Work into one or more - Collections, and to Reproduce the Work as incorporated in the - Collections; - b. to create and Reproduce Adaptations provided that any such Adaptation, - including any translation in any medium, takes reasonable steps to - clearly label, demarcate or otherwise identify that changes were made - to the original Work. For example, a translation could be marked "The - original work was translated from English to Spanish," or a - modification could indicate "The original work has been modified."; - c. to Distribute and Publicly Perform the Work including as incorporated - in Collections; and, - d. to Distribute and Publicly Perform Adaptations. - e. For the avoidance of doubt: - - i. Non-waivable Compulsory License Schemes. In those jurisdictions in - which the right to collect royalties through any statutory or - compulsory licensing scheme cannot be waived, the Licensor - reserves the exclusive right to collect such royalties for any - exercise by You of the rights granted under this License; - ii. Waivable Compulsory License Schemes. In those jurisdictions in - which the right to collect royalties through any statutory or - compulsory licensing scheme can be waived, the Licensor waives the - exclusive right to collect such royalties for any exercise by You - of the rights granted under this License; and, - iii. Voluntary License Schemes. The Licensor waives the right to - collect royalties, whether individually or, in the event that the - Licensor is a member of a collecting society that administers - voluntary licensing schemes, via that society, from any exercise - by You of the rights granted under this License. - -The above rights may be exercised in all media and formats whether now -known or hereafter devised. The above rights include the right to make -such modifications as are technically necessary to exercise the rights in -other media and formats. Subject to Section 8(f), all rights not expressly -granted by Licensor are hereby reserved. - -4. Restrictions. The license granted in Section 3 above is expressly made -subject to and limited by the following restrictions: - - a. You may Distribute or Publicly Perform the Work only under the terms - of this License. You must include a copy of, or the Uniform Resource - Identifier (URI) for, this License with every copy of the Work You - Distribute or Publicly Perform. You may not offer or impose any terms - on the Work that restrict the terms of this License or the ability of - the recipient of the Work to exercise the rights granted to that - recipient under the terms of the License. You may not sublicense the - Work. You must keep intact all notices that refer to this License and - to the disclaimer of warranties with every copy of the Work You - Distribute or Publicly Perform. When You Distribute or Publicly - Perform the Work, You may not impose any effective technological - measures on the Work that restrict the ability of a recipient of the - Work from You to exercise the rights granted to that recipient under - the terms of the License. This Section 4(a) applies to the Work as - incorporated in a Collection, but this does not require the Collection - apart from the Work itself to be made subject to the terms of this - License. If You create a Collection, upon notice from any Licensor You - must, to the extent practicable, remove from the Collection any credit - as required by Section 4(c), as requested. If You create an - Adaptation, upon notice from any Licensor You must, to the extent - practicable, remove from the Adaptation any credit as required by - Section 4(c), as requested. - b. You may Distribute or Publicly Perform an Adaptation only under the - terms of: (i) this License; (ii) a later version of this License with - the same License Elements as this License; (iii) a Creative Commons - jurisdiction license (either this or a later license version) that - contains the same License Elements as this License (e.g., - Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible - License. If you license the Adaptation under one of the licenses - mentioned in (iv), you must comply with the terms of that license. If - you license the Adaptation under the terms of any of the licenses - mentioned in (i), (ii) or (iii) (the "Applicable License"), you must - comply with the terms of the Applicable License generally and the - following provisions: (I) You must include a copy of, or the URI for, - the Applicable License with every copy of each Adaptation You - Distribute or Publicly Perform; (II) You may not offer or impose any - terms on the Adaptation that restrict the terms of the Applicable - License or the ability of the recipient of the Adaptation to exercise - the rights granted to that recipient under the terms of the Applicable - License; (III) You must keep intact all notices that refer to the - Applicable License and to the disclaimer of warranties with every copy - of the Work as included in the Adaptation You Distribute or Publicly - Perform; (IV) when You Distribute or Publicly Perform the Adaptation, - You may not impose any effective technological measures on the - Adaptation that restrict the ability of a recipient of the Adaptation - from You to exercise the rights granted to that recipient under the - terms of the Applicable License. This Section 4(b) applies to the - Adaptation as incorporated in a Collection, but this does not require - the Collection apart from the Adaptation itself to be made subject to - the terms of the Applicable License. - c. If You Distribute, or Publicly Perform the Work or any Adaptations or - Collections, You must, unless a request has been made pursuant to - Section 4(a), keep intact all copyright notices for the Work and - provide, reasonable to the medium or means You are utilizing: (i) the - name of the Original Author (or pseudonym, if applicable) if supplied, - and/or if the Original Author and/or Licensor designate another party - or parties (e.g., a sponsor institute, publishing entity, journal) for - attribution ("Attribution Parties") in Licensor's copyright notice, - terms of service or by other reasonable means, the name of such party - or parties; (ii) the title of the Work if supplied; (iii) to the - extent reasonably practicable, the URI, if any, that Licensor - specifies to be associated with the Work, unless such URI does not - refer to the copyright notice or licensing information for the Work; - and (iv) , consistent with Ssection 3(b), in the case of an - Adaptation, a credit identifying the use of the Work in the Adaptation - (e.g., "French translation of the Work by Original Author," or - "Screenplay based on original Work by Original Author"). The credit - required by this Section 4(c) may be implemented in any reasonable - manner; provided, however, that in the case of a Adaptation or - Collection, at a minimum such credit will appear, if a credit for all - contributing authors of the Adaptation or Collection appears, then as - part of these credits and in a manner at least as prominent as the - credits for the other contributing authors. For the avoidance of - doubt, You may only use the credit required by this Section for the - purpose of attribution in the manner set out above and, by exercising - Your rights under this License, You may not implicitly or explicitly - assert or imply any connection with, sponsorship or endorsement by the - Original Author, Licensor and/or Attribution Parties, as appropriate, - of You or Your use of the Work, without the separate, express prior - written permission of the Original Author, Licensor and/or Attribution - Parties. - d. Except as otherwise agreed in writing by the Licensor or as may be - otherwise permitted by applicable law, if You Reproduce, Distribute or - Publicly Perform the Work either by itself or as part of any - Adaptations or Collections, You must not distort, mutilate, modify or - take other derogatory action in relation to the Work which would be - prejudicial to the Original Author's honor or reputation. Licensor - agrees that in those jurisdictions (e.g. Japan), in which any exercise - of the right granted in Section 3(b) of this License (the right to - make Adaptations) would be deemed to be a distortion, mutilation, - modification or other derogatory action prejudicial to the Original - Author's honor and reputation, the Licensor will waive or not assert, - as appropriate, this Section, to the fullest extent permitted by the - applicable national law, to enable You to reasonably exercise Your - right under Section 3(b) of this License (right to make Adaptations) - but not otherwise. - -5. Representations, Warranties and Disclaimer - -UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR -OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY -KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, -INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, -FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF -LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, -WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION -OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. - -6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE -LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR -ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES -ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS -BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -7. Termination - - a. This License and the rights granted hereunder will terminate - automatically upon any breach by You of the terms of this License. - Individuals or entities who have received Adaptations or Collections - from You under this License, however, will not have their licenses - terminated provided such individuals or entities remain in full - compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will - survive any termination of this License. - b. Subject to the above terms and conditions, the license granted here is - perpetual (for the duration of the applicable copyright in the Work). - Notwithstanding the above, Licensor reserves the right to release the - Work under different license terms or to stop distributing the Work at - any time; provided, however that any such election will not serve to - withdraw this License (or any other license that has been, or is - required to be, granted under the terms of this License), and this - License will continue in full force and effect unless terminated as - stated above. - -8. Miscellaneous - - a. Each time You Distribute or Publicly Perform the Work or a Collection, - the Licensor offers to the recipient a license to the Work on the same - terms and conditions as the license granted to You under this License. - b. Each time You Distribute or Publicly Perform an Adaptation, Licensor - offers to the recipient a license to the original Work on the same - terms and conditions as the license granted to You under this License. - c. If any provision of this License is invalid or unenforceable under - applicable law, it shall not affect the validity or enforceability of - the remainder of the terms of this License, and without further action - by the parties to this agreement, such provision shall be reformed to - the minimum extent necessary to make such provision valid and - enforceable. - d. No term or provision of this License shall be deemed waived and no - breach consented to unless such waiver or consent shall be in writing - and signed by the party to be charged with such waiver or consent. - e. This License constitutes the entire agreement between the parties with - respect to the Work licensed here. There are no understandings, - agreements or representations with respect to the Work not specified - here. Licensor shall not be bound by any additional provisions that - may appear in any communication from You. This License may not be - modified without the mutual written agreement of the Licensor and You. - f. The rights granted under, and the subject matter referenced, in this - License were drafted utilizing the terminology of the Berne Convention - for the Protection of Literary and Artistic Works (as amended on - September 28, 1979), the Rome Convention of 1961, the WIPO Copyright - Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 - and the Universal Copyright Convention (as revised on July 24, 1971). - These rights and subject matter take effect in the relevant - jurisdiction in which the License terms are sought to be enforced - according to the corresponding provisions of the implementation of - those treaty provisions in the applicable national law. If the - standard suite of rights granted under applicable copyright law - includes additional rights not granted under this License, such - additional rights are deemed to be included in the License; this - License is not intended to restrict the license of any rights under - applicable law. - - -Creative Commons Notice - - Creative Commons is not a party to this License, and makes no warranty - whatsoever in connection with the Work. Creative Commons will not be - liable to You or any party on any legal theory for any damages - whatsoever, including without limitation any general, special, - incidental or consequential damages arising in connection to this - license. Notwithstanding the foregoing two (2) sentences, if Creative - Commons has expressly identified itself as the Licensor hereunder, it - shall have all rights and obligations of Licensor. - - Except for the limited purpose of indicating to the public that the - Work is licensed under the CCPL, Creative Commons does not authorize - the use by either party of the trademark "Creative Commons" or any - related trademark or logo of Creative Commons without the prior - written consent of Creative Commons. Any permitted use will be in - compliance with Creative Commons' then-current trademark usage - guidelines, as may be published on its website or otherwise made - available upon request from time to time. For the avoidance of doubt, - this trademark restriction does not form part of the License. - - Creative Commons may be contacted at http://creativecommons.org/. \ No newline at end of file +The sbpy logo v2 is a modified version of the original sbpy logo (copyright +Michael Mommert 2018), based on the astropy logo (copyright Kyle Barbary, 2013). +Both logos are released under the Creative Commons Attribution-ShareAlike +license 3.0. The sbpy logo v2 is released under the compatible Creative Commons Attribution-ShareAlike license 4.0. + +(c) 2025, sbpy team + +Attribution-ShareAlike 4.0 International + +https://creativecommons.org/licenses/by-sa/4.0/ + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + +Section 1 -- Definitions. + +a. Adapted Material means material subject to Copyright and Similar +Rights that is derived from or based upon the Licensed Material +and in which the Licensed Material is translated, altered, +arranged, transformed, or otherwise modified in a manner requiring +permission under the Copyright and Similar Rights held by the +Licensor. For purposes of this Public License, where the Licensed +Material is a musical work, performance, or sound recording, +Adapted Material is always produced where the Licensed Material is +synched in timed relation with a moving image. + +b. Adapter's License means the license You apply to Your Copyright +and Similar Rights in Your contributions to Adapted Material in +accordance with the terms and conditions of this Public License. + +c. BY-SA Compatible License means a license listed at +creativecommons.org/compatiblelicenses, approved by Creative +Commons as essentially the equivalent of this Public License. + +d. Copyright and Similar Rights means copyright and/or similar rights +closely related to copyright including, without limitation, +performance, broadcast, sound recording, and Sui Generis Database +Rights, without regard to how the rights are labeled or +categorized. For purposes of this Public License, the rights +specified in Section 2(b)(1)-(2) are not Copyright and Similar +Rights. + +e. Effective Technological Measures means those measures that, in the +absence of proper authority, may not be circumvented under laws +fulfilling obligations under Article 11 of the WIPO Copyright +Treaty adopted on December 20, 1996, and/or similar international +agreements. + +f. Exceptions and Limitations means fair use, fair dealing, and/or +any other exception or limitation to Copyright and Similar Rights +that applies to Your use of the Licensed Material. + +g. License Elements means the license attributes listed in the name +of a Creative Commons Public License. The License Elements of this +Public License are Attribution and ShareAlike. + +h. Licensed Material means the artistic or literary work, database, +or other material to which the Licensor applied this Public +License. + +i. Licensed Rights means the rights granted to You subject to the +terms and conditions of this Public License, which are limited to +all Copyright and Similar Rights that apply to Your use of the +Licensed Material and that the Licensor has authority to license. + +j. Licensor means the individual(s) or entity(ies) granting rights +under this Public License. + +k. Share means to provide material to the public by any means or +process that requires permission under the Licensed Rights, such +as reproduction, public display, public performance, distribution, +dissemination, communication, or importation, and to make material +available to the public including in ways that members of the +public may access the material from a place and at a time +individually chosen by them. + +l. Sui Generis Database Rights means rights other than copyright +resulting from Directive 96/9/EC of the European Parliament and of +the Council of 11 March 1996 on the legal protection of databases, +as amended and/or succeeded, as well as other essentially +equivalent rights anywhere in the world. + +m. You means the individual or entity exercising the Licensed Rights +under this Public License. Your has a corresponding meaning. + +Section 2 -- Scope. + +a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + +b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + +a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + +b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + +a. for the avoidance of doubt, Section 2(a)(1) grants You the right +to extract, reuse, reproduce, and Share all or a substantial +portion of the contents of the database; + +b. if You include all or a substantial portion of the database +contents in a database in which You have Sui Generis Database +Rights, then the database in which You have Sui Generis Database +Rights (but not its individual contents) is Adapted Material, +including for purposes of Section 3(b); and + +c. You must comply with the conditions in Section 3(a) if You Share +all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + +a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE +EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS +AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF +ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, +IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, +WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, +ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT +KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT +ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + +b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE +TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, +NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, +INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, +COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR +USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN +ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR +DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR +IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + +c. The disclaimer of warranties and limitation of liability provided +above shall be interpreted in a manner that, to the extent +possible, most closely approximates an absolute disclaimer and +waiver of all liability. + +Section 6 -- Term and Termination. + +a. This Public License applies for the term of the Copyright and +Similar Rights licensed here. However, if You fail to comply with +this Public License, then Your rights under this Public License +terminate automatically. + +b. Where Your right to use the Licensed Material has terminated under +Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + +c. For the avoidance of doubt, the Licensor may also offer the +Licensed Material under separate terms or conditions or stop +distributing the Licensed Material at any time; however, doing so +will not terminate this Public License. + +d. Sections 1, 5, 6, 7, and 8 survive termination of this Public +License. + +Section 7 -- Other Terms and Conditions. + +a. The Licensor shall not be bound by any additional or different +terms or conditions communicated by You unless expressly agreed. + +b. Any arrangements, understandings, or agreements regarding the +Licensed Material not stated herein are separate from and +independent of the terms and conditions of this Public License. + +Section 8 -- Interpretation. + +a. For the avoidance of doubt, this Public License does not, and +shall not be interpreted to, reduce, limit, restrict, or impose +conditions on any use of the Licensed Material that could lawfully +be made without permission under this Public License. + +b. To the extent possible, if any provision of this Public License is +deemed unenforceable, it shall be automatically reformed to the +minimum extent necessary to make it enforceable. If the provision +cannot be reformed, it shall be severed from this Public License +without affecting the enforceability of the remaining terms and +conditions. + +c. No term or condition of this Public License will be waived and no +failure to comply consented to unless expressly agreed to by the +Licensor. + +d. Nothing in this Public License constitutes or may be interpreted +as a limitation upon, or waiver of, any privileges and immunities +that apply to the Licensor or You, including from the legal +processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/logo/sbpy_banner_96.png b/logo/sbpy_banner_96.png new file mode 100644 index 000000000..0f8875919 Binary files /dev/null and b/logo/sbpy_banner_96.png differ diff --git a/logo/sbpy_banner_dark_96.png b/logo/sbpy_banner_dark_96.png new file mode 100644 index 000000000..34ccd6590 Binary files /dev/null and b/logo/sbpy_banner_dark_96.png differ diff --git a/logo/sbpy_logo.ico b/logo/sbpy_logo.ico new file mode 100644 index 000000000..4c136bea3 Binary files /dev/null and b/logo/sbpy_logo.ico differ diff --git a/logo/sbpy_logo.png b/logo/sbpy_logo.png new file mode 100644 index 000000000..46d2fb0c3 Binary files /dev/null and b/logo/sbpy_logo.png differ diff --git a/logo/sbpy_logo.svg b/logo/sbpy_logo.svg deleted file mode 100644 index 4f152d1d5..000000000 --- a/logo/sbpy_logo.svg +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - sbpy - An Astropy Affiliated Package for Small-Body Planetary Astronomy - - - - - - - - - - - - diff --git a/logo/sbpy_logo_dark.png b/logo/sbpy_logo_dark.png new file mode 100644 index 000000000..8e6b1f0a2 Binary files /dev/null and b/logo/sbpy_logo_dark.png differ diff --git a/logo/sbpy_logo_full.pdf b/logo/sbpy_logo_full.pdf deleted file mode 100644 index 3343bebb9..000000000 Binary files a/logo/sbpy_logo_full.pdf and /dev/null differ diff --git a/logo/sbpy_logo_full.png b/logo/sbpy_logo_full.png deleted file mode 100644 index 8bfab762f..000000000 Binary files a/logo/sbpy_logo_full.png and /dev/null differ diff --git a/logo/sbpy_logo_logoonly.pdf b/logo/sbpy_logo_logoonly.pdf deleted file mode 100644 index b15848b2a..000000000 Binary files a/logo/sbpy_logo_logoonly.pdf and /dev/null differ diff --git a/logo/sbpy_logo_logoonly.png b/logo/sbpy_logo_logoonly.png deleted file mode 100644 index 71505eb34..000000000 Binary files a/logo/sbpy_logo_logoonly.png and /dev/null differ diff --git a/logo/sbpy_logo_logoonly.svg b/logo/sbpy_logo_logoonly.svg deleted file mode 100644 index c1a2a37d2..000000000 --- a/logo/sbpy_logo_logoonly.svg +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - diff --git a/logo/sbpy_logo_logoonly_inverted.svg b/logo/sbpy_logo_logoonly_inverted.svg deleted file mode 100644 index 6266e43ff..000000000 --- a/logo/sbpy_logo_logoonly_inverted.svg +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - diff --git a/logo/sbpy_logo_short.pdf b/logo/sbpy_logo_short.pdf deleted file mode 100644 index 7fcfcfad5..000000000 Binary files a/logo/sbpy_logo_short.pdf and /dev/null differ diff --git a/logo/sbpy_logo_short.png b/logo/sbpy_logo_short.png deleted file mode 100644 index 6924813e0..000000000 Binary files a/logo/sbpy_logo_short.png and /dev/null differ diff --git a/logo/sbpy_logo_short.svg b/logo/sbpy_logo_short.svg deleted file mode 100644 index 3fc8e4a8a..000000000 --- a/logo/sbpy_logo_short.svg +++ /dev/null @@ -1,317 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - sbpy - - - diff --git a/logo/sbpy_logo_v2.svg b/logo/sbpy_logo_v2.svg new file mode 100644 index 000000000..1a2145b5a --- /dev/null +++ b/logo/sbpy_logo_v2.svg @@ -0,0 +1,601 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + sbpy + An Astropy affiliated package for small-body planetary astronomy +   + + + + + + + + + + + + + + + sbpy + An Astropy affiliated package for small-body planetary astronomy + + + sbpy + + + + + + + + + + + + + sbpy_banner + sbpy_logo + sbpy_banner_dark + sbpy_logo_dark + sbpy_logo.ico + + diff --git a/pyproject.toml b/pyproject.toml index b222b6bbe..9a7dd3c7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,154 @@ +[project] +name = "sbpy" +description = "An Astropy affiliated package for small-body planetary astronomy" +readme = "README.rst" +authors = [{ name = "sbpy team", email = "msk@astro.umd.edu" }] +license = "BSD-3-Clause" +license-files = ["LICENSE.rst", "licenses/*.rst"] +requires-python = ">=3.10" +dependencies = ["numpy>1.26.0", "astropy>=5.3.3"] +dynamic = ["version"] +keywords = [ + "astronomy", + "astrophysics", + "planetary", + "asteroid", + "comet", + "space", + "science", +] +classifiers = [ + "Intended Audience :: Science/Research", + "Programming Language :: C", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering :: Astronomy", + "Topic :: Scientific/Engineering :: Physics", +] + +[project.urls] +homepage = "https://sbpy.org" +documentation = "https://sbpy.readthedocs.io/" +repository = "https://github.com/NASA-Planetary-Science/sbpy" + [build-system] -requires = ["setuptools", - "setuptools_scm", - "wheel"] +requires = ["setuptools>=77", "setuptools_scm>=8.0.0"] build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +write_to = "sbpy/_version.py" + +[tool.setuptools] +zip-safe = false +include-package-data = true + +[tool.setuptools.packages.find] + +[tool.setuptools.package-data] +sbpy = ["*.fits", "*.csv", "*.txt"] + +[project.optional-dependencies] +recommended = [ + "ads>=0.12", + "astroquery>=0.4.5", + "scipy>=1.10", + "synphot>=1.1.1", +] +all = [ + "ads>=0.12", + "astroquery>=0.4.5", + "ginga", + "photutils", + # "pyoorb", + "pyyaml", + "scipy>=1.10", + "synphot>=1.1.1", +] +test = [ + "pytest>=8.0", + "pytest-astropy>=0.10", + "pytest-astropy-header>=0.2.1", + "pytest-doctestplus>=0.12", + "pytest-remotedata", + "pytest-xdist", + "coverage", +] +docs = [ + "sbpy[all,test]", + "astropy!=6.1.*", + "matplotlib>=3.8", + "packaging", + "scipy>=1.10", + "sphinx-astropy>=1.9.1", + "sphinx-changelog>=1.2.0", + "sphinx_design", + "sphinxcontrib-globalsubs >= 0.1.1", +] + +[project.scripts] +sbpy-ephem = "sbpy.data.ephem.cli:EphemerisCLI.run" + +[project.entry-points."ginga.rv.plugins"] +cometaryenhancements = "sbpy.ginga_plugins:setup_cometaryenhancements" + +[tool.pytest.ini_options] +minversion = "8.0" +testpaths = ["sbpy", "docs"] +norecursedirs = ["docs[\\/]_build"] +astropy_header = true +doctest_plus = "enabled" +text_file_format = "rst" +remote_data_strict = true +addopts = ["--doctest-rst", "--doctest-plus", "--color=yes"] +xfail_strict = true +filterwarnings = [ + "ignore:numpy.ufunc size changed:RuntimeWarning", + "ignore:numpy.ndarray size changed:RuntimeWarning", +] +doctest_norecursedirs = [ + "*/setup_package.py", + "docs/_build", + "*/compile_fieldnames.py", +] +doctest_subpackage_requires = [ + "docs/sbpy/photometry.rst = astroquery", + "docs/sbpy/data/ephem.rst = astroquery", + "docs/sbpy/data/obs.rst = astroquery", + "docs/sbpy/data/orbit.rst = astroquery,oorb", + "docs/sbpy/data/phys.rst = astroquery", +] + +[tool.coverage] +[tool.coverage.run] +omit = [ + "sbpy/__init__*", + "sbpy/**/conftest.py", + "sbpy/**/tests/*", + "sbpy/extern/*", + "sbpy/version*", + "*/sbpy/__init__*", + "*/sbpy/**/conftest.py", + "*/sbpy/**/tests/*", + "*/sbpy/extern/*", + "*/sbpy/version*", +] + +[tool.coverage.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 defensive assertion code: + "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", +] diff --git a/sbpy/__init__.py b/sbpy/__init__.py index 2565228fe..dc6187b67 100644 --- a/sbpy/__init__.py +++ b/sbpy/__init__.py @@ -1,16 +1,9 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst """ -This is an Astropy affiliated package. +sbpy: The Small Bodies Python package """ -# Affiliated packages may add whatever they like to this file, but -# should keep this content at the top. -# ---------------------------------------------------------------------------- -from ._astropy_init import * -# ---------------------------------------------------------------------------- +from importlib.metadata import version as _version - -# For egg_info test builds to pass, put package imports here. -# if not _ASTROPY_SETUP_: -# from sbpy import * +__version__ = _version(__name__) diff --git a/sbpy/_astropy_init.py b/sbpy/_astropy_init.py deleted file mode 100644 index bd4532450..000000000 --- a/sbpy/_astropy_init.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under a 3-clause BSD style license - see LICENSE.rst -import os - -__all__ = ['__version__', 'test'] - -try: - from .version import version as __version__ -except ImportError: - __version__ = '' - -# Create the test function for self test -from astropy.tests.runner import TestRunner -test = TestRunner.make_test_runner_in(os.path.dirname(__file__)) diff --git a/sbpy/_dev/__init__.py b/sbpy/_dev/__init__.py new file mode 100644 index 000000000..d64602c74 --- /dev/null +++ b/sbpy/_dev/__init__.py @@ -0,0 +1,6 @@ +""" +This package contains utilities that are only used when developing sbpy +in a copy of the source repository. + +These files are not installed, and should not be assumed to exist at runtime. +""" diff --git a/sbpy/_dev/scm_version.py b/sbpy/_dev/scm_version.py new file mode 100644 index 000000000..f1c06f274 --- /dev/null +++ b/sbpy/_dev/scm_version.py @@ -0,0 +1,11 @@ +# from astropy... +# Try to use setuptools_scm to get the current version; this is only used +# in development installations from the git repository. +from pathlib import Path + +try: + from setuptools_scm import get_version + + version = get_version(root=Path(__file__).parents[2]) +except Exception: + raise ImportError("setuptools_scm broken or not installed") diff --git a/sbpy/activity/dust.py b/sbpy/activity/dust.py index 43dd598ab..97b7b48d7 100644 --- a/sbpy/activity/dust.py +++ b/sbpy/activity/dust.py @@ -332,7 +332,7 @@ def from_fluxd(cls, wfb, fluxd, aper, eph, **kwargs): Ephemerides of the comet. Required fields: 'rh', 'delta'. Optional: 'phase'. - **kwargs + **kwargs : dict Keyword arguments for `~to_fluxd`. """ @@ -520,7 +520,7 @@ def to_fluxd(self, wfb, aper, eph, unit=None, phasecor=False, Phi=None): Phi : callable, optional Phase function, see :func:`~Afrho.to_phase`. - **kwargs + kwargs : dict Keyword arguments for `~Sun.observe`. diff --git a/sbpy/calib/core.py b/sbpy/calib/core.py index 25711f81f..60cb86eb1 100644 --- a/sbpy/calib/core.py +++ b/sbpy/calib/core.py @@ -197,7 +197,7 @@ def observe(self, wfb, unit=None, interpolate=False, **kwargs): spectral resolution of the source is close to that of the requested wavelengths. - **kwargs + **kwargs : dict Additional keyword arguments for `~synphot.observation.Observation`, e.g., ``force``. diff --git a/sbpy/data/ephem/cli.py b/sbpy/data/ephem/cli.py index 824ce1655..abffb320b 100644 --- a/sbpy/data/ephem/cli.py +++ b/sbpy/data/ephem/cli.py @@ -11,7 +11,7 @@ import numpy as np import sys import argparse -from typing import Any, Dict, List, Optional, Set, Union +from typing import Any, Optional import astropy.units as u from astropy.time import Time @@ -45,9 +45,9 @@ class EphemerisCLI: """ @requires("astroquery") - def __init__(self, argv: Optional[List[str]] = None) -> None: + def __init__(self, argv: Optional[list[str]] = None) -> None: self.args: argparse.Namespace = self.parse_args(argv) - self.epochs: Dict[str, Any] = self._format_epochs(self.args) + self.epochs: dict[str, Any] = self._format_epochs(self.args) self.eph: Ephem if self.args.service == EphemerisService.mpc: @@ -79,7 +79,7 @@ def run(cls) -> None: # pragma: no cover cli.eph.table.pprint_all() @staticmethod - def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace: + def parse_args(argv: Optional[list[str]] = None) -> argparse.Namespace: """Parse command-line arguments. Parameters @@ -203,7 +203,7 @@ def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace: return args @staticmethod - def _format_epochs(args) -> Dict[str, Any]: + def _format_epochs(args) -> dict[str, Any]: """Format the epochs dictionary.""" epochs: dict = { @@ -211,7 +211,7 @@ def _format_epochs(args) -> Dict[str, Any]: "step": args.step, "stop": args.stop, } - defined_attributes: Set[str] = { + defined_attributes: set[str] = { k for k in ["start", "stop", "step", "number"] if getattr(args, k) is not None @@ -246,7 +246,7 @@ def horizons(self) -> Ephem: # return closest apparition closest_apparition: bool = False no_fragments: bool = False - id_type: Union[str, None] = self.args.id_type + id_type: str | None = self.args.id_type try: Names.parse_comet(self.args.target) jd_mid = np.mean((self.epochs["start"].jd, self.epochs["stop"].jd)) @@ -315,7 +315,7 @@ def _format_eph(self, eph: Ephem) -> Ephem: ) # normalize output for most common columns - first_fields: List[str] = [ + first_fields: list[str] = [ "target", "date", "RA", @@ -337,7 +337,7 @@ def _format_eph(self, eph: Ephem) -> Ephem: eph.table.rename_column(translated, k) # re-order - fields: List[str] = eph.field_names + fields: list[str] = eph.field_names for k in reversed(first_fields): if k not in fields: continue diff --git a/sbpy/data/ephem/core.py b/sbpy/data/ephem/core.py index 37a2fa5f5..28843d948 100644 --- a/sbpy/data/ephem/core.py +++ b/sbpy/data/ephem/core.py @@ -361,7 +361,7 @@ def from_mpc( `~astropy.coordinates.Angle.to_string` using these keyword arguments, e.g., ``{'sep': ':', 'precision': 0}``. - **kwargs + **kwargs : dict Additional keyword arguments are passed to `~astroquery.mpc.MPC.get_ephemerides`: ``eph_type``, ``proper_motion``, ``proper_motion_unit``, ``suppress_daytime``, diff --git a/sbpy/dynamics/models.py b/sbpy/dynamics/models.py index d6a09ab3a..ff740251b 100644 --- a/sbpy/dynamics/models.py +++ b/sbpy/dynamics/models.py @@ -49,7 +49,7 @@ class DynamicalModel(abc.ABC): Parameters ---------- - **kwargs + **kwargs : dict Arguments passed on to `~scipy.integrate.solve_ivp`. Units are seconds, km, and km/s, e.g., ``max_step`` is a float value in units of seconds. For relative and absolute tolerance keywords, ``rtol`` and ``atol``, @@ -186,7 +186,7 @@ class FreeExpansion(DynamicalModel): Parameters ---------- - **kwargs + **kwargs : dict Arguments passed on to `~scipy.integrate.solve_ivp`. Units are seconds, km, and km/s, e.g., ``max_step`` is a float value in units of seconds. For relative and absolute tolerance keywords, ``rtol`` and ``atol``, @@ -221,7 +221,7 @@ class SolarGravity(DynamicalModel): Parameters ---------- - **kwargs + **kwargs : dict Arguments passed on to `~scipy.integrate.solve_ivp`. Units are seconds, km, and km/s, e.g., ``max_step`` is a float value in units of seconds. For relative and absolute tolerance keywords, ``rtol`` and ``atol``, @@ -307,7 +307,7 @@ class SolarGravityAndRadiationPressure(DynamicalModel): Parameters ---------- - **kwargs + **kwargs : dict Arguments passed on to `~scipy.integrate.solve_ivp`. Units are seconds, km, and km/s, e.g., ``max_step`` is a float value in units of seconds. For relative and absolute tolerance keywords, ``rtol`` and ``atol``, diff --git a/sbpy/dynamics/state.py b/sbpy/dynamics/state.py index 98cd6f29f..a41aad8ac 100644 --- a/sbpy/dynamics/state.py +++ b/sbpy/dynamics/state.py @@ -16,15 +16,9 @@ ] import abc -import sys -from typing import Iterable, Optional, TypeVar, Union +from typing import Iterable, Optional, TypeVar from packaging.version import Version -if sys.version_info[:2] < (3, 11): - Self = TypeVar("Self", bound="StateBase") -else: - from typing import Self - import numpy as np import astropy from astropy.time import Time @@ -36,6 +30,9 @@ from ..data.ephem import Ephem from ..exceptions import SbpyException +StateBaseType = TypeVar("StateBaseType", bound="StateBase") +StateType = TypeVar("StateType", bound="StateBase") + class SolverFailed(SbpyException): """DynamicalModel solver failed.""" @@ -109,7 +106,7 @@ def __init__( self, r: u.Quantity, v: u.Quantity, - t: Union[u.Quantity, Time], + t: u.Quantity | Time, frame: Optional[FrameInputTypes] = None, ) -> None: frame_class: BaseCoordinateFrame = self._get_frame_class(frame) @@ -142,7 +139,7 @@ def __init__( "`State` only supports time as a quantity with `ArbitraryFrame`." ) - t_: Union[Time, u.Quantity, list] + t_: Time | u.Quantity | list[Time | u.Quantity] if np.size(t) != len(self): t_ = [t] * len(self) else: @@ -168,11 +165,11 @@ def __len__(self): else: return self.r.shape[0] - def __getitem__(self, k: Union[int, tuple, slice]) -> Self: + def __getitem__(self, k: int | tuple | slice) -> StateBaseType: """Get the state(s) at ``k``.""" return State(self.r[k], self.v[k], self.t[k], frame=self.frame) - def __add__(self, other: Self) -> Self: + def __add__(self, other: StateBaseType) -> StateBaseType: """Vector addition of two states. Time is taken from the left operand. @@ -186,7 +183,7 @@ def __add__(self, other: Self) -> Self: frame=self.frame, ) - def __sub__(self, other: Self) -> Self: + def __sub__(self, other: StateBaseType) -> StateBaseType: """Vector subtraction of two states. Time is taken from the left operand. @@ -195,7 +192,7 @@ def __sub__(self, other: Self) -> Self: return self + -other - def __neg__(self) -> Self: + def __neg__(self) -> StateBaseType: """Invert the direction of the state vector position and velocity.""" return State( -self.r, @@ -212,8 +209,8 @@ def __abs__(self) -> tuple[u.Quantity, u.Quantity]: @staticmethod def _get_frame_class( - frame_input: Union[None, FrameInputTypes] - ) -> Union[None, BaseCoordinateFrame]: + frame_input: FrameInputTypes | None, + ) -> BaseCoordinateFrame | None: """Get a frame class based on allowed ``State`` frame input.""" frame_class: BaseCoordinateFrame @@ -276,7 +273,7 @@ def rv(self) -> np.ndarray: return np.hstack([self.r.to_value("km"), self.v.to_value("km/s")]) @property - def t(self) -> Union[Time, u.Quantity]: + def t(self) -> Time | u.Quantity: """Time.""" return self._t @@ -286,7 +283,7 @@ def arbitrary_time(self) -> bool: return isinstance(self.t, u.Quantity) @property - def frame(self) -> Union[BaseCoordinateFrame, None]: + def frame(self) -> BaseCoordinateFrame | None: return self._data.replicate_without_data() def to_skycoord(self) -> SkyCoord: @@ -297,7 +294,7 @@ def to_skycoord(self) -> SkyCoord: else: return SkyCoord(self._data, obstime=self.t, representation_type="cartesian") - def transform_to(self, frame: FrameInputTypes) -> Self: + def transform_to(self, frame: FrameInputTypes) -> StateBaseType: """Transform state into another reference frame. @@ -334,7 +331,7 @@ def transform_to(self, frame: FrameInputTypes) -> Self: class State(StateBase): @classmethod - def from_states(cls, states: Iterable[Self]) -> Self: + def from_states(cls, states: Iterable[StateType]) -> StateType: """Initialize from a list of states. The resulting reference frame will be that of ``states[0]``. @@ -351,12 +348,12 @@ def from_states(cls, states: Iterable[Self]) -> Self: r: list[u.Quantity] = [state.r for state in states_] v: list[u.Quantity] = [state.v for state in states_] - t: list[Union[u.Quantity, Time]] = [state.t for state in states_] + t: list[u.Quantity | Time] = [state.t for state in states_] return State(r, v, t, frame=frame) @classmethod - def from_skycoord(cls, coords: SkyCoord) -> Self: + def from_skycoord(cls, coords: SkyCoord) -> StateType: """Initialize from astropy `~astropy.coordinates.SkyCoord`. @@ -382,7 +379,7 @@ def from_ephem( cls, eph: Ephem, frame: Optional[FrameInputTypes] = None, - ) -> Self: + ) -> StateType: """Initialize from an `~sbpy.data.Ephem` object. @@ -438,7 +435,7 @@ def from_ephem( " velocity fields." ) - def observe(self, target: Self) -> SkyCoord: + def observe(self, target: StateType) -> SkyCoord: """Project a target's position onto the sky. diff --git a/sbpy/dynamics/syndynes.py b/sbpy/dynamics/syndynes.py index effed4063..a198fbcbf 100644 --- a/sbpy/dynamics/syndynes.py +++ b/sbpy/dynamics/syndynes.py @@ -18,15 +18,9 @@ ] import abc -import sys import time import logging -from typing import Iterable, Union, Optional, TypeVar - -if sys.version_info[:2] < (3, 11): - Self = TypeVar("Self", bound="StateBase") -else: - from typing import Self +from typing import Iterable, Optional, TypeVar import numpy as np import astropy.units as u @@ -36,7 +30,9 @@ from ..data import Ephem from .models import DynamicalModel, SolarGravityAndRadiationPressure -from .state import StateBase, State +from .state import StateBase, StateBaseType, State + +SynGeneratorType = TypeVar("SynGeneratorType", bound="SynGenerator") class SynStates(StateBase, abc.ABC): @@ -58,7 +54,7 @@ def __init__( self.source: State = source self.initial: State = initial - self.observer: Union[State, None] = observer + self.observer: State | None = observer # syndynes will be single beta and array of ages, synchrones will be # single age and array of betas @@ -71,7 +67,7 @@ def __init__( super().__init__(r, v, t, frame=initial.frame) # generate sky coordinates as needed - self.coords: Union[SkyCoord, None] = ( + self.coords: SkyCoord | None = ( None if observer is None else observer.observe(self) ) @@ -314,7 +310,7 @@ def __len__(self) -> int: """Number of items in the container.""" return len(self._data) - def __getitem__(self, k: Union[int, tuple, slice]) -> SynStates: + def __getitem__(self, k: int | tuple | slice) -> SynStates: return self._data[k] def to_ephem(self) -> Ephem: @@ -414,7 +410,7 @@ class SynGenerator: def __init__( self, source: State, - betas: Union[Iterable, u.Quantity], + betas: Iterable | u.Quantity, ages: u.Quantity, observer: Optional[State] = None, solver: Optional[DynamicalModel] = None, @@ -440,10 +436,10 @@ def __repr__(self) -> str: def at_epochs( cls, source: State, - betas: Union[Iterable, u.Quantity], + betas: Iterable | u.Quantity, epochs: Time, **kwargs: dict, - ) -> Self: + ) -> SynGeneratorType: """An alternative constructor that ejects dust at specific times. @@ -462,7 +458,7 @@ def at_epochs( Specific times to produce dust test particles. The times will be converted to particle ages. - **kwargs + **kwargs : dict Any other `SynGenerator` keyword argument. """ @@ -603,7 +599,7 @@ def synchrones(self) -> Synchrones: return Synchrones([self.synchrone(i) for i in range(len(self.ages))]) - def source_orbit(self, dt: u.Quantity) -> Union[State, tuple[State, SkyCoord]]: + def source_orbit(self, dt: u.Quantity) -> State | tuple[State, SkyCoord]: """Calculate and observe the orbit of the dust source. diff --git a/sbpy/imageanalysis/utils.py b/sbpy/imageanalysis/utils.py index 41803e729..c22938418 100644 --- a/sbpy/imageanalysis/utils.py +++ b/sbpy/imageanalysis/utils.py @@ -162,7 +162,7 @@ def refine_pixel(func, subsample, yx_pixel, yx, **kwargs): The coordinates of the pixel to consider. yx : array The function's origin. - **kwargs + **kwargs : dict Keyword arguments to pass on to `func`. Returns diff --git a/sbpy/spectroscopy/sources.py b/sbpy/spectroscopy/sources.py index 6de151b0f..d17ec662d 100644 --- a/sbpy/spectroscopy/sources.py +++ b/sbpy/spectroscopy/sources.py @@ -93,7 +93,7 @@ def from_array(cls, wave, fluxd, meta=None, **kwargs): meta : dict, optional Meta data. - **kwargs + **kwargs : dict Passed to object initialization. """ @@ -125,7 +125,7 @@ def from_file(cls, filename, wave_unit=None, flux_unit=None, cache : bool, optional If ``True``, cache the contents of URLs. - **kwargs + **kwargs : dict Passed to object initialization. """ @@ -237,7 +237,7 @@ def observe(self, wfb, unit=None, interpolate=False, **kwargs): spectral resolution of the source is close to that of the requested wavelengths. - **kwargs + **kwargs : dict Additional keyword arguments for `~synphot.observation.Observation`, e.g., ``force``. @@ -288,7 +288,7 @@ def observe_bandpass(self, bp, unit=None, **kwargs): Spectral flux density units for the output. The default is W/(m2 μm). - **kwargs + **kwargs : dict Additional keyword arguments for `~synphot.observation.Observation`, e.g., ``force``. @@ -359,7 +359,7 @@ def observe_spectrum(self, wave_or_freq, unit=None, **kwargs): the default is W/(m2 μm) for wavelengths, Jy for frequencies. - **kwargs + **kwargs : dict Additional keyword arguments for `~synphot.observation.Observation`, e.g., ``force``. diff --git a/sbpy/units/core.py b/sbpy/units/core.py index 8bbbdaa3b..bf9d28615 100644 --- a/sbpy/units/core.py +++ b/sbpy/units/core.py @@ -196,7 +196,7 @@ def reflectance(wfb, cross_section=None, reflectance=None, **kwargs): Average reflectance. One of `cross_section` or `reflectance` is required. - **kwargs + **kwargs : dict Keyword arguments for `~Sun.observe()`. diff --git a/sbpy/version.py b/sbpy/version.py new file mode 100644 index 000000000..a04dbcbf0 --- /dev/null +++ b/sbpy/version.py @@ -0,0 +1,43 @@ +# from astropy... + +from packaging.version import Version + +# NOTE: First try _dev.scm_version if it exists and setuptools_scm is installed +# This file is not included in astropy wheels/tarballs, so otherwise it will +# fall back on the generated _version module. +try: + try: + from ._dev.scm_version import version + except ImportError: + from ._version import version +except Exception: + import warnings + + warnings.warn( + f"could not determine {__name__.split('.')[0]} package version; " + "this indicates a broken installation" + ) + del warnings + + version = "0.0.0" + + +# We use Version to define major, minor, micro, but ignore any suffixes. +def split_version(version): + pieces = [0, 0, 0] + + try: + v = Version(version) + pieces = [v.major, v.minor, v.micro] + + except Exception: + pass + + return pieces + + +major, minor, bugfix = split_version(version) + +del split_version # clean up namespace. + +release = "dev" not in version diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index c657dcbd9..000000000 --- a/setup.cfg +++ /dev/null @@ -1,168 +0,0 @@ - -[metadata] -name = sbpy -package_name = sbpy -author = sbpy team -author_email = msk@astro.umd.edu -license = BSD 3-Clause -license_files = - LICENSE.rst -url = https://sbpy.org -description = Python module for small-body planetary astronomy -long_description = file: README.rst -long_description_content_type = text/x-rst -edit_on_github = False -github_project = NASA-Planetary-Science/sbpy -keywords = astronomy, astrophysics, planetary, asteroid, comet, space, science -classifiers = - Intended Audience :: Science/Research - License :: OSI Approved :: BSD License - Programming Language :: C - Programming Language :: Python :: 3 - Topic :: Scientific/Engineering :: Astronomy - Topic :: Scientific/Engineering :: Physics - -[options] -packages = find: -zip_save = False -python_requires = >=3.9 -setup_requires = setuptools_scm - -# keep requirements in synchronization with docs/install.rst -install_requires = - numpy>=1.24.0 - astropy>=5.3.3 -include_package_data = True - -[options.extras_require] -recommended = - ads>=0.12 - astroquery>=0.4.5 - scipy>=1.10 - synphot>=1.1.1 -all = - ads>=0.12 - astroquery>=0.4.5 - ginga - photutils - pyoorb - pyyaml - scipy>=1.10 - synphot>=1.1.1 -test = - pytest>=7.0 - pytest-astropy>=0.10 - pytest-astropy-header>=0.2.1 - pytest-doctestplus>=0.12 - pytest-remotedata - pytest-xdist - coverage -docs = - sbpy[all,test] - matplotlib>=3.8 - sphinx-astropy>=1.3 - astropy!=6.1.* - scipy>=1.10 - numpy<2 - -[options.package_data] -* = *.fits *.csv *.txt - -[options.entry_points] -ginga.rv.plugins = - cometaryenhancements = sbpy.ginga_plugins:setup_cometaryenhancements - -console_scripts = - sbpy-ephem = sbpy.data.ephem.cli:EphemerisCLI.run - -[tool:pytest] -minversion = 7.0 -testpaths = "sbpy" "docs" -norecursedirs = docs/_build -astropy_header = true -doctest_plus = enabled -text_file_format = rst -remote_data_strict = true -addopts = --doctest-rst --doctest-plus --ignore-glob="*/compile_fieldnames.py" --color=yes -xfail_strict = true -doctest_norecursedirs = - */setup_package.py - docs/_build -filterwarnings = - ignore:numpy\.ufunc size changed:RuntimeWarning - ignore:numpy\.ndarray size changed:RuntimeWarning - -# The following is to work around an issue building the documentation (see -# #383). The prefered approach is to use doctest-requires at the code-block -# level (e.g., this marks all orbit.rst tests as needed oorb, but only 2 of 9 -# blocks require it). Relevant doctest-requires directives have been commented -# out. -doctest_subpackage_requires = - docs/sbpy/photometry.rst = astroquery - docs/sbpy/data/ephem.rst = astroquery - docs/sbpy/data/obs.rst = astroquery - docs/sbpy/data/orbit.rst = astroquery,oorb - docs/sbpy/data/phys.rst = astroquery - -# [coverage:run] -# omit = -# sbpy/_astropy_init* -# sbpy/conftest.py -# sbpy/*setup_package* -# sbpy/tests/* -# sbpy/*/tests/* -# sbpy/*/*/tests/* -# sbpy/extern/* -# sbpy/version* -# */sbpy/_astropy_init* -# */sbpy/conftest.py -# */sbpy/*setup_package* -# */sbpy/tests/* -# */sbpy/*/tests/* -# */sbpy/*/*/tests/* -# */sbpy/extern/* -# */sbpy/version* - - -# [coverage: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_ - -# open_files_ignore = "astropy.log" "/etc/hosts" "*.ttf" -# filterwarnings = -# error -# ignore:unclosed file:ResourceWarning -# ignore:unclosed =0.0.dev0 -# The following indicates which extras_require from setup.cfg will be installed +# The following indicates which extras_require from pyproject.toml will be installed extras = test: test alldeps: all commands = pip freeze - !cov: pytest --pyargs sbpy {toxinidir}/docs {env:MPLFLAGS} {posargs} - cov: pytest --pyargs sbpy {env:MPLFLAGS} --cov sbpy --cov-config={toxinidir}/setup.cfg {posargs} - cov: coverage xml -o {toxinidir}/coverage.xml + cov: pytest --pyargs sbpy {toxinidir}/docs {env:MPLFLAGS} --cov sbpy --cov-config={toxinidir}/pyproject.toml --cov-report xml:{toxinidir}/coverage.xml {posargs} [testenv:build_docs] basepython = py311 @@ -93,6 +85,7 @@ description = invoke sphinx-build to build the HTML docs extras = docs commands = pip freeze + python3 compile_fieldnames.py sphinx-build -W -b html . _build/html {posargs} [testenv:linkcheck] @@ -105,7 +98,7 @@ commands = sphinx-build -W -b linkcheck . _build/html --keep-going [testenv:codestyle] -# We list the warnings/errors to check for here rather than in setup.cfg because +# We list the warnings/errors to check for here rather than in pyproject.toml because # we don't want these options to apply whenever anyone calls flake8 from the # command-line or their code editor - in this case all warnings/errors should be # checked for. The warnings/errors we check for here are: