satkit 0.2.5__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. {satkit-0.2.5 → satkit-0.2.6}/Cargo.toml +1 -1
  2. {satkit-0.2.5/python/satkit.egg-info → satkit-0.2.6}/PKG-INFO +1 -1
  3. {satkit-0.2.5 → satkit-0.2.6}/pyproject.toml +8 -8
  4. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/__init__.pyi +2 -2
  5. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/frametransform/__init__.pyi +91 -46
  6. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/utils/__init__.pyi +1 -1
  7. {satkit-0.2.5 → satkit-0.2.6/python/satkit.egg-info}/PKG-INFO +1 -1
  8. {satkit-0.2.5 → satkit-0.2.6}/python/test/test.py +39 -1
  9. {satkit-0.2.5 → satkit-0.2.6}/src/consts.rs +16 -16
  10. {satkit-0.2.5 → satkit-0.2.6}/src/duration.rs +3 -1
  11. {satkit-0.2.5 → satkit-0.2.6}/src/frametransform/mod.rs +1 -0
  12. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/mod_utils.rs +23 -4
  13. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pyastrotime.rs +32 -14
  14. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pyconsts.rs +1 -1
  15. satkit-0.2.6/src/pybindings/pyduration.rs +237 -0
  16. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pyframetransform.rs +50 -18
  17. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pyutils.rs +2 -0
  18. {satkit-0.2.5 → satkit-0.2.6}/src/utils/datadir.rs +2 -2
  19. {satkit-0.2.5 → satkit-0.2.6}/src/utils/mod.rs +7 -0
  20. satkit-0.2.5/src/pybindings/pyduration.rs +0 -97
  21. {satkit-0.2.5 → satkit-0.2.6}/LICENSE +0 -0
  22. {satkit-0.2.5 → satkit-0.2.6}/MANIFEST.in +0 -0
  23. {satkit-0.2.5 → satkit-0.2.6}/README.md +0 -0
  24. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/__init__.py +0 -0
  25. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/astro-data/py.typed +0 -0
  26. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/density/__init__.pyi +0 -0
  27. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/density/py.typed +0 -0
  28. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/frametransform/py.typed +0 -0
  29. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/jplephem/__init__.pyi +0 -0
  30. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/jplephem/py.typed +0 -0
  31. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/moon/__init__.py +0 -0
  32. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/moon/py.typed +0 -0
  33. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/py.typed +0 -0
  34. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/satprop/__init__.pyi +0 -0
  35. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/satprop/py.typed +0 -0
  36. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/sun/__init__.pyi +0 -0
  37. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/sun/py.typed +0 -0
  38. {satkit-0.2.5 → satkit-0.2.6}/python/satkit/utils/py.typed +0 -0
  39. {satkit-0.2.5 → satkit-0.2.6}/python/satkit.egg-info/SOURCES.txt +0 -0
  40. {satkit-0.2.5 → satkit-0.2.6}/python/satkit.egg-info/dependency_links.txt +0 -0
  41. {satkit-0.2.5 → satkit-0.2.6}/python/satkit.egg-info/requires.txt +0 -0
  42. {satkit-0.2.5 → satkit-0.2.6}/python/satkit.egg-info/top_level.txt +0 -0
  43. {satkit-0.2.5 → satkit-0.2.6}/python/test/download_data.py +0 -0
  44. {satkit-0.2.5 → satkit-0.2.6}/python/test/download_from_json.py +0 -0
  45. {satkit-0.2.5 → satkit-0.2.6}/python/test/download_testvecs.py +0 -0
  46. {satkit-0.2.5 → satkit-0.2.6}/python/test/orbitprop_gps_fit.py +0 -0
  47. {satkit-0.2.5 → satkit-0.2.6}/python/test/sp3file.py +0 -0
  48. {satkit-0.2.5 → satkit-0.2.6}/setup.cfg +0 -0
  49. {satkit-0.2.5 → satkit-0.2.6}/src/astrotime.rs +0 -0
  50. {satkit-0.2.5 → satkit-0.2.6}/src/earth_orientation_params.rs +0 -0
  51. {satkit-0.2.5 → satkit-0.2.6}/src/earthgravity.rs +0 -0
  52. {satkit-0.2.5 → satkit-0.2.6}/src/frametransform/ierstable.rs +0 -0
  53. {satkit-0.2.5 → satkit-0.2.6}/src/frametransform/qcirs2gcrs.rs +0 -0
  54. {satkit-0.2.5 → satkit-0.2.6}/src/itrfcoord.rs +0 -0
  55. {satkit-0.2.5 → satkit-0.2.6}/src/jplephem.rs +0 -0
  56. {satkit-0.2.5 → satkit-0.2.6}/src/lib.rs +0 -0
  57. {satkit-0.2.5 → satkit-0.2.6}/src/lpephem/mod.rs +0 -0
  58. {satkit-0.2.5 → satkit-0.2.6}/src/lpephem/moon.rs +0 -0
  59. {satkit-0.2.5 → satkit-0.2.6}/src/lpephem/sun.rs +0 -0
  60. {satkit-0.2.5 → satkit-0.2.6}/src/nrlmsise.rs +0 -0
  61. {satkit-0.2.5 → satkit-0.2.6}/src/ode/harmonic_oscillator.rs +0 -0
  62. {satkit-0.2.5 → satkit-0.2.6}/src/ode/mod.rs +0 -0
  63. {satkit-0.2.5 → satkit-0.2.6}/src/ode/nalgebra.rs +0 -0
  64. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rk_adaptive.rs +0 -0
  65. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rk_adaptive_settings.rs +0 -0
  66. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rk_explicit.rs +0 -0
  67. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkf45.rs +0 -0
  68. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkts54.rs +0 -0
  69. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv65.rs +0 -0
  70. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv65_table.rs +0 -0
  71. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv87.rs +0 -0
  72. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv87_table.rs +0 -0
  73. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv98.rs +0 -0
  74. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv98_nointerp.rs +0 -0
  75. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv98_nointerp_table.rs +0 -0
  76. {satkit-0.2.5 → satkit-0.2.6}/src/ode/rkv98_table.rs +0 -0
  77. {satkit-0.2.5 → satkit-0.2.6}/src/ode/types.rs +0 -0
  78. {satkit-0.2.5 → satkit-0.2.6}/src/orbitprop/drag.rs +0 -0
  79. {satkit-0.2.5 → satkit-0.2.6}/src/orbitprop/mod.rs +0 -0
  80. {satkit-0.2.5 → satkit-0.2.6}/src/orbitprop/point_gravity.rs +0 -0
  81. {satkit-0.2.5 → satkit-0.2.6}/src/orbitprop/propagator.rs +0 -0
  82. {satkit-0.2.5 → satkit-0.2.6}/src/orbitprop/satproperties.rs +0 -0
  83. {satkit-0.2.5 → satkit-0.2.6}/src/orbitprop/satstate.rs +0 -0
  84. {satkit-0.2.5 → satkit-0.2.6}/src/orbitprop/settings.rs +0 -0
  85. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/mod.rs +0 -0
  86. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pydensity.rs +0 -0
  87. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pygravity.rs +0 -0
  88. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pyitrfcoord.rs +0 -0
  89. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pyjplephem.rs +0 -0
  90. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pylpephem_moon.rs +0 -0
  91. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pylpephem_sun.rs +0 -0
  92. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pynrlmsise.rs +0 -0
  93. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pypropagate.rs +0 -0
  94. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pypropsettings.rs +0 -0
  95. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pyquaternion.rs +0 -0
  96. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pysatproperties.rs +0 -0
  97. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pysatstate.rs +0 -0
  98. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pysgp4.rs +0 -0
  99. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pysolarsystem.rs +0 -0
  100. {satkit-0.2.5 → satkit-0.2.6}/src/pybindings/pytle.rs +0 -0
  101. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/dpper.rs +0 -0
  102. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/dscom.rs +0 -0
  103. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/dsinit.rs +0 -0
  104. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/dspace.rs +0 -0
  105. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/getgravconst.rs +0 -0
  106. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/initl.rs +0 -0
  107. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/mod.rs +0 -0
  108. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/satrec.rs +0 -0
  109. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/sgp4.rs +0 -0
  110. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/sgp4_lowlevel.rs +0 -0
  111. {satkit-0.2.5 → satkit-0.2.6}/src/sgp4/sgp4init.rs +0 -0
  112. {satkit-0.2.5 → satkit-0.2.6}/src/solarsystem.rs +0 -0
  113. {satkit-0.2.5 → satkit-0.2.6}/src/spaceweather.rs +0 -0
  114. {satkit-0.2.5 → satkit-0.2.6}/src/tle.rs +0 -0
  115. {satkit-0.2.5 → satkit-0.2.6}/src/types.rs +0 -0
  116. {satkit-0.2.5 → satkit-0.2.6}/src/utils/download.rs +0 -0
  117. {satkit-0.2.5 → satkit-0.2.6}/src/utils/skerror.rs +0 -0
  118. {satkit-0.2.5 → satkit-0.2.6}/src/utils/test.rs +0 -0
  119. {satkit-0.2.5 → satkit-0.2.6}/src/utils/update_data.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "satkit"
