Code Monkey home page Code Monkey logo

azely's Introduction

azely

Release Python Downloads DOI Tests

Computation and plotting of azimuth and elevation for astronomical objects

TL;DR

Azely (pronounced as "as-elie") is a Python package for computation and plotting of horizontal coordinates (azimuth and elevation; az/el, hereafter) of astronomical objects at given location and time. While computation and plotting are realized by Astropy and Matplotlib, what azely provides is high-level API to use them easily. In fact azely offers one-liner to compute and plot, for example, one-day elevation of the Sun in Tokyo:

>>> azely.compute('Sun', 'Tokyo').el.plot(ylim=(0, 90))

one-liner.svg

Features

  • High-level API: azely provides a simple yet powerful compute() function. Users can complete most of operation with it (e.g., information acquisition and computation).
  • Handy output: azely's output (from compute()) is pandas DataFrame, a de facto standard data structure of Python. Users can convert it to other formats like CSV and plot it by Matplotlib using builtin methods.
  • Web information acquisition: azely can automatically acquire object and location information (i.e., longitude and latitude) from online services (e.g., catalogues or maps). Obtained information is cached in a local TOML file for an offline use.
  • User-defined information: azely also offers to use user-defined object and location information written in a TOML file.

Requirements

  • Python: 3.7, 3.8, 3.9, and 3.10 (tested by author)
  • Dependencies: See pyproject.toml

Installation

$ pip install azely

Basic usage

This section describes basic az/el computation using compute() function.

Compute function

Azely's compute() function receives the following parameters and returns pandas DataFrame (df):

>>> import azely
>>> df = azely.compute(object, site, time, view, **options)

This means that azely will compute az/el of object observed from site at (on) time in view. For example, the following code will compute az/el of Sun observed from ALMA AOS on Jan. 1st 2020 in Tokyo.

>>> df = azely.compute('Sun', 'ALMA AOS', '2020-01-01', 'Tokyo')

Acceptable formats of each parameter and examples are as follows.

Parameter Acceptable format Description Examples
object <obj. name> name of object to be searched 'Sun', 'NGC1068'
<toml>:<obj. name> user-defined object to be loaded (see below) 'user.toml:M42', 'user:M42' (also valid)
site 'here' (default) current location (guess by IP address)
<loc. name> name of location to be searched 'ALMA AOS', 'Tokyo'
<toml>:<loc. name> user-defined location to be loaded (see below) 'user.toml:ASTE', 'user:ASTE' (also valid)
time 'today' (default) get one-day time range of today
'now' get current time
<time> start time of one-day time range '2020-01-01', '1/1 12:00', 'Jan. 1st'
<time> to <time> start and end of time range '1/1 to 1/3', 'Jan. 1st to Jan. 3rd'
view '' (default) use timezone of site
<tz name> name of timezone database 'Asia/Tokyo', 'UTC'
<loc. name> name of location from which timezone is identified same as site's examples
<toml>:<loc. name> user-defined location from which timezone is identified same as site's examples

Output DataFrame

The output DataFrame contains az/el expressed in units of degrees and local sidereal time (LST) at site indexed by time in view:

>>> print(df)
                                  az         el             lst
Asia/Tokyo
2020-01-01 00:00:00+09:00  94.820323  68.416756 17:07:59.405556
2020-01-01 00:10:00+09:00  94.333979  70.709575 17:18:01.048298
2020-01-01 00:20:00+09:00  93.856123  73.003864 17:28:02.691044
2020-01-01 00:30:00+09:00  93.388695  75.299436 17:38:04.333786
2020-01-01 00:40:00+09:00  92.935403  77.596109 17:48:05.976529
...                              ...        ...             ...
2020-01-01 23:20:00+09:00  96.711830  59.146249 16:31:49.389513
2020-01-01 23:30:00+09:00  96.185941  61.431823 16:41:51.032256
2020-01-01 23:40:00+09:00  95.664855  63.719668 16:51:52.674998
2020-01-01 23:50:00+09:00  95.147951  66.009577 17:01:54.317740
2020-01-02 00:00:00+09:00  94.634561  68.301349 17:11:55.960483

[145 rows x 3 columns]

Example

Here is a sample script which will plot one-day elevation of the Sun and candidates of black hole shadow observations at ALMA AOS on Apr. 11th 2017 in UTC.

import azely
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')

fig, ax = plt.subplots(figsize=(12, 4))

site = 'ALMA AOS'
time = 'Apr. 11th 2017'
view = 'UTC'

for obj in ('Sun', 'Sgr A*', 'M87', 'M104', 'Cen A'):
    df = azely.compute(obj, site, time, view)
    df.el.plot(ax=ax, label=obj)

ax.set_title(f'site: {site}, view: {view}, time: {time}')
ax.set_ylabel('Elevation (deg)')
ax.set_ylim(0, 90)
ax.legend()

