-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ch_ephem): CHIME ephemeris refactored from ch_util.
Extracts a lot of `ch_util.ephemeris` into a separate package. General changes: * Solar and lunar ephemeris functions have been converted into `caput.time.Observer` methods: radiocosmology/caput#271 * Other functions that take a `Observer` object, now use `None` as a default, and load the `chime` observer during execution if necessary. More comments on specific submodules follow. Catalogs: This contains all the `ch_util/catalogs` plus a function (`ch_ephem.catalogs.load`) to read them and return the parsed JSON. The standard source catalogues loaded by the `sources` submodule need to move to `ch_ephem`. The other catalogues could stay in `ch_util`, but it seems simpler to me to keep them all in the same place and provide a uniform interface to them. Coord: Co-ordinate transforms etc. These are essentially unchanged from their versions in `ch_util.ephemeris`. Observers: Re-creates all the `caput.time.Observers` which used to be created by `ch_util.ephemeris`, but for the most part, they have to be fetched via name from the `get()` function. The exception to this is the `chime` Observer, which can be directly imported, since it's the one usually needed. Position data for the observers is now in a YAML data file `instruments.yaml` which is parsed at import time. New instrument `Observer` objects can be added to `ch_ephem` just by adding information for it to the YAML file. Also note that `Observers` returned by this submodule have an extra attribute, `rotation`, inserted into their `__dict__`, which is not in `caput`. This rotation is needed by `ch_ephem.coord.peak_ra`. If we don't want to do this to these `Observers`, one other options would be to keep `peak_ra` in `ch_util` (moving it to, say, `ch_util.tools`), and then there's no need for rotation information in this module. Like `sources`, this submodule reads data from disk at import time, so is not automatically imported into the base `ch_ephem` object. Pointing: Just Galt telescope pointing routines, unchanged from `ch_util.ephemeris`. These are another candidate we could consider putting somewhere else in ch_util, if we don't want them here. Sources: Loads the standard source catalogs, and provides the calibrator objects `CasA`, `CygA`, `TauA`, `VirA`. Like `observers`, this submodule reads data from disk at import time, so is not automatically imported into the base `ch_ephem` object. Time: Time utilities, largely unchanged from what was in `ch_util.ephemeris`.
- Loading branch information
1 parent
22b9b1f
commit 7694836
Showing
15 changed files
with
39,736 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
name: ch_ephem-linting | ||
on: | ||
pull_request: | ||
branches: | ||
- master | ||
push: | ||
branches: | ||
- master | ||
|
||
jobs: | ||
|
||
black-check: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up Python 3.11 | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: "3.11" | ||
|
||
- name: Install black | ||
run: pip install black | ||
|
||
- name: Check code with black | ||
run: black --check . | ||
|
||
ruff-check: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Install ruff | ||
run: pip install ruff | ||
|
||
- name: Install ch_ephem | ||
run: pip install . | ||
|
||
- name: Run ruff | ||
run: ruff check . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
# ch_ephem | ||
# CHIME ephemeris | ||
|
||
CHIME ephemeris | ||
This package provides the CHIME ephemeris routines, `ch_ephem`. Most | ||
of this code originated in `ch_util`. | ||
|
||
For general-purpose ephemeris routines, see `caput`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,104 @@ | ||
pass | ||
"""CHIME ephemeris routines | ||
Instrument Observrers and General Ephemeris Routines | ||
==================================================== | ||
Any ephemeris routine which needs to know the location of the | ||
observer on the Earth are accessible via instrument Observer | ||
instances obtainable through :py:meth:`ch_ephem.observers.get`: | ||
>>> import ch_ephem.observers | ||
>>> pathfinder = ch_ephem.observers.get("pathfinder") | ||
>>> pathfinder.solar_transit(...) | ||
The `Observer` instances returned by this method are subclassed from | ||
`caput.time.Observers` and can be used as normal `caput` observers. | ||
Location and geometry data for the instrument observers are defined | ||
in the data file `instruments.yaml` provided as part of `ch_ephem`. | ||
Celestial Intermediate Reference System | ||
======================================= | ||
The precession of the Earth's axis gives noticeable shifts in object | ||
positions over the life time of CHIME. To minimise the effects of this we | ||
need to be careful and consistent with our ephemeris calculations. | ||
Historically Right Ascension has been given with respect to the Vernal | ||
Equinox which has a significant (and unnecessary) precession in the origin of | ||
the RA axis. To avoid this we use the new Celestial Intermediate Reference | ||
System which does not suffer from this issue. | ||
Practically this means that when calculating RA, DEC coordinates for a source | ||
position at a *given time* you must be careful to obtain CIRS coordinates | ||
(and not equinox based ones). Internally using `ch_ephem.coord.object_coords` does | ||
exactly that for you, so for any lookup of coordinates you should use that on | ||
your requested body. | ||
Note that the actual coordinate positions of sources must be specified using | ||
RA, DEC coordinates in ICRS (which is roughly equivalent to J2000). The | ||
purpose of `object_coords` is to transform into new RA, DEC coordinates taking | ||
into account the precession and nutation of the Earth's polar axis since | ||
then. | ||
These kind of coordinate issues are tricky, confusing and hard to debug years | ||
later, so if you're unsure you are recommended to seek some advice. | ||
Radio Source Catalogs | ||
===================== | ||
This package provides several radio source catalogues used by CHIME. The | ||
standard radio source catalogue used by CHIME is available as | ||
`ch_ephem.sources.source_dictionary`: | ||
>>> from ch_ephem.sources import source_dictionary | ||
>>> source_dictionary['CAS_A'].ra | ||
<Angle 23h 23m 27.94s> | ||
The four standard CHIME cailbrators are also available by name: | ||
>>> from ch_ephem.sources import CasA, CygA, VirA, TauA | ||
>>> CasA.ra | ||
<Angle 23h 23m 27.94s> | ||
Additional catalogues which are not part of the standard radio source catalogue | ||
are also available through the `ch_ephem.catalogs` module. Any catalog can be | ||
accessed using :py:meth:`ch_ephem.catalogs.load`, which takes a catalogue name | ||
and returns a dict containing the parsed JSON representation of the catalog: | ||
>>> import ch_ephem.catalogs | ||
>>> ch_ephem.catalogs.list() | ||
['atnf_psrcat', 'hfb_target_list', 'primary_calibrators_perley2016', 'specfind_v2_5Jy_vollmer2009'] | ||
>>> perley2016 = ch_ephem.catalogs.load('primary_calibrators_perley2016') | ||
>>> perley2016["CAS_A"]["ra"] | ||
350.86642 | ||
Submodules | ||
========== | ||
Note: the submodules `observers` and `sources` read data from disk at import time. | ||
.. autosummary:: | ||
:toctree: _autosummary | ||
catalogs | ||
coord | ||
observers | ||
pointing | ||
sources | ||
time | ||
""" | ||
|
||
__all__ = ["catalogs", "coord", "pointing", "time", "__version__"] | ||
|
||
# We deliberately do not import .observers and .sources here | ||
# because they both perform reads from disk | ||
from . import catalogs, coord, pointing, time | ||
|
||
from importlib.metadata import version, PackageNotFoundError | ||
|
||
try: | ||
__version__ = version("ch_ephem") | ||
except PackageNotFoundError: | ||
# package is not installed | ||
pass | ||
|
||
del version, PackageNotFoundError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
"""CHIME ephemeris source catalogues | ||
Functions | ||
========= | ||
- :py:meth:`list` | ||
- :py:meth:`load` | ||
""" | ||
|
||
from __future__ import annotations | ||
from typing import TYPE_CHECKING | ||
|
||
import glob | ||
import json | ||
import pathlib | ||
|
||
if TYPE_CHECKING: | ||
from collections.abc import Iterable | ||
del TYPE_CHECKING | ||
|
||
|
||
def list() -> list[str]: | ||
"""List available catalogues. | ||
Returns | ||
------- | ||
catalogs : list | ||
A list with the names of available catalogs | ||
""" | ||
|
||
cats = sorted(glob.glob("*.json", root_dir=pathlib.Path(__file__).parent)) | ||
|
||
# Strip ".json" off the end | ||
return [cat[:-5] for cat in cats] | ||
|
||
|
||
def load(name: str) -> Iterable: | ||
"""Read the named catalogue and return the parsed JSON representation. | ||
Parameters | ||
---------- | ||
name : str | ||
The name of the catalogue to load. This is the name of a JSON file | ||
in the `ch_ephem/catalogs` directory, excluding the `.json` suffix. | ||
Returns | ||
------- | ||
catalogue: Iterable | ||
The parsed catalogue. | ||
Raises | ||
------ | ||
JSONDecodeError: | ||
An error occurred while trying to parse the catalogue. | ||
ValueError: | ||
No catalogue with the given name could be found. | ||
""" | ||
path = pathlib.Path(__file__).with_name(name + ".json") | ||
|
||
try: | ||
with path.open() as f: | ||
return json.load(f) | ||
except FileNotFoundError as e: | ||
raise ValueError(f"No such catalogue: {name}") from e |
Oops, something went wrong.