@@ -18,21 +18,13 @@ | |||||
import argparse | import argparse | ||||
from datetime import date | from datetime import date | ||||
import numpy | |||||
from kosmorrolib import dumper | from kosmorrolib import dumper | ||||
from kosmorrolib.ephemerides import EphemeridesComputer, Position | from kosmorrolib.ephemerides import EphemeridesComputer, Position | ||||
# Fixes the "TypeError: Object of type int64 is not JSON serializable" | |||||
# See https://stackoverflow.com/a/50577730 | |||||
def json_default(obj): | |||||
if isinstance(obj, numpy.int64): | |||||
return int(obj) | |||||
raise TypeError('Object of type ' + str(type(obj)) + ' could not be integrated in the JSON') | |||||
def main(): | def main(): | ||||
args = get_args() | output_formats = get_dumpers() | ||||
args = get_args(list(output_formats.keys())) | |||||
year = args.year | year = args.year | ||||
month = args.month | month = args.month | ||||
day = args.day | day = args.day | ||||
@@ -43,11 +35,18 @@ def main(): | |||||
ephemeris = EphemeridesComputer(Position(args.latitude, args.longitude, altitude=args.altitude)) | ephemeris = EphemeridesComputer(Position(args.latitude, args.longitude, altitude=args.altitude)) | ||||
ephemerides = ephemeris.compute_ephemerides(year, month, day) | ephemerides = ephemeris.compute_ephemerides(year, month, day) | ||||
dump = dumper.TextDumper(ephemerides) | dump = output_formats[args.format](ephemerides) | ||||
print(dump.to_string()) | print(dump.to_string()) | ||||
def get_args(): | def get_dumpers() -> {str: dumper.Dumper}: | ||||
return { | |||||
'text': dumper.TextDumper, | |||||
'json': dumper.JsonDumper | |||||
} | |||||
def get_args(output_formats: [str]): | |||||
today = date.today() | today = date.today() | ||||
parser = argparse.ArgumentParser(description='Compute the ephemerides for a given date, at a given position' | parser = argparse.ArgumentParser(description='Compute the ephemerides for a given date, at a given position' | ||||
@@ -56,6 +55,8 @@ def get_args(): | |||||
' observer positioned at coordinates (0,0), with an altitude of 0.' | ' observer positioned at coordinates (0,0), with an altitude of 0.' | ||||
% today.strftime('%a %b %d, %Y')) | % today.strftime('%a %b %d, %Y')) | ||||
parser.add_argument('--format', '-f', type=str, default=output_formats[0], choices=output_formats, | |||||
help='The format under which the information have to be output') | |||||
parser.add_argument('--latitude', '-lat', type=float, default=0., | parser.add_argument('--latitude', '-lat', type=float, default=0., | ||||
help="The observer's latitude on Earth") | help="The observer's latitude on Earth") | ||||
parser.add_argument('--longitude', '-lon', type=float, default=0., | parser.add_argument('--longitude', '-lon', type=float, default=0., | ||||
@@ -22,6 +22,18 @@ from typing import Union | |||||
from skyfield.api import Topos | from skyfield.api import Topos | ||||
from skyfield.timelib import Time | from skyfield.timelib import Time | ||||
MOON_PHASES = { | |||||
'NEW_MOON': 'New Moon', | |||||
'FIRST_QUARTER': 'First Quarter', | |||||
'FULL_MOON': 'Full Moon', | |||||
'LAST_QUARTER': 'Last Quarter' | |||||
} | |||||
def skyfield_to_moon_phase(val: int) -> str: | |||||
phases = list(MOON_PHASES.keys()) | |||||
return phases[val] | |||||
class Position: | class Position: | ||||
def __init__(self, latitude: float, longitude: float, altitude: float = 0): | def __init__(self, latitude: float, longitude: float, altitude: float = 0): | ||||
@@ -18,9 +18,11 @@ | |||||
from abc import ABC, abstractmethod | from abc import ABC, abstractmethod | ||||
import datetime | import datetime | ||||
import json | |||||
from tabulate import tabulate | from tabulate import tabulate | ||||
from skyfield import almanac | from skyfield.timelib import Time | ||||
from .data import Object | from numpy import int64 | ||||
from .data import Object, AsterEphemerides, MOON_PHASES | |||||
class Dumper(ABC): | class Dumper(ABC): | ||||
@@ -33,6 +35,30 @@ class Dumper(ABC): | |||||
pass | pass | ||||
class JsonDumper(Dumper): | |||||
def to_string(self): | |||||
return json.dumps(self.ephemeris, | |||||
default=self._json_default, | |||||
indent=4) | |||||
@staticmethod | |||||
def _json_default(obj): | |||||
# Fixes the "TypeError: Object of type int64 is not JSON serializable" | |||||
# See https://stackoverflow.com/a/50577730 | |||||
if isinstance(obj, int64): | |||||
return int(obj) | |||||
if isinstance(obj, Time): | |||||
return obj.utc_iso() | |||||
if isinstance(obj, Object): | |||||
obj = obj.__dict__ | |||||
obj.pop('skyfield_name') | |||||
return obj | |||||
if isinstance(obj, AsterEphemerides): | |||||
return obj.__dict__ | |||||
raise TypeError('Object of type "%s" could not be integrated in the JSON' % str(type(obj))) | |||||
class TextDumper(Dumper): | class TextDumper(Dumper): | ||||
def to_string(self): | def to_string(self): | ||||
return '\n\n'.join(['Ephemerides of %s' % self.date.strftime('%A %B %d, %Y'), | return '\n\n'.join(['Ephemerides of %s' % self.date.strftime('%A %B %d, %Y'), | ||||
@@ -69,4 +95,4 @@ class TextDumper(Dumper): | |||||
@staticmethod | @staticmethod | ||||
def get_moon(moon): | def get_moon(moon): | ||||
return 'Moon phase: %s' % almanac.MOON_PHASES[moon['phase']] | return 'Moon phase: %s' % MOON_PHASES[moon['phase']] |
@@ -20,7 +20,7 @@ import datetime | |||||
from skyfield import almanac | from skyfield import almanac | ||||
from skyfield.timelib import Time | from skyfield.timelib import Time | ||||
from .data import Object, Position, AsterEphemerides | from .data import Object, Position, AsterEphemerides, skyfield_to_moon_phase | ||||
from .core import get_skf_objects, get_timescale, ASTERS, MONTHS | from .core import get_skf_objects, get_timescale, ASTERS, MONTHS | ||||
RISEN_ANGLE = -0.8333 | RISEN_ANGLE = -0.8333 | ||||
@@ -48,7 +48,7 @@ class EphemeridesComputer: | |||||
_, moon_phase = almanac.find_discrete(time1, time2, almanac.moon_phases(get_skf_objects())) | _, moon_phase = almanac.find_discrete(time1, time2, almanac.moon_phases(get_skf_objects())) | ||||
return {'phase': moon_phase[-1]} | return {'phase': skyfield_to_moon_phase(moon_phase[-1])} | ||||
@staticmethod | @staticmethod | ||||
def get_asters_ephemerides_for_aster(aster, date: datetime.date, position: Position) -> Object: | def get_asters_ephemerides_for_aster(aster, date: datetime.date, position: Position) -> Object: | ||||