multiple-objects.svg

Advanced usage

This section describes advanced usage of azely by special DataFrame accessor and local TOML files. Note that azely will create a config directory, $XDG_CONFIG_HOME/azely (if the environment variable exists) or ~/.config/azely, after importing azely for the first time. TOML files for configuration (config.toml) and cached information (objects.toml, locations.toml) will be automatically created in it.

Plotting in local sidereal time

The compute() function does not accept local sidereal time (LST) as view (i.e., view='LST') because LST has no information on year and date. Instead an output DataFrame has in_lst property which provides az/el with a LST index converted from the original time index. For example, the following code will plot elevation of an object in LST:

>>> df.in_lst.el.plot()

In order to use LST values as an index of DataFrame, LST has pseudo dates which start from 1970-01-01. Please ignore them or hide them by using Matplotlib DateFormatter when you plot the result. Here is a sample script which has JST time axis at the bottom and LST axis at the top of a figure, respectively.

import matplotlib.dates as mdates

fig, ax = plt.subplots(figsize=(12, 4))
twin = ax.twiny()

df = azely.compute('Sun', 'Tokyo', '2020-01-01')
df.el.plot(ax=ax, label=df.object.name)
df.in_lst.el.plot(ax=twin, alpha=0)

ax.set_ylabel("Elevation (deg)")
ax.set_ylim(0, 90)
ax.legend()

formatter = mdates.DateFormatter('%H:%M')
twin.xaxis.set_major_formatter(formatter)
fig.autofmt_xdate(rotation=0)

lst-axis.svg

User-defined information

Azely offers to use user-defined information from a TOML file. Here is a sample TOML file (e.g., user.toml) which has custom object and location informaiton.

# user.toml

[ASTE]
name = "ASTE Telescope"
longitude = "-67.70317915"
latitude = "-22.97163575"
altitude = "0"

[GC]
name = "Galactic center"
frame = "galactic"
longitude = "0deg"
latitude = "0deg"

If it is located in a current directory or in the azely's config directory, users can use the information like:

>>> df = azely.compute('user:GC', 'user:ASTE', '2020-01-01')

Cached information

Object and location information obtained from online services is cached to TOML files (objects.toml, locations.toml) in the azely's config directory with the same format as user-defined files. If a query argument is given with '!' at the end of it, then the cached values are forcibly updated by a new acquisition. This is useful, for example, when users want to update a current location:

>>> df = azely.compute('Sun', 'here!', '2020-01-01')

Customizing default values

Users can modify default values of the compute() function by editing the azely's config TOML file (config.toml) in the azely's config directory like:

# config.toml

[compute]
site = "Tokyo"
time = "now"

Then compute('Sun') becomes equivalent to compute('Sun', 'Tokyo', 'now').

azely's People

Contributors

astropenguin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

azely's Issues

Update force-query feature

Use query='aaa!' instead of query='!aaa' to forcibly update information of an object or a location.

  • Update the cache_to decorator and get_* functions
  • Update related description in docstrings and README

Add feature of multiple objects

Add a utility function to parse queries of objects to an iterable. For example, the proposed function lists names of Messier objects in user.toml and all names in solar.toml:

for obj in func(['user:^M[0-9]+$', 'solar:*']):
    print(obj)
user:M1
user:M2
...
solar:Sun
solar:Moon
...

Then update the compute() function like:

for df in azely.compute(['user:^M[0-9]+$', 'solar:*'], 'Tokyo', ...):
    df.el.plot(ylim=(0, 90))

Note that the utility function must only be activated when obj is given as a list or a tuple and the return be a generator; otherwise obj is never parsed even if it is regex-like (i.e., with obj='solar:*', it tries to find an object whose names is * in user.toml).

Add option for forcibly updating cache

Implement an option for forcibly updating cache
when query string is given with the special keyword (!).

import azely

# not updated (if cached value already exists)
location = azely.get_location("here")

# forcibly updated
location = azely.get_location("!here")

Use today as a default value of time

  • Use time='today' as a default value of azely.compute() and azely.time.get_time()
  • Update docstrings that describe default time value
  • Update README

Update docs

Update (or fix) the following docs.

  • Add description of default values in the azel module and the compute() function
  • Add example images of codes in README

Update Flake8 config

  • Use minimum Flake8 config (.flake8)
  • Update codes to be compatible with the new config

Use case-insensitive query

Make sure that 'query', 'QUERY', and 'QuErY' are considered to be same.
Note that other parameters are still case-sensitive at this moment:
For example, frame='ICRS' is not allowed.

Release v0.6.0

  • Update version numbers written in:
    • pyproject.toml
    • azely/__init__.py
    • docs/conf.py
    • tests/test_metadata.py
  • Remove docs/images/example.png
  • Update image URLs in README
    • use .../v0.6.0/docs/_static/*.svg instead of .../master/docs/_static/*.svg

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.