3
- version = "0.2.5"
3
+ version = "0.2.6"
4
4
  edition = "2021"
5
5
  description = "Satellite Toolkit"
6
6
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: satkit
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Satellite Orbital Dynamics Toolkit
5
5
  Author-email: Steven Michael <ssmichael@gmail.com>
6
6
  Maintainer-email: Steven Michael <ssmichael@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "satkit"
7
- version = "0.2.5"
7
+ version = "0.2.6"
8
8
  dependencies = ["numpy>=1.20.0"]
9
9
  requires-python = ">= 3.8"
10
10
  authors = [{ name = "Steven Michael", email = "ssmichael@gmail.com" }]
@@ -43,6 +43,9 @@ find = { where = ["python"] }
43
43
 
44
44
  [tool.cibuildwheel]
45
45
  build = ["cp312-*", "cp311-* cp310-* cp39-* cp38-*"]
46
+ test-skip = "*-macosx_arm64 *-macosx_universal2:arm64"
47
+ skip = ["pp*", "*_i686", "*_s390x", "*_aarch64", "*_ppc64le", "*-musllinux*"]
48
+
46
49
 
47
50
  [tool.cibuildwheel.macos]
48
51
  archs = ["x86_64", "arm64"]
@@ -54,17 +57,15 @@ before-build = [
54
57
  ]
