A library that computes the ephemerides.
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.
 
 

118 lines
3.4 KiB

  1. #!/usr/bin/env python3
  2. # Kosmorro - Compute The Next Ephemerides
  3. # Copyright (C) 2019 Jérôme Deuchnord <jerome@deuchnord.fr>
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU Affero General Public License as
  7. # published by the Free Software Foundation, either version 3 of the
  8. # License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU Affero General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Affero General Public License
  16. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. import os
  18. import re
  19. from shutil import rmtree
  20. from pathlib import Path
  21. from datetime import date
  22. from dateutil.relativedelta import relativedelta
  23. from skyfield.api import Loader
  24. from skyfield.timelib import Time
  25. from skyfield.nutationlib import iau2000b
  26. CACHE_FOLDER = str(Path.home()) + '/.kosmorro-cache'
  27. class Environment:
  28. def __init__(self):
  29. self._vars = {}
  30. def __set__(self, key, value):
  31. self._vars[key] = value
  32. def __getattr__(self, key):
  33. return self._vars[key] if key in self._vars else None
  34. def __str__(self):
  35. return self._vars.__str__()
  36. def __len__(self):
  37. return len(self._vars)
  38. def get_env() -> Environment:
  39. environment = Environment()
  40. for var in os.environ:
  41. if not re.search('^KOSMORRO_', var):
  42. continue
  43. [_, env] = var.split('_', 1)
  44. environment.__set__(env.lower(), os.getenv(var))
  45. return environment
  46. def get_loader():
  47. return Loader(CACHE_FOLDER)
  48. def get_timescale():
  49. return get_loader().timescale()
  50. def get_skf_objects():
  51. return get_loader()('de421.bsp')
  52. def get_iau2000b(time: Time):
  53. return iau2000b(time.tt)
  54. def clear_cache():
  55. rmtree(CACHE_FOLDER)
  56. def flatten_list(the_list: list):
  57. new_list = []
  58. for item in the_list:
  59. if isinstance(item, list):
  60. for item2 in flatten_list(item):
  61. new_list.append(item2)
  62. continue
  63. new_list.append(item)
  64. return new_list
  65. def get_date(date_arg: str) -> date:
  66. if re.match(r'^\d{4}-\d{2}-\d{2}$', date_arg):
  67. try:
  68. return date.fromisoformat(date_arg)
  69. except ValueError as error:
  70. raise ValueError(_('The date {date} is not valid: {error}').format(date=date_arg,
  71. error=error.args[0])) from error
  72. elif re.match(r'^([+-])(([0-9]+)y)?[ ]?(([0-9]+)m)?[ ]?(([0-9]+)d)?$', date_arg):
  73. def get_offset(date_arg: str, signifier: str):
  74. if re.search(r'([0-9]+)' + signifier, date_arg):
  75. return abs(int(re.search(r'[+-]?([0-9]+)' + signifier, date_arg).group(0)[:-1]))
  76. return 0
  77. days = get_offset(date_arg, 'd')
  78. months = get_offset(date_arg, 'm')
  79. years = get_offset(date_arg, 'y')
  80. if date_arg[0] == '+':
  81. return date.today() + relativedelta(days=days, months=months, years=years)
  82. return date.today() - relativedelta(days=days, months=months, years=years)
  83. else:
  84. error_msg = 'The date {date} does not match the required YYYY-MM-DD format or the offset format.'
  85. raise ValueError(error_msg.format(date=date_arg))