Switch to reify() for computed Time attributes

This commit is contained in:
Brandon Rhodes 2018-05-14 19:58:48 -04:00
parent f24c9be9c6
commit f757bc451f
2 changed files with 72 additions and 49 deletions

14
skyfield/descriptorlib.py Normal file
View File

@ -0,0 +1,14 @@
from functools import update_wrapper
class reify(object):
"""Adapted from Pyramid's `reify()` memoizing decorator."""
def __init__(self, method):
self.method = method
update_wrapper(self, method)
def __get__(self, instance, objtype=None):
if instance is None:
return self
value = self.method(instance)
instance.__dict__[self.__name__] = value
return value

View File

@ -3,6 +3,7 @@ from numpy import (array, concatenate, einsum, float_, interp, isnan, nan,
rollaxis, searchsorted, sin, where, zeros_like)
from time import strftime
from .constants import B1950, DAY_S, T0
from .descriptorlib import reify
from .earthlib import sidereal_time
from .framelib import ICRS_to_J2000 as B
from .functions import load_bundled_npy
@ -470,69 +471,77 @@ class Time(object):
"""Return TT as a tuple (year, month, day, hour, minute, second)."""
return calendar_tuple(self.tt)
def __getattr__(self, name):
# Convenient caching of several expensive functions of time.
# Cache of several expensive functions of time.
@reify
def P(self):
self.P = P = compute_precession(self.tdb)
return P
if name == 'P':
self.P = P = compute_precession(self.tdb)
return P
@reify
def PT(self):
self.PT = PT = rollaxis(self.P, 1)
return PT
if name == 'PT':
self.PT = PT = rollaxis(self.P, 1)
return PT
@reify
def N(self):
self.N = N = compute_nutation(self)
return N
if name == 'N':
self.N = N = compute_nutation(self)
return N
@reify
def NT(self):
self.NT = NT = rollaxis(self.N, 1)
return NT
if name == 'NT':
self.NT = NT = rollaxis(self.N, 1)
return NT
@reify
def M(self):
self.M = M = einsum('ij...,jk...,kl...->il...', self.N, self.P, B)
return M
if name == 'M':
self.M = M = einsum('ij...,jk...,kl...->il...', self.N, self.P, B)
return M
@reify
def MT(self):
self.MT = MT = rollaxis(self.M, 1)
return MT
if name == 'MT':
self.MT = MT = rollaxis(self.M, 1)
return MT
# Conversion between timescales.
# Conversion between timescales.
@reify
def tai(self):
self.tai = tai = self.tt - tt_minus_tai
return tai
if name == 'tai':
self.tai = tai = self.tt - tt_minus_tai
return tai
@reify
def utc(self):
utc = self._utc_tuple()
utc = array(utc) if self.shape else utc
self.utc = utc = utc
return utc
if name == 'utc':
utc = self._utc_tuple()
utc = array(utc) if self.shape else utc
self.utc = utc = utc
return utc
@reify
def tdb(self):
tt = self.tt
return tt + tdb_minus_tt(tt) / DAY_S
if name == 'tdb':
tt = self.tt
self.tdb = tdb = tt + tdb_minus_tt(tt) / DAY_S
return tdb
@reify
def ut1(self):
self.ut1 = ut1 = self.tt - self.delta_t / DAY_S
return ut1
if name == 'ut1':
self.ut1 = ut1 = self.tt - self.delta_t / DAY_S
return ut1
@reify
def delta_t(self):
table = self.ts.delta_t_table
self.delta_t = delta_t = interpolate_delta_t(table, self.tt)
return delta_t
if name == 'delta_t':
table = self.ts.delta_t_table
self.delta_t = delta_t = interpolate_delta_t(table, self.tt)
return delta_t
@reify
def gmst(self):
self.gmst = gmst = sidereal_time(self)
return gmst
if name == 'gmst':
self.gmst = gmst = sidereal_time(self)
return gmst
if name == 'gast':
self.gast = gast = self.gmst + earth_tilt(self)[2] / 3600.0
return gast
raise AttributeError('no such attribute %r' % name)
@reify
def gast(self):
self.gast = gast = self.gmst + earth_tilt(self)[2] / 3600.0
return gast
def __eq__(self, other_time):
if not isinstance(other_time, Time):