55
58
  environment = { PATH = "$PATH:$HOME/.cargo/bin" }
56
59
  # Skip trying to test arm64 builds on Intel Macs
57
- test-skip = "*-macosx_arm64 *-macosx_universal2:arm64"
58
60
  test-requires = "pytest"
59
61
  test-command = [
60
- "ASTRO_DATA={package}/astro-data SATKIT_TESTVEC_ROOT={package}/satkit-testvecs pytest {project}/python/test/test.py",
62
+ "SATKIT_DATA={package}/astro-data SATKIT_TESTVEC_ROOT={package}/satkit-testvecs pytest {project}/python/test/test.py",
61
63
  ]
62
64
 
63
65
 
64
66
  [tool.cibuildwheel.linux]
65
67
  environment = { PATH = "$PATH:$HOME/.cargo/bin" }
66
68
  archs = ["x86_64"]
67
- skip = ["pp*", "*_i686", "*_s390x", "*_aarch64", "*_ppc64le", "*-musllinux*"]
68
69
  before-build = [
69
70
  "pip install -U setuptools-rust",
70
71
  "curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain=stable --profile=minimal -y",
@@ -72,7 +73,7 @@ before-build = [
72
73
  ]
73
74
  test-requires = "pytest"
74
75
  test-command = [
75
- "ASTRO_DATA={package}/astro-data SATKIT_TESTVEC_ROOT={package}/satkit-testvecs pytest {project}/python/test/test.py",
76
+ "SATKIT_DATA={package}/astro-data SATKIT_TESTVEC_ROOT={package}/satkit-testvecs pytest {project}/python/test/test.py",
76
77
  ]
77
78
 
78
79
  [tool.cibuildwheel.windows]
@@ -85,14 +86,13 @@ before-build = [
85
86
  "rustup show",
86
87
  ]
87
88
  archs = ["AMD64"]
88
- skip = ["pp*"]
89
89
  test-requires = "pytest"
90
90
  before-test = [
91
- "set ASTRO_DATA={package}\\astro-data",
91
+ "set SATKIT_DATA={package}\\astro-data",
92
92
  "set SATKIT_TESTVEC_ROOT={package}\\satkit-testvecs",
93
93
  ]
94
94
  test-command = [
95
- "set ASTRO_DATA={package}\\astro-data&&set SATKIT_TESTVEC_ROOT={package}\\satkit-testvecs&&pytest {project}\\python\\test\\test.py",
95
+ "set SATKIT_DATA={package}\\astro-data&&set SATKIT_TESTVEC_ROOT={package}\\satkit-testvecs&&pytest {project}\\python\\test\\test.py",
96
96
  ]
97
97
 
98
98
 
@@ -537,8 +537,8 @@ class timescale:
537
537
  are needed to compute precise rotations between various inertial and
538
538
  Earth-fixed coordinate frames
539
539
 
540
- For details, see:
541
- https://stjarnhimlen.se/comp/time.html
540
+ For an excellent overview, see:
541
+ https://spsweb.fltops.jpl.nasa.gov/portaldataops/mpg/MPG_Docs/MPG%20Book/Release/Chapter2-TimeScales.pdf
542
542
 
543
543
  # Options:
544
544
 
@@ -19,80 +19,125 @@ import satkit
19
19
  import datetime
20
20
 
21
21
  def gmst(
22
- tm: satkit.time | npt.ArrayLike[satkit.time],
22
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
23
23
  ) -> float | npt.ArrayLike[np.float]:
24
24
  """
25
25
  Greenwich Mean Sidereal Time
26
-
26
+
27
27
  Vallado algorithm 15:
28
-
29
- GMST = 67310.5481 + (876600h + 8640184.812866) * tᵤₜ₁ * (0.983104 + tᵤₜ₁ * -6.2e-6)
30
-
31
- Input is satkit.time object or list or numpy array of satkit.time objects.
32
-
33
- Output is float or numpy array of floats with GMST in radians matched element-wise
34
- to the input times.
28
+
29
+ GMST = 67310.5481 + (876600h + 8640184.812866) * tᵤₜ₁ * (0.983104 + tᵤₜ₁ * −6.2e−6)
30
+
31
+
32
+ # Arguments
33
+
34
+ * `tm`: scalar, list, or numpy array of astro.time or datetime.datetime
35
+ representing time at which to calculate output
36
+
37
+ # Returns
38
+
39
+ * Greenwich Mean Sideral Time, radians, at intput time(s)
40
+
35
41
  """
36
42
 
37
43
  def gast(
38
- tm: satkit.time | npt.ArrayLike[satkit.time],
44
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
39
45
  ) -> float | npt.ArrayLike[np.float]:
40
46
  """
41
- Greenwich Apparent Sidereal Time
42
-
43
- Input is satkit.time object or list or numpy array of satkit.time objects.
44
-
45
- Output is float or numpy array of floats with GAST in radians matched element-wise
46
- to the input times.
47
+ Greenwich apparant sidereal time, radians
48
+
49
+ # Arguments:
50
+
51
+ * `tm`: scalar, list, or numpy array of astro.time or datetime.datetime
52
+ representing time at which to calculate output
53
+
54
+ # Returns:
55
+
56
+ * Greenwich apparant sidereal time, radians, at input time(s)
57
+
47
58
  """
48
59
 
49
60
  def earth_rotation_angle(
50
- tm: satkit.time | npt.ArrayLike[satkit.time],
61
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
51
62
  ) -> float | npt.ArrayLike[np.float]:
52
63
  """
53
- Earth rotation angle
54
-
55
- See:
56
- https://www.iers.org/SharedDocs/Publikationen/EN/IERS/Publications/tn/TechnNote36/tn36_043.pdf?__blob=publicationFile&v=1
57
-
64
+ Earth Rotation Angle
65
+
66
+ See
67
+ [IERS Technical Note 36, Chapter 5](https://www.iers.org/SharedDocs/Publikationen/EN/IERS/Publications/tn/TechnNote36/tn36_043.pdf?__blob=publicationFile&v=1)
58
68
  Equation 5.15
59
-
60
- Input is satkit.time object or list or numpy array of satkit.time objects.
61
-
62
- Output is float or numpy array of floats with Earth Rotation Angle in radians
63
- matched element-wise to the input times.
69
+
70
+ # Arguments:
71
+
72
+ * `tm`: scalar, list, or numpy array of astro.time or datetime.datetime
73
+ representing time at which to calculate output
74
+
75
+ # Returns:
76
+
77
+ * Earth rotation angle, in radians, at input time(s)
78
+
79
+ # Calculation Details
80
+
81
+ * Let t be UT1 Julian date
82
+ * let f be fractional component of t (fraction of day)
83
+ * ERA = 2𝜋 ((0.7790572732640 + f + 0.00273781191135448 * (t − 2451545.0))
84
+
64
85
  """
65
86
 
66
87
  def qitrf2tirs(
67
- tm: satkit.time | npt.ArrayLike[satkit.time],
88
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
68
89
  ) -> satkit.quaternion | npt.ArrayLike[satkit.quaternion]:
69
90
  """
70
- Rotation from International Terrestrial Reference Frame
71
- (ITRF) to the Terrestrial Intermediate Reference System (TIRS)
72
- represented as satkit.quaterinion object
73
-
74
- Input is satkit.time object or list or numpy array of satkit.time objects.
75
-
76
- Output is satkit.quaternion or numpy array of satkit.quaternion representiong
77
- rotations from itrf to tirs matched element-wise to the input times
91
+ Rotation from Terrestrial Intermediate Reference System to
92
+ Celestial Intermediate Reference Systems
93
+
94
+ # Arguments:
95
+
96
+ * `tm`: scalar, list, or numpy array of astro.time or datetime.datetime
97
+ representing time at which to calculate output
98
+
99
+ # Returns:
100
+
101
+ * Quaternion representing rotation from TIRS to CIRS at input time(s)
102
+
78
103
  """
79
104
 
80
105
  @typing.overload
81
- def qcirs2gcrf(tm: satkit.time) -> satkit.quaternion:
82
- """
83
- Rotate from Celestial Intermediate Reference System
106
+ def qcirs2gcrf(tm: satkit.time | datetime.datetime) -> satkit.quaternion:
107
+ """
108
+ Rotation from Celestial Intermediate Reference System
84
109
  to Geocentric Celestial Reference Frame
110
+
111
+ # Arguments:
112
+
113
+ * `tm`: scalar, list, or numpy array of astro.time or datetime.datetime
114
+ representing time at which to calculate output
115
+
116
+ # Returns:
117
+
118
+ * Quaternion representing rotation from CIRS to GCRF at input time(s)
119
+
85
120
  """
86
121
 
87
122
  @typing.overload
88
- def qcirs2gcrf(tm: npt.ArrayLike[satkit.time]) -> npt.ArrayLike[satkit.quaternion]:
123
+ def qcirs2gcrf(tm: npt.ArrayLike[satkit.time] | npt.ArrayLike[datetime.datetime]) -> npt.ArrayLike[satkit.quaternion]:
89
124
  """
90
- Rotate from Celestial Intermediate Reference System
125
+ Rotation from Celestial Intermediate Reference System
91
126
  to Geocentric Celestial Reference Frame
127
+
128
+ # Arguments:
129
+
130
+ * `tm`: scalar, list, or numpy array of astro.time or datetime.datetime
131
+ representing time at which to calculate output
132
+
133
+ # Returns:
134
+
135
+ * Quaternion representing rotation from CIRS to GCRF at input time(s)
136
+
92
137
  """
93
138
 
94
139
  def qtirs2cirs(
95
- tm: satkit.time | npt.ArrayLike[satkit.time],
140
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
96
141
  ) -> satkit.quaternion | npt.ArrayLike[satkit.quaternion]:
97
142
  """
98
143
  Rotation from Terrestrial Intermediate Reference System (TIRS)
@@ -106,7 +151,7 @@ def qtirs2cirs(
106
151
  """
107
152
 
108
153
  def qgcrf2itrf_approx(
109
- tm: satkit.time | npt.ArrayLike[satkit.time],
154
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
110
155
  ) -> satkit.quaternion | npt.ArrayLike[satkit.quaternion]:
111
156
  """
112
157
  Quaternion representing approximate rotation from the
@@ -128,7 +173,7 @@ def qgcrf2itrf_approx(
128
173
  """
129
174
 
130
175
  def qitrf2gcrf_approx(
131
- tm: satkit.time | npt.ArrayLike[satkit.time],
176
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
132
177
  ) -> satkit.quaternion | npt.ArrayLike[satkit.quaternion]:
133
178
  """
134
179
  Quaternion representing approximate rotation from the
@@ -175,7 +220,7 @@ def qgcrf2itrf(
175
220
  """
176
221
 
177
222
  def qitrf2gcrf(
178
- tm: satkit.time | npt.ArrayLike[satkit.time],
223
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
179
224
  ) -> satkit.quaternion | npt.ArrayLike[satkit.quaternion]:
180
225
  """
181
226
  Quaternion representing rotation from the
@@ -200,7 +245,7 @@ def qitrf2gcrf(
200
245
  """
201
246
 
202
247
  def qteme2itrf(
203
- tm: satkit.time | npt.ArrayLike[satkit.time],
248
+ tm: satkit.time | npt.ArrayLike[satkit.time] | datetime.datetime | npt.ArrayLike[datetime.datetime],
204
249
  ) -> satkit.quaternion | npt.ArrayLike[satkit.quaternion]:
205
250
  """
206
251
  Quaternion representing rotation from the
@@ -52,7 +52,7 @@ def datadir() -> str:
52
52
 
53
53
  MacOS:
54
54
 
55
- 1. Directory pointed to by "ASTRO_DATA" environment variable
55
+ 1. Directory pointed to by "SATKIT_DATA" environment variable
56
56
  2. $HOME/LIBRARY/Application\ Support/astro-data
57
57
  3. $HOME/.astro-data
58
58
  4. $HOME
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: satkit
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Satellite Orbital Dynamics Toolkit
5
5
  Author-email: Steven Michael <ssmichael@gmail.com>
6
6
  Maintainer-email: Steven Michael <ssmichael@gmail.com>
@@ -5,12 +5,50 @@ import numpy as np
5
5
  import math as m
6
6
  import os
7
7
  from sp3file import read_sp3file
8
-
8
+ from datetime import datetime, timezone
9
9
 
10
10
  testvec_dir = os.getenv(
11
11
  "SATKIT_TESTVEC_ROOT", default="." + os.path.sep + "satkit-testvecs" + os.path.sep
12
12
  )
13
13
 
14
+ class TestDateTime:
15
+ """
16
+ Check that function calls with satkit.time and datetime.datetime return
17
+ the same result
18
+ """
19
+ def test_scalar_times(self):
20
+
21
+ # Create times and show that they are equal
22
+ tm1 = sk.time(2023, 3, 4, 12, 5, 6)
23
+ tm2 = datetime(2023, 3, 4, 12, 5, 6, tzinfo=timezone.utc)
24
+
25
+
26
+ assert(tm1.datetime() == tm2)
27
+ # Check that function calls work
28
+ # Pick gmst as the test function call for time
29
+ # it can be anything since under the hood the same function call is used
30
+ # to get time inputs for all python functions in package
31
+ g1 = sk.frametransform.gmst(tm1)
32
+ g2 = sk.frametransform.gmst(tm2)
33
+ assert g1 == pytest.approx(g2, rel=1e-10)
34
+
35
+ def test_list_times(self):
36
+ timearr = range(10)
37
+ tm1 = [sk.time(2023, 3, x+1, 12, 0, 0) for x in timearr]
38
+ tm2 = [datetime(2023, 3, x+1, 12, 0, 0, tzinfo=timezone.utc) for x in timearr]
39
+ g1 = sk.frametransform.gmst(tm1)
40
+ g2 = sk.frametransform.gmst(tm2)
41
+ assert g1 == pytest.approx(g2)
42
+
43
+ def test_numpy_times(self):
44
+ timearr = range(10)
45
+ tm1 = np.array([sk.time(2023, 3, x+1, 12, 0, 0) for x in timearr])
46
+ tm2 = np.array([datetime(2023, 3, x+1, 12, 0, 0, tzinfo=timezone.utc) for x in timearr])
47
+ g1 = sk.frametransform.gmst(tm1)
48
+ g2 = sk.frametransform.gmst(tm2)
49
+ assert g1 == pytest.approx(g2)
50
+
51
+
14
52
  class TestTime:
15
53
  def test_mjd(self):
16
54
  """
@@ -1,36 +1,36 @@
1
1
  #[allow(non_upper_case_globals)]
2
- /// WGS-84 semiparameter, in meters */
2
+ /// WGS-84 semiparameter, in meters
3
3
  pub const WGS84_A: f64 = 6378137.0;
4
- /// WGS-84 flattening */
4
+ /// WGS-84 flattening
5
5
  pub const WGS84_F: f64 = 0.003352810664747;
6
6
  /// WGS-84 Earth radius, meters
7
7
  pub const EARTH_RADIUS: f64 = WGS84_A;
8
- /// Gravitational parameter of Earth, m^3/s^2 */
8
+ /// Gravitational parameter of Earth, m^3/s^2
9
9
  pub const MU_EARTH: f64 = 3.986004418E14;
10
- /// Gravitational parameter of Moon, m^3/s^2 */
10
+ /// Gravitational parameter of Moon, m^3/s^2
11
11
  pub const MU_MOON: f64 = 4.9048695E12;
12
- /// Gravitational parameter of Sun, m^3/s^2 */
12
+ /// Gravitational parameter of Sun, m^3/s^2
13
13
  pub const MU_SUN: f64 = 1.32712440018E20;
14
- /// Alternate name for gravitational parameter */
14
+ /// Alternate name for gravitational parameter
15
15
  pub const GM: f64 = MU_EARTH;
16
- /// Earth rotation rate, radians / second */
16
+ /// Earth rotation rate, radians / second
17
17
  pub const OMEGA_EARTH: f64 = 7.292115090E-5;
18
- /// speed of light, m/s */
18
+ /// speed of light, m/s
19
19
  pub const C: f64 = 299792458.0;
20
- /// Astronomical unit, meters */
20
+ /// Astronomical unit, meters
21
21
  pub const AU: f64 = 1.4959787069999998807907104492E11;
22
- /// Sun radius in meters */
22
+ /// Sun radius in meters
23
23
  pub const SUN_RADIUS: f64 = 695500000.0;
24
- /// Moon radius, meters */
24
+ /// Moon radius, meters
25
25
  pub const MOON_RADIUS: f64 = 1737400.0;
26
- /// Ratio of earth mass to moon mass */
26
+ /// Ratio of earth mass to moon mass
27
27
  pub const EARTH_MOON_MASS_RATIO: f64 = 81.30056822149721540427;
28
- /// Geosynchronous Distance */
28
+ /// Geosynchronous Distance
29
29
  pub const GEO_R: f64 = 42164172.58422766;
30
- /// JGM3 Gravitational parameter of Earth, m^3/s^2 */
30
+ /// JGM3 Gravitational parameter of Earth, m^3/s^2
31
31
  pub const JGM3_MU: f64 = 0.3986004415E+15;
32
- /// JGM3 Semimajor axis of Earth, m */
32
+ /// JGM3 Semimajor axis of Earth, m
33
33
  pub const JGM3_A: f64 = 0.6378136300E+07;
34
- /// JGM3 J2 term */
34
+ /// JGM3 J2 term
35
35
  pub const JGM3_J2: f64 = -0.0010826360229829945;
36
36
  //jgm3_J2:f64 = -sqrt(5.) * -0.484169548456e-03;
@@ -77,7 +77,9 @@ impl Duration {
77
77
  // e.g. if seconds = 59.999..., rather than round up and
78
78
  // display "seconds" in second field, show 0 and increment
79
79
  // minutes...
80
- secs = secs + 5.0e-4;
80
+ if secs % 60.0 > 59.9995 {
81
+ secs = secs + 5.0e-4;
82
+ }
81
83
 
82
84
  if secs < 1.0 {
83
85
  format!("Duration: {}{:.3} microseconds", sign, (secs % 1.0) * 1.0e6)
@@ -59,6 +59,7 @@ pub fn gmst(tm: &AstroTime) -> f64 {
59
59
  }
60
60
 
61
61
  /// Equation of Equinoxes
62
+ /// Equation of the equinoxes
62
63
  pub fn eqeq(tm: &AstroTime) -> f64 {
63
64
  let d: f64 = tm.to_mjd(Scale::TT) - 51544.5;
64
65
  let omega = PI / 180.0 * (125.04 - 0.052954 * d);
@@ -54,11 +54,22 @@ fn update_datafiles(kwds: Option<&PyDict>) -> PyResult<()> {
54
54
  }
55
55
  }
56
56
 
57
- /// Return directory currently used to hold
58
- /// necessary data files for the directory
57
+ /// Get directory where astronomy data is stored
59
58
  ///
60
- /// e.g., Earth Orientation Parameters, gravity coefficients,
61
- /// JPL Ephemeris, etc..
59
+ /// Tries the following paths in order, and stops when the
60
+ /// files are found
61
+ ///
62
+ /// * "SATKIT_DATA" environment variable
63
+ /// * ${HOME}/astro-data
64
+ /// * ${HOME}
65
+ /// * /usr/share/astro-data
66
+ /// * On Mac Only:
67
+ /// * /Library/Application Support/astro-data
68
+ /// * ${Home}/Library/Application Support/astro-data
69
+ ///
70
+ /// Returns:
71
+ ///
72
+ /// * string representing directory where files are stored
62
73
  ///
63
74
  #[pyfunction]
64
75
  fn datadir() -> PyResult<PyObject> {
@@ -76,6 +87,13 @@ fn githash() -> PyResult<String> {
76
87
  Ok(String::from(crate::utils::githash()))
77
88
  }
78
89
 
90
+ // Version of satkit
91
+ #[pyfunction]
92
+ fn version() -> PyResult<String> {
93
+ Ok(String::from(crate::utils::gittag()))
94
+ }
95
+
96
+
79
97
  #[pyfunction]
80
98
  fn dylib_path() -> PyResult<PyObject> {
81
99
  pyo3::Python::with_gil(|py| -> PyResult<PyObject> {
@@ -100,6 +118,7 @@ pub fn utils(_py: Python, m: &PyModule) -> PyResult<()> {
100
118
  m.add_function(wrap_pyfunction!(update_datafiles, m)?)
101
119
  .unwrap();
102
120
  m.add_function(wrap_pyfunction!(githash, m)?).unwrap();
121
+ m.add_function(wrap_pyfunction!(version, m)?).unwrap();
103
122
  m.add_function(wrap_pyfunction!(build_date, m)?).unwrap();
104
123
  Ok(())
105
124
  }
@@ -2,7 +2,6 @@ use pyo3::prelude::*;
2
2
  use pyo3::types::timezone_utc;
3
3
  use pyo3::types::PyDateTime;
4
4
  use pyo3::types::PyTuple;
5
- use pyo3::types::PyTzInfo;
6
5
 
7
6
  use crate::astrotime::{self, AstroTime, Scale};
8
7
 
@@ -17,8 +16,8 @@ use numpy as np;
17
16
  /// are needed to compute precise rotations between various inertial and
18
17
  /// Earth-fixed coordinate frames
19
18
  ///
20
- /// For details, see:
21
- /// https://stjarnhimlen.se/comp/time.html
19
+ /// For an excellent overview, see:
20
+ /// https://spsweb.fltops.jpl.nasa.gov/portaldataops/mpg/MPG_Docs/MPG%20Book/Release/Chapter2-TimeScales.pdf
22
21
  ///
23
22
  /// UTC = Universal Time Coordinate
24
23
  /// TT = Terrestrial Time
@@ -327,10 +326,10 @@ impl PyAstroTime {
327
326
  fn datetime(&self, utc: bool) -> PyResult<PyObject> {
328
327
  pyo3::Python::with_gil(|py| -> PyResult<PyObject> {
329
328
  let timestamp: f64 = self.to_unixtime();
330
- let mut tz: Option<&PyTzInfo> = Some(timezone_utc(py));
331
- if utc == false {
332
- tz = None;
333
- }
329
+ let tz = match utc {
330
+ false => None,
331
+ true => Some(timezone_utc(py)),
332
+ };
334
333
  Ok(PyDateTime::from_timestamp(py, timestamp, tz)?.into_py(py))
335
334
  })
336
335
  }
@@ -636,13 +635,27 @@ impl ToTimeVec for &PyAny {
636
635
  let tm: PyAstroTime = self.extract().unwrap();
637
636
  Ok(vec![tm.inner.clone()])
638
637
  }
638
+ else if self.is_instance_of::<PyDateTime>() {
639
+ let dt: &PyDateTime = self.extract().unwrap();
640
+ Ok(vec![PyAstroTime::from_datetime(dt).unwrap().inner])
641
+ }
639
642
  // List case
640
643
  else if self.is_instance_of::<pyo3::types::PyList>() {
641
644
  match self.extract::<Vec<PyAstroTime>>() {
642
645
  Ok(v) => Ok(v.iter().map(|x| x.inner).collect::<Vec<_>>()),
643
- Err(e) => Err(pyo3::exceptions::PyRuntimeError::new_err(format!(
644
- "Not a list of astro::AstroTime: {e}"
645
- ))),
646
+ Err(e) => {
647
+ match self.extract::<Vec<&PyDateTime>>() {
648
+ Ok(v) => Ok(v.iter().map(|x|
649
+ PyAstroTime::from_datetime(x.extract().unwrap()).unwrap().inner)
650
+ .collect::<Vec<_>>()),
651
+ Err(e) => {
652
+ Err(pyo3::exceptions::PyTypeError::new_err(format!(
653
+ "Not a list of satkit.time or datetime.datetime: {e}"
654
+ )))
655
+ }
656
+ }
657
+ }
658
+
646
659
  }
647
660
  }
648
661
  // numpy array case
@@ -656,13 +669,18 @@ impl ToTimeVec for &PyAny {
656
669
  .map(|p| -> Result<AstroTime, _> {
657
670
  match p.extract::<PyAstroTime>(py) {
658
671
  Ok(v2) => Ok(v2.inner),
659
- Err(v2) => Err(v2),
672
+ Err(_) => match p.extract::<&PyDateTime>(py) {
673
+ Ok(v3) => Ok(PyAstroTime::from_datetime(v3.extract().unwrap()).unwrap().inner),
674
+ Err(_) => Err(pyo3::exceptions::PyTypeError::new_err(format!(
675
+ "Input numpy array must contain satkit.time elements or datetime.datetime elements"
676
+ ))),
660
677
  }
678
+ }
661
679
  })
662
680
  .collect();
663
681
  if !tmarray.is_ok() {
664
682
  Err(pyo3::exceptions::PyRuntimeError::new_err(
665
- "Invalid AstroTime input",
683
+ "Invalid satkit.time input",
666
684
  ))
667
685
  } else {
668
686
  Ok(tmarray.unwrap())
@@ -670,12 +688,12 @@ impl ToTimeVec for &PyAny {
670
688
  }),
671
689
 
672
690
  Err(e) => Err(pyo3::exceptions::PyRuntimeError::new_err(format!(
673
- "Invalid AstroTime input: {e}"
691
+ "Invalid satkit.time or datetime.datetime input: {e}"
674
692
  ))),
675
693
  }
676
694
  } else {
677
695
  Err(pyo3::exceptions::PyRuntimeError::new_err(
678
- "Invalid AstroTime input",
696
+ "Invalid satkit.time or datetime.datetime input",
679
697
  ))
680
698
  }
681
699
  }
@@ -18,7 +18,7 @@ impl Consts {
18
18
  /// WGS-84 Earth radius, meters
19
19
  const earth_radius: f64 = cconsts::EARTH_RADIUS;
20
20
 
21
- /// Gravitational parameter of Earth, m^3/s^2 */
21
+ /// Gravitational parameter of Earth, m^3/s^2
22
22
  #[classattr]
23
23
  const mu_earth: f64 = cconsts::MU_EARTH;
24
24
  /// Gravitational parameter of moon, m^3/s^2