A PoC of Kosmorro, before Kosmorro became cool.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

101 lines
3.3 KiB

  1. from skyfield.api import Loader, Topos
  2. from skyfield import almanac
  3. class Ephemeris:
  4. position = None
  5. timescale = None
  6. planets = None
  7. def __init__(self, position):
  8. self.MONTH = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
  9. self.PLANETS = ['mercury', 'venus', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune', 'pluto']
  10. load = Loader('./cache')
  11. self.timescale = load.timescale()
  12. self.planets = load('de421.bsp')
  13. self.position = Topos(latitude_degrees=position['lat'], longitude_degrees=position['lon'])
  14. def compute_ephemeris_for_day(self, year: int, month: int, day: int) -> dict:
  15. ephemeris = {}
  16. time1 = self.timescale.utc(year, month, day, 2)
  17. time2 = self.timescale.utc(year, month, day + 1, 2)
  18. # Compute sunrise and sunset
  19. ephemeris['sun'] = self.get_sun(time1, time2)
  20. ephemeris['moon'] = self.get_moon(year, month, day)
  21. return ephemeris
  22. def get_sun(self, time1, time2) -> dict:
  23. t, y = almanac.find_discrete(time1, time2, almanac.sunrise_sunset(self.planets, self.position))
  24. sunrise = t[0] if y[0] else t[1]
  25. sunset = t[1] if not y[1] else t[0]
  26. return {'rise': sunrise.utc_iso(), 'set': sunset.utc_iso()}
  27. def get_moon(self, year, month, day) -> dict:
  28. time1 = self.timescale.utc(year, month, day - 10)
  29. time2 = self.timescale.utc(year, month, day)
  30. _, y = almanac.find_discrete(time1, time2, almanac.moon_phases(self.planets))
  31. return {'phase': y[-1]}
  32. def compute_ephemeris_for_month(self, year: int, month: int) -> list:
  33. if month == 2:
  34. is_leap_year = (year % 4 == 0 and year % 100 > 0) or (year % 400 == 0)
  35. max_day = 29 if is_leap_year else 28
  36. elif month < 8:
  37. max_day = 30 if month % 2 == 0 else 31
  38. else:
  39. max_day = 31 if month % 2 == 0 else 30
  40. e = []
  41. for day in range(1, max_day + 1):
  42. e.append(self.compute_ephemeris_for_day(year, month, day))
  43. return e
  44. def compute_ephemeris_for_year(self, year: int) -> dict:
  45. e = {}
  46. for month in range(0, 12):
  47. e[self.MONTH[month]] = self.compute_ephemeris_for_month(year, month + 1)
  48. e['seasons'] = self.get_seasons(year)
  49. return e
  50. def get_seasons(self, year: int) -> dict:
  51. t1 = self.timescale.utc(year, 1, 1)
  52. t2 = self.timescale.utc(year, 12, 31)
  53. t, y = almanac.find_discrete(t1, t2, almanac.seasons(self.planets))
  54. seasons = {}
  55. for ti, yi in zip(t, y):
  56. if yi == 0:
  57. season = 'MARCH'
  58. elif yi == 1:
  59. season = 'JUNE'
  60. elif yi == 2:
  61. season = 'SEPTEMBER'
  62. elif yi == 3:
  63. season = 'DECEMBER'
  64. else:
  65. raise AssertionError
  66. seasons[season] = ti.utc_iso()
  67. return seasons
  68. def compute_ephemeris(self, year: int, month: int, day: int):
  69. if day is not None:
  70. return self.compute_ephemeris_for_day(year, month, day)
  71. elif month is not None:
  72. return self.compute_ephemeris_for_month(year, month)
  73. else:
  74. return self.compute_ephemeris_for_year(year)