astronoby 0.9.0 → 0.11.0

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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +235 -0
  4. data/README.md +19 -1
  5. data/UPGRADING.md +270 -0
  6. data/docs/README.md +105 -16
  7. data/docs/altitude_crossings.md +92 -0
  8. data/docs/angles.md +1 -0
  9. data/docs/configuration.md +28 -17
  10. data/docs/coordinates.md +72 -12
  11. data/docs/deep_sky_bodies.md +46 -1
  12. data/docs/ephem.md +5 -2
  13. data/docs/equinoxes_solstices_times.md +4 -3
  14. data/docs/glossary.md +99 -1
  15. data/docs/iers.md +40 -0
  16. data/docs/instant.md +33 -21
  17. data/docs/lunar_eclipses.md +208 -0
  18. data/docs/lunar_observation.md +87 -0
  19. data/docs/moon_phases.md +4 -1
  20. data/docs/observer.md +20 -6
  21. data/docs/planetary_phenomena.md +78 -0
  22. data/docs/reference_frames.md +192 -34
  23. data/docs/rise_transit_set_times.md +6 -4
  24. data/docs/solar_system_bodies.md +26 -4
  25. data/docs/twilight_times.md +43 -24
  26. data/lib/astronoby/angle.rb +63 -2
  27. data/lib/astronoby/angles/dms.rb +18 -1
  28. data/lib/astronoby/angles/hms.rb +14 -1
  29. data/lib/astronoby/angular_velocity.rb +21 -0
  30. data/lib/astronoby/bodies/deep_sky_object.rb +6 -1
  31. data/lib/astronoby/bodies/deep_sky_object_position.rb +35 -38
  32. data/lib/astronoby/bodies/earth.rb +7 -44
  33. data/lib/astronoby/bodies/jupiter.rb +10 -0
  34. data/lib/astronoby/bodies/mars.rb +10 -0
  35. data/lib/astronoby/bodies/mercury.rb +10 -0
  36. data/lib/astronoby/bodies/moon.rb +158 -32
  37. data/lib/astronoby/bodies/neptune.rb +10 -0
  38. data/lib/astronoby/bodies/saturn.rb +10 -0
  39. data/lib/astronoby/bodies/solar_system_body.rb +240 -61
  40. data/lib/astronoby/bodies/sun.rb +79 -4
  41. data/lib/astronoby/bodies/uranus.rb +10 -0
  42. data/lib/astronoby/bodies/venus.rb +10 -0
  43. data/lib/astronoby/body.rb +6 -0
  44. data/lib/astronoby/cache.rb +13 -0
  45. data/lib/astronoby/center.rb +84 -0
  46. data/lib/astronoby/constants.rb +1 -2
  47. data/lib/astronoby/constellation.rb +9 -1
  48. data/lib/astronoby/constellations/data.rb +1 -1
  49. data/lib/astronoby/coordinates/ecliptic.rb +10 -1
  50. data/lib/astronoby/coordinates/equatorial.rb +79 -13
  51. data/lib/astronoby/coordinates/geodetic.rb +102 -0
  52. data/lib/astronoby/coordinates/horizontal.rb +13 -1
  53. data/lib/astronoby/delta_t.rb +44 -0
  54. data/lib/astronoby/distance.rb +35 -0
  55. data/lib/astronoby/duration.rb +116 -0
  56. data/lib/astronoby/earth_rotation.rb +70 -0
  57. data/lib/astronoby/equinox_solstice.rb +31 -8
  58. data/lib/astronoby/errors.rb +11 -0
  59. data/lib/astronoby/events/altitude_crossing.rb +29 -0
  60. data/lib/astronoby/events/altitude_crossing_calculator.rb +511 -0
  61. data/lib/astronoby/events/altitude_extreme.rb +31 -0
  62. data/lib/astronoby/events/conjunction.rb +51 -0
  63. data/lib/astronoby/events/conjunction_opposition_calculator.rb +84 -0
  64. data/lib/astronoby/events/extremum_calculator.rb +23 -176
  65. data/lib/astronoby/events/greatest_elongation.rb +58 -0
  66. data/lib/astronoby/events/greatest_elongation_calculator.rb +56 -0
  67. data/lib/astronoby/events/lunar_eclipse.rb +111 -0
  68. data/lib/astronoby/events/lunar_eclipse_calculator.rb +397 -0
  69. data/lib/astronoby/events/lunar_eclipse_geometry.rb +115 -0
  70. data/lib/astronoby/events/lunar_eclipse_phase.rb +45 -0
  71. data/lib/astronoby/events/lunar_eclipse_visibility.rb +296 -0
  72. data/lib/astronoby/events/opposition.rb +19 -0
  73. data/lib/astronoby/events/rise_transit_set_calculator.rb +9 -13
  74. data/lib/astronoby/events/rise_transit_set_event.rb +12 -1
  75. data/lib/astronoby/events/rise_transit_set_events.rb +12 -1
  76. data/lib/astronoby/events/twilight_calculator.rb +37 -147
  77. data/lib/astronoby/events/twilight_event.rb +24 -6
  78. data/lib/astronoby/events/twilight_events.rb +26 -6
  79. data/lib/astronoby/extremum_finder.rb +148 -0
  80. data/lib/astronoby/horizon.rb +40 -0
  81. data/lib/astronoby/horizontal_transformation.rb +112 -0
  82. data/lib/astronoby/instant.rb +56 -16
  83. data/lib/astronoby/libration.rb +25 -0
  84. data/lib/astronoby/mean_obliquity.rb +8 -0
  85. data/lib/astronoby/moon_orientation_ephemeris.rb +69 -0
  86. data/lib/astronoby/moon_physical_ephemeris.rb +263 -0
  87. data/lib/astronoby/nutation.rb +10 -20
  88. data/lib/astronoby/observer.rb +67 -49
  89. data/lib/astronoby/orientation.rb +107 -0
  90. data/lib/astronoby/position.rb +16 -0
  91. data/lib/astronoby/precession.rb +62 -61
  92. data/lib/astronoby/reference_frame.rb +80 -9
  93. data/lib/astronoby/reference_frames/apparent.rb +43 -12
  94. data/lib/astronoby/reference_frames/astrometric.rb +14 -1
  95. data/lib/astronoby/reference_frames/geometric.rb +7 -1
  96. data/lib/astronoby/reference_frames/mean_of_date.rb +19 -1
  97. data/lib/astronoby/reference_frames/teme.rb +159 -0
  98. data/lib/astronoby/reference_frames/topocentric.rb +36 -4
  99. data/lib/astronoby/refraction.rb +26 -5
  100. data/lib/astronoby/root_finder.rb +90 -0
  101. data/lib/astronoby/rotation.rb +49 -0
  102. data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +19 -8
  103. data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +44 -5
  104. data/lib/astronoby/time/greenwich_sidereal_time.rb +21 -0
  105. data/lib/astronoby/time/local_apparent_sidereal_time.rb +21 -0
  106. data/lib/astronoby/time/local_mean_sidereal_time.rb +21 -0
  107. data/lib/astronoby/time/local_sidereal_time.rb +24 -0
  108. data/lib/astronoby/time/sidereal_time.rb +23 -1
  109. data/lib/astronoby/true_obliquity.rb +4 -0
  110. data/lib/astronoby/util/maths.rb +8 -0
  111. data/lib/astronoby/util/time.rb +0 -497
  112. data/lib/astronoby/vector.rb +10 -0
  113. data/lib/astronoby/velocity.rb +39 -0
  114. data/lib/astronoby/version.rb +1 -1
  115. data/lib/astronoby.rb +30 -0
  116. metadata +80 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: becadc2ba01e7620f12b20a5192e8537ed9f717336bb43471734fd5be9561675
4
- data.tar.gz: 47c5743867f09c58f49093645da7534def3836135883f44929d4da15f73a441a
3
+ metadata.gz: 1093c9a0d077cfa9c2a9fcf60e2af2a21ec4c1f74c268ef22dca8e93b5badadb
4
+ data.tar.gz: e12ccfad49e7a63821cde3b382e8584efdff3c0c06a42ffddf60119ad213b2f5
5
5
  SHA512:
6
- metadata.gz: 2b04c971a79ac8201e21398dc0cc02b920cdadde538a0eb7d5d59dbc260661cbda51f3a72a434695b596634848f361a96b9533074f399d23d1e3d21fac89d772
7
- data.tar.gz: f71973fd392c15a243a28ac09e521e813adf4900eefacfbc55712bd4f942c46b3351cfe44e183c1e809b0285b0ffb22ab320afd26b84c3d329be7fe79897378d
6
+ metadata.gz: cc73661c433669d3b9efcd816088513a031d7c8c609844988e0ecabed36959e9a361d15d8cbd87905f83bfcb3685640dbad1a7862d624a6895b0b78fe0aa54f7
7
+ data.tar.gz: 7c544cd27042ec8436d2c11a9f27c6269e039256dadb1ba80a62dac6b3140669420c336df950077aa6a54786158f5c2f3b91744b3cacf67de2003db686ffca37
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.4.4
1
+ 4.0.5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,240 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0 - 2026-10-31
4
+
5
+ _If you are upgrading: please see [UPGRADING.md]._
6
+
7
+ ### Bug fixes
8
+
9
+ * Apply nutation after precession for a `DeepSkyObject` without an ephemeris.
10
+ The two rotations were composed in the wrong order, so the apparent position
11
+ was off by up to about 0.1 arcsecond depending on the date, and the velocity
12
+ had the same error. The rotation now matches ERFA and Skyfield, and is the
13
+ one used when an ephemeris is given. Without an ephemeris there is still no
14
+ aberration correction ([#316])
15
+ * Let the rise, transit and set refinement move an estimate back in time. The
16
+ correction was clamped to be positive, so an estimate that overshot its event
17
+ could never be brought back, and settings and transits came out up to a few
18
+ minutes late depending on the window asked for ([#301])
19
+ * Refer equatorial coordinates to the epoch of the frame they come from
20
+ ([#302])
21
+ * Return real Barycentric Dynamical Time from `Instant#tdb`, which returned
22
+ Terrestrial Time unchanged. The two scales differ by up to about 1.7
23
+ milliseconds ([#304])
24
+ * Keep ΔT at its last measured value past the end of the IERS series. `iers`
25
+ 0.3.0 stopped attaching an `available_range` to the `OutOfRangeError` it
26
+ raises for an uncovered date, and the fallback read that absence as "no data
27
+ at all" and answered 0. Every date after the bundled series, currently
28
+ 2027-09-04, was off by about 69 seconds ([#304])
29
+ * Read the constellation data files as UTF-8, so that `Constellations::Finder`
30
+ and `Constellations::Repository` work when the default external encoding is
31
+ not UTF-8, as under `LANG=C`
32
+
33
+ ### Features
34
+
35
+ * Add `HorizontalTransformation`, which converts equatorial coordinates at
36
+ J2000 epoch into horizontal coordinates for one observer and one instant. The
37
+ rotation and the sidereal time are computed once, which makes converting many
38
+ points, like the stars of a catalogue, about 70 times faster than going
39
+ through `DeepSkyObject#at(instant).observed_by(observer).horizontal`. Points
40
+ are treated as fixed directions, as for a `DeepSkyObject` without an
41
+ ephemeris. `refraction:` is an option ([#317])
42
+ * Add `AltitudeCrossingCalculator`, which finds when a body reaches any
43
+ altitude, with unrounded instants, the crossing direction, a grazing flag and
44
+ the culminations. `refraction:` and `reference:` (`:center`, `:upper_limb`,
45
+ `:lower_limb`) are options ([#311])
46
+ * Expose lunar eclipse shadow geometry at greatest eclipse and at every contact
47
+ ([#300])
48
+ * Add lunar eclipse local circumstances with `LunarEclipse#visibility_from`
49
+ ([#302])
50
+ * Expose the Moon's apparent place at every lunar eclipse contact ([#302])
51
+
52
+ ### Improvements
53
+
54
+ * Cache Greenwich mean and apparent sidereal times when the cache is enabled.
55
+ The cache is still disabled by default, which is now stated in the README
56
+ ([#320])
57
+ * Compute the TAI and TDB time scales with the horologium gem, which owns the
58
+ scales that convert by definition or by model. UT1 stays in Astronoby
59
+ ([#304])
60
+ * Read `Instant#tai` and `#tdb` as a `Rational`, which a `Float` Julian Date is
61
+ too coarse to hold ([#304])
62
+ * Evaluate `Precession` in TT, as SOFA and ERFA do ([#304])
63
+ * Raise the minimum `iers` version from 0.1 to 0.3.1, which `horologium`
64
+ requires ([#304])
65
+ * Share the rise and set horizon convention through `Astronoby::Horizon`
66
+ ([#311])
67
+ * Derive a lunar eclipse's magnitudes, axis distance and gamma from its
68
+ geometry ([#300], [#302])
69
+ * Resolve the lunar eclipse shadow axis offset with vectors ([#302])
70
+ * Reduce the Moon to the observer by vectors for lunar eclipse visibility
71
+ ([#302])
72
+ * Answer lunar eclipse phase coverage in the words the whole eclipse uses
73
+ ([#302])
74
+ * Pin CI runner to ubuntu-24.04 ([#312])
75
+ * Fix CI for the standard and simplecov bumps ([#319])
76
+ * Bump rubyzip from 3.4.0 to 3.7.0 by @dependabot ([#285], [#299], [#305],
77
+ [#308])
78
+ * Bump standard from 1.55.0 to 1.56.0 by @dependabot ([#288])
79
+ * Bump simplecov from 0.22 to 1.0.3 by @dependabot ([#287], [#289], [#291])
80
+ * Bump iers from 0.1.0 to 0.2.0 by @dependabot ([#284], [#294])
81
+ * Update json to 2.21.2 ([#296])
82
+
83
+ ### Backward-incompatible changes
84
+
85
+ * `TwilightCalculator` is based on `AltitudeCrossingCalculator`. Times change
86
+ slightly: up to about 30 seconds at the standard angles, and up to about 100
87
+ seconds with `time_for_zenith_angle` and custom angles. The new values match
88
+ IMCCE, Horizons and Skyfield. Twilight that exists is returned when the Sun
89
+ doesn't rise or set, as in a polar night, instead of `nil`. Results are still
90
+ rounded to the second. `#event_on` is about 1.8 times slower than before,
91
+ because it solves for the real crossing instead of approximating the Sun's
92
+ position from a single evaluation ([#311])
93
+ * Equatorial coordinates carry the epoch of the frame they come from ([#302])
94
+ * `Instant#tdb` returns real TDB, and `#tai` and `#tdb` return a `Rational`
95
+ ([#304])
96
+ * Remove `Constants::TAI_TT_OFFSET` ([#304])
97
+ * `Util::Time.terrestrial_universal_time_delta` is replaced by `DeltaT.at`
98
+ ([#295])
99
+ * `EclipsePhase` is now `LunarEclipsePhase`, `LunarEclipse#greatest_eclipse` is
100
+ now `#greatest_eclipse_instant`, `LunarEclipse.new` no longer accepts the
101
+ magnitudes, gamma or shadow axis distance, and `LunarEclipsePhase#duration` is
102
+ no longer rounded ([#300], [#302])
103
+ * Remove `LunarEclipseVisibility#altitude_at` ([#302])
104
+ * Lunar eclipse contacts are reduced with the IAU eclipse constant k. Contact
105
+ times may shift by a second or two, and magnitudes by up to about 0.001
106
+ ([#302])
107
+ * Bisect to a millisecond rather than to a second when locating an event in
108
+ time. Conjunction and opposition times may move by a fraction of a second, and
109
+ searches are about 20% slower ([#302])
110
+
111
+ **Full Changelog**: https://github.com/rhannequin/astronoby/compare/v0.10.0...v0.11.0
112
+
113
+ [#284]: https://github.com/rhannequin/astronoby/pull/284
114
+ [#285]: https://github.com/rhannequin/astronoby/pull/285
115
+ [#287]: https://github.com/rhannequin/astronoby/pull/287
116
+ [#288]: https://github.com/rhannequin/astronoby/pull/288
117
+ [#289]: https://github.com/rhannequin/astronoby/pull/289
118
+ [#291]: https://github.com/rhannequin/astronoby/pull/291
119
+ [#294]: https://github.com/rhannequin/astronoby/pull/294
120
+ [#295]: https://github.com/rhannequin/astronoby/pull/295
121
+ [#296]: https://github.com/rhannequin/astronoby/pull/296
122
+ [#299]: https://github.com/rhannequin/astronoby/pull/299
123
+ [#300]: https://github.com/rhannequin/astronoby/pull/300
124
+ [#301]: https://github.com/rhannequin/astronoby/pull/301
125
+ [#302]: https://github.com/rhannequin/astronoby/pull/302
126
+ [#304]: https://github.com/rhannequin/astronoby/pull/304
127
+ [#305]: https://github.com/rhannequin/astronoby/pull/305
128
+ [#308]: https://github.com/rhannequin/astronoby/pull/308
129
+ [#311]: https://github.com/rhannequin/astronoby/pull/311
130
+ [#312]: https://github.com/rhannequin/astronoby/pull/312
131
+ [#316]: https://github.com/rhannequin/astronoby/pull/316
132
+ [#317]: https://github.com/rhannequin/astronoby/pull/317
133
+ [#319]: https://github.com/rhannequin/astronoby/pull/319
134
+ [#320]: https://github.com/rhannequin/astronoby/pull/320
135
+ [UPGRADING.md]: https://github.com/rhannequin/astronoby/blob/main/UPGRADING.md
136
+
137
+ ## 0.10.0 - 2026-06-26
138
+
139
+ _If you are upgrading: please see [UPGRADING.md]._
140
+
141
+ ### Bug fixes
142
+
143
+ * Fix constant name typo ([#245])
144
+ * Fix matrix multiplication order in Apparent frame ([#250])
145
+ * Remove spurious N·P from observer ECEF-to-TOD transformation ([#251])
146
+ * Apply aberration in GCRS before precession/nutation rotation ([#253])
147
+ * Fix Moon magnitude ([#254])
148
+ * Fix astrometric position for Deep Sky Objects ([#272])
149
+
150
+ ### Features
151
+
152
+ * Defer Solar System body computations lazily ([#244])
153
+ * Integrate `iers` gem for Delta T and GMST ([#249])
154
+ * Add IERS polar motion correction to observer ECEF-to-TOD transformation ([#252])
155
+ * Fall back to polynomial GMST for dates outside IERS EOP range ([#255])
156
+ * Add ICRS frame bias to precession matrix ([#257])
157
+ * Extract `EarthRotation` class from `Observer` ([#260])
158
+ * Add TEME reference frame for satellite tracking ([#261])
159
+ * Add ECEF to geodetic conversion (WGS-84) ([#262])
160
+ * Memoize per-instant conversions on `Instant` ([#268])
161
+ * Add `ReferenceFrame#separation_from` for angular separation ([#269])
162
+ * Introduce `Center`, `Body` and `Position` domain objects ([#270])
163
+ * Add planetary phenomena ([#271])
164
+ * Add lunar libration, position angle of axis and bright limb ([#273])
165
+ * Add `Astronoby::Orientation` for arcsecond lunar libration ([#279])
166
+ * Add Lunar eclipses ([#280])
167
+ * Add `Astronoby::Duration` ([#281])
168
+
169
+ ### Improvements
170
+
171
+ * Optimize nutation loop by eliminating array allocations ([#246])
172
+ * Reuse single Nutation instance in observer matrix computation ([#247])
173
+ * Memoize Observer geodetic computation methods ([#248])
174
+ * Update documentation with recent values ([#256])
175
+ * Update referential frames documentation ([#258])
176
+ * YARD documentation update ([#259])
177
+ * Update zlib, JSON and ERB for security reasons
178
+ * Add references to README
179
+ * Bump actions/checkout from 5 to 7 by @dependabot ([#239], [#276])
180
+ * Bump rubyzip from 3.2.1 to 3.4.0 by @dependabot ([#237], [#267], [#275])
181
+ * Bump irb from 1.15.2 to 1.17.0 by @dependabot ([#242])
182
+ * Bump standard from 1.51.1 to 1.55.0 by @dependabot ([#243], [#274])
183
+ * Bump rake from 13.3.1 to 13.4.2 by @dependabot ([#264])
184
+ * Bump ephem from 0.4.1 to 0.5.0 by @dependabot ([#278])
185
+ * Upgrade default Ruby to 4.0.5 ([#277])
186
+
187
+ ### Backward-incompatible changes
188
+
189
+ * Minimum Ruby version bumped to 3.2.0 ([#249])
190
+ * Delta T and GMST now use IERS data ([#249])
191
+ * Defer Solar System body computations lazily ([#244])
192
+ * `SolarSystemBody#ephem` is now publicly accessible ([#244])
193
+ * `ReferenceFrame#center_identifier` replaced by `#center` ([#270])
194
+ * `Sun#equation_of_time` now returns a `Duration` ([#281])
195
+
196
+ **Full Changelog**: https://github.com/rhannequin/astronoby/compare/v0.9.0...v0.10.0
197
+
198
+ [#237]: https://github.com/rhannequin/astronoby/pull/237
199
+ [#239]: https://github.com/rhannequin/astronoby/pull/239
200
+ [#242]: https://github.com/rhannequin/astronoby/pull/242
201
+ [#243]: https://github.com/rhannequin/astronoby/pull/243
202
+ [#244]: https://github.com/rhannequin/astronoby/pull/244
203
+ [#245]: https://github.com/rhannequin/astronoby/pull/245
204
+ [#246]: https://github.com/rhannequin/astronoby/pull/246
205
+ [#247]: https://github.com/rhannequin/astronoby/pull/247
206
+ [#248]: https://github.com/rhannequin/astronoby/pull/248
207
+ [#249]: https://github.com/rhannequin/astronoby/pull/249
208
+ [#250]: https://github.com/rhannequin/astronoby/pull/250
209
+ [#251]: https://github.com/rhannequin/astronoby/pull/251
210
+ [#252]: https://github.com/rhannequin/astronoby/pull/252
211
+ [#253]: https://github.com/rhannequin/astronoby/pull/253
212
+ [#254]: https://github.com/rhannequin/astronoby/pull/254
213
+ [#255]: https://github.com/rhannequin/astronoby/pull/255
214
+ [#256]: https://github.com/rhannequin/astronoby/pull/256
215
+ [#257]: https://github.com/rhannequin/astronoby/pull/257
216
+ [#258]: https://github.com/rhannequin/astronoby/pull/258
217
+ [#259]: https://github.com/rhannequin/astronoby/pull/259
218
+ [#260]: https://github.com/rhannequin/astronoby/pull/260
219
+ [#261]: https://github.com/rhannequin/astronoby/pull/261
220
+ [#262]: https://github.com/rhannequin/astronoby/pull/262
221
+ [#264]: https://github.com/rhannequin/astronoby/pull/264
222
+ [#267]: https://github.com/rhannequin/astronoby/pull/267
223
+ [#268]: https://github.com/rhannequin/astronoby/pull/268
224
+ [#269]: https://github.com/rhannequin/astronoby/pull/269
225
+ [#270]: https://github.com/rhannequin/astronoby/pull/270
226
+ [#271]: https://github.com/rhannequin/astronoby/pull/271
227
+ [#272]: https://github.com/rhannequin/astronoby/pull/272
228
+ [#273]: https://github.com/rhannequin/astronoby/pull/273
229
+ [#274]: https://github.com/rhannequin/astronoby/pull/274
230
+ [#275]: https://github.com/rhannequin/astronoby/pull/275
231
+ [#276]: https://github.com/rhannequin/astronoby/pull/276
232
+ [#277]: https://github.com/rhannequin/astronoby/pull/277
233
+ [#278]: https://github.com/rhannequin/astronoby/pull/278
234
+ [#279]: https://github.com/rhannequin/astronoby/pull/279
235
+ [#280]: https://github.com/rhannequin/astronoby/pull/280
236
+ [#281]: https://github.com/rhannequin/astronoby/pull/281
237
+
3
238
  ## 0.9.0 - 2025-10-31
4
239
 
5
240
  _If you are upgrading: please see [UPGRADING.md]._
data/README.md CHANGED
@@ -11,7 +11,9 @@ Some algorithms are based on the following astrometry books:
11
11
  Duffet-Smith and Jonathan Zwart
12
12
 
13
13
  Solar System bodies' positions are computed based on ephemerides from the
14
- [IMCCE] or [NASA/JPL].
14
+ [IMCCE] or [NASA/JPL]. The library also supports Earth-orbiting satellite
15
+ tracking through the [TEME] reference frame, suitable for use with SGP4/SDP4
16
+ orbit propagators.
15
17
 
16
18
  ## Content
17
19
  - [Installation](#installation)
@@ -45,6 +47,8 @@ previous versions, you can access the documentation in the README for each
45
47
  and objects
46
48
  - [Reference Frames](docs/reference_frames.md) - for coordinate systems
47
49
  - [Observer Setup](docs/observer.md) - for location configuration
50
+ - [IERS Data](docs/iers.md) - for Delta T and Greenwich Mean Sidereal Time
51
+ (GMST) data management
48
52
  - [Glossary](docs/glossary.md) - for astronomical and technical terms
49
53
 
50
54
  ### Expected breaking changes notice
@@ -69,6 +73,19 @@ automated guiding of amateur telescopes and some professional use-cases.
69
73
  The sources used for comparison are: [IMCCE], [JPL Horizons], [Stellarium],
70
74
  and the [Skyfield] library.
71
75
 
76
+ ## Performance
77
+
78
+ Astronoby has an internal cache for intermediate results like nutation,
79
+ precession and sidereal time. It is disabled by default. It helps when the same
80
+ computation is repeated at one instant, for example for many bodies or many
81
+ points seen by one observer, and can make it about 2.5 times faster:
82
+
83
+ ```rb
84
+ Astronoby.configuration.cache_enabled = true
85
+ ```
86
+
87
+ See the [configuration documentation](docs/configuration.md) for the details.
88
+
72
89
  ## Development
73
90
 
74
91
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
@@ -122,6 +139,7 @@ Everyone interacting in the Astronoby project's codebases, issue trackers, chat
122
139
  rooms and mailing lists is expected to follow the [code of conduct].
123
140
 
124
141
  [NASA/JPL]: https://ssd.jpl.nasa.gov/planets/eph_export.html
142
+ [TEME]: https://github.com/rhannequin/astronoby/blob/main/docs/reference_frames.md#teme
125
143
  [Bundler]: https://bundler.io
126
144
  [`docs/`]: https://github.com/rhannequin/astronoby/blob/main/docs
127
145
  [release]: https://github.com/rhannequin/astronoby/releases
data/UPGRADING.md CHANGED
@@ -7,6 +7,276 @@ changes to it as long as a major version has not been released.
7
7
  If you are already using Astronoby and wish to follow the changes to its
8
8
  public API, please read the upgrading notes for each release.
9
9
 
10
+ ## Upgrading from 0.10.0 to 0.11.0
11
+
12
+ ### Lunar eclipse contacts and magnitudes have changed slightly
13
+
14
+ Lunar eclipse contacts are now reduced with the IAU eclipse constant
15
+ k = 0.2725076 Earth radii, putting the Moon's radius at 1738.09 km, instead of
16
+ its physical equatorial radius of 1737.4 km. This is what IMCCE and NASA reduce
17
+ eclipses with. The atmospheric enlargement of Earth's shadow has been
18
+ recalibrated alongside it, from 1/99 of Earth's radius to a 64 km shell.
19
+
20
+ The two constants have to move together: either one alone makes agreement with
21
+ IMCCE worse, because the old 1/99 enlargement was partly compensating for the
22
+ smaller lunar radius. Together they cut the contact-time error against IMCCE by
23
+ more than half, and the worst case over the 2026 to 2048 eclipses from 8.9
24
+ seconds to 2.2 seconds.
25
+
26
+ Contact times may shift by a second or two, and the magnitudes by up to about
27
+ 0.001. Greatest eclipse, `#gamma` and `#shadow_axis_distance` are unaffected,
28
+ since they depend on neither constant.
29
+
30
+ ### `EclipsePhase` is now `LunarEclipsePhase`
31
+
32
+ `Astronoby::EclipsePhase` has been renamed to `Astronoby::LunarEclipsePhase`.
33
+ Its geometry is a `LunarEclipseGeometry`, so the class was never general to
34
+ every kind of eclipse, and the old name reserved a place that solar eclipses
35
+ will need.
36
+
37
+ ### A lunar eclipse and its phases are built from fewer values
38
+
39
+ `Astronoby::LunarEclipsePhase.new` requires `starting_geometry:` and
40
+ `ending_geometry:`, and `Astronoby::LunarEclipse.new` requires `geometry:`,
41
+ each an `Astronoby::LunarEclipseGeometry`.
42
+
43
+ `LunarEclipse.new` no longer accepts `umbral_magnitude:`,
44
+ `penumbral_magnitude:`, `gamma:` or `shadow_axis_distance:`. All four are now
45
+ read off the geometry at greatest eclipse, so an eclipse can no longer be
46
+ built holding values that contradict its own geometry. The readers are
47
+ unchanged.
48
+
49
+ Both objects are built by `Astronoby::LunarEclipseCalculator`, so this only
50
+ affects code constructing them directly.
51
+
52
+ ### `LunarEclipse#greatest_eclipse` is now `#greatest_eclipse_instant`
53
+
54
+ The method returns an `Astronoby::Instant`, not an eclipse. `#instant` remains
55
+ available and is the same value.
56
+
57
+ ### `LunarEclipsePhase#duration` is no longer rounded
58
+
59
+ The duration was rounded to whole seconds. It is now measured on the
60
+ terrestrial time scale, which is continuous, so it is unaffected by a leap
61
+ second falling inside the phase, and it keeps the fraction of a second.
62
+ `#duration.seconds` may now return a Float with a fractional part.
63
+
64
+ ### Equatorial coordinates carry the epoch of the frame they came from
65
+
66
+ `#equatorial` reported the J2000 epoch on every reference frame, including
67
+ frames referred to the equator and equinox of date. Precessing a mean of date,
68
+ apparent, topocentric or TEME place was therefore a no operation rather than
69
+ removing the precession accumulated since J2000, and `GeocentricParallax`
70
+ carried the wrong epoch into anything derived from one.
71
+
72
+ `MeanOfDate`, `Apparent`, `Topocentric` and `Teme` now report their own
73
+ instant as the epoch, through a new `#epoch` reader on `ReferenceFrame`.
74
+ `Geometric` and `Astrometric` are unchanged, since both are built on the ICRS
75
+ and were already right.
76
+
77
+ Code passing an of date coordinate to
78
+ `Precession.for_equatorial_coordinates` will now get a precessed result where
79
+ it previously got the coordinate back nearly unchanged.
80
+
81
+ ### Twilight times are computed from altitude crossings
82
+
83
+ `TwilightCalculator` is now built on `AltitudeCrossingCalculator`, which finds
84
+ the instant the Sun's centre reaches each altitude directly. The previous
85
+ approach was an approximation that could be off by tens of seconds.
86
+
87
+ Times change slightly: up to about 30 seconds at the standard angles, and up to
88
+ about 100 seconds with `time_for_zenith_angle` and custom angles. The new
89
+ values agree with IMCCE, JPL Horizons and Skyfield. Results are still rounded
90
+ to the second.
91
+
92
+ When the Sun doesn't rise or set, as in a polar night, the twilight that does
93
+ happen is now returned instead of `nil`. A twilight that never happens, such as
94
+ astronomical twilight at high latitude in midsummer, is still `nil`.
95
+
96
+ `TwilightCalculator#event_on` is about 1.8 times slower than before, from around
97
+ 4 to around 7.5 milliseconds for one day. The previous version approximated the
98
+ Sun's position from a single evaluation, which could be off by up to 30
99
+ seconds. This one solves for the real crossing, evaluating the Sun's position
100
+ about 20 times, and agrees with IMCCE, JPL Horizons and Skyfield to the second.
101
+
102
+ ### Rise, transit and set times are no longer late
103
+
104
+ The refinement of a rise, transit or set time could only move its estimate
105
+ forward in time. An estimate that overshot its event was never brought back, so
106
+ settings and transits came out up to a few minutes late depending on the window
107
+ asked for. Moon transits now agree with Skyfield to the second. Expect Moon
108
+ times to move by up to a few minutes, and Sun and planet times by a few
109
+ seconds.
110
+
111
+ ### Event times are located more precisely
112
+
113
+ Bisection accepted a root once its bracket fell under 0.864 seconds, so a
114
+ reported time could sit up to 0.43 seconds from the root of the model it came
115
+ from. It now bisects to under a millisecond. Conjunction and opposition times
116
+ may move by a fraction of a second, and a time that sat near a whole second
117
+ may round to the next one.
118
+
119
+ A sample landing exactly on a root is also no longer missed, and bisection
120
+ stops if a bracket reaches the resolution of a Float rather than looping.
121
+
122
+ ### New `horologium` dependency, and `iers` raised to 0.3.1
123
+
124
+ The TAI and TDB time scales are now computed by the
125
+ [`horologium`](https://github.com/rhannequin/horologium) gem, which owns the
126
+ scales that convert by definition or by model. UT1 stays in Astronoby: it
127
+ follows the actual rotation of the Earth rather than a definition, and comes
128
+ from `Astronoby::DeltaT`. Nothing else about time changes, and `Instant#tt`,
129
+ `#to_time`, `#to_date`, `#to_datetime`, `#delta_t`, `#gmst`, `#gast`, `#lmst`
130
+ and `#last` are untouched.
131
+
132
+ `horologium` requires `iers` 0.3.1, so the minimum `iers` version is raised
133
+ from 0.1 to 0.3.1. One `iers` API Astronoby used did change on the way: `iers`
134
+ 0.3.0 stopped attaching an `available_range` to the `OutOfRangeError` that
135
+ `DeltaT.at` raises for a date it cannot answer. Astronoby reads the end of the
136
+ published series directly now, so ΔT past that end still comes back as the last
137
+ measured value rather than 0.
138
+
139
+ Astronoby pins the precision it asks `horologium` for, so an application that
140
+ calls `Horologium.configure` for its own purposes cannot change what Astronoby
141
+ computes.
142
+
143
+ ### `Instant#tdb` now returns Barycentric Dynamical Time
144
+
145
+ `tdb` previously returned Terrestrial Time unchanged, documented in the source
146
+ as an approximation. It now returns real TDB, from the Fairhead and Bretagnon
147
+ series that ERFA uses. The two scales differ by up to about 1.7 milliseconds.
148
+
149
+ ```rb
150
+ instant = Astronoby::Instant.from_terrestrial_time(2460796)
151
+
152
+ # Before
153
+ instant.tdb # => 2460796
154
+
155
+ # After
156
+ instant.tdb.to_f # => 2460796.000000017
157
+ ```
158
+
159
+ `Precession` is now evaluated in TT, as SOFA and ERFA do. It read `tdb` before,
160
+ which was TT under another name, so precession results are unchanged.
161
+
162
+ ### `Instant#tai` and `#tdb` return a `Rational`
163
+
164
+ Both are read as a `Rational` rather than a `Float`. A Julian Date is around
165
+ 2.46 million, so a single `Float` rounds to about 47 microseconds of the day,
166
+ which is more than the whole TDB - TT correction. Call `to_f` where a `Float`
167
+ is what you want.
168
+
169
+ `tai` is now exactly 32.184 seconds behind TT. It was within a few femtoseconds
170
+ of that for an instant built from an `Integer` or a `Rational`, the offset
171
+ having been built from a `Float` literal, and up to 47 microseconds off for one
172
+ built from a `Float`, where the result came back as a `Float` too. So the type
173
+ changes in that last case, and `tai.to_f` can land one `Float` step from where
174
+ it used to, closer to the true value.
175
+
176
+ ### Drop of `Constants::TAI_TT_OFFSET`
177
+
178
+ `Astronoby::Constants::TAI_TT_OFFSET` has been removed. The offset between TAI
179
+ and TT is `horologium`'s to hold now, and Astronoby no longer names it.
180
+
181
+ ### `Util::Time.terrestrial_universal_time_delta` replaced by `DeltaT.at`
182
+
183
+ Delta T (TT - UT1) now has its own namespace instead of living in
184
+ `Astronoby::Util::Time`. The returned value is unchanged.
185
+
186
+ ```rb
187
+ # Before
188
+ Astronoby::Util::Time.terrestrial_universal_time_delta(time)
189
+
190
+ # After
191
+ Astronoby::DeltaT.at(time)
192
+ ```
193
+
194
+ `Astronoby::Util::Time` keeps `decimal_hour_to_time`.
195
+
196
+ ## Upgrading from 0.9.0 to 0.10.0
197
+
198
+ ### Minimum Ruby version bumped to 3.2.0
199
+
200
+ The minimum required Ruby version is now 3.2.0 (previously 3.0.0), due to the
201
+ new `iers` gem dependency.
202
+
203
+ ### Delta T and GMST now use IERS data
204
+
205
+ Delta T (TT - UT1) is now computed from IERS data via the
206
+ [`iers`](https://github.com/rhannequin/iers) gem instead of hardcoded lookup
207
+ tables. Greenwich Mean Sidereal Time (GMST) is now computed using the IERS
208
+ Conventions 2010 ERA-based expression instead of the Duffett-Smith polynomial.
209
+
210
+ Both changes improve accuracy significantly (Delta T error reduced from ~0.5s
211
+ to ~0.001s, GMST error reduced by 600-2200x vs Skyfield). As a result,
212
+ computed values for sidereal times, horizontal coordinates, and
213
+ rise/transit/set times may differ slightly from previous versions.
214
+
215
+ The `iers` gem ships with bundled data files that work out of the box. See
216
+ [IERS Data](docs/iers.md) for details on data coverage and updates.
217
+
218
+ ### `SolarSystemBody` initialization is now lazy
219
+
220
+ `SolarSystemBody#initialize` no longer eagerly computes geometric positions,
221
+ light-time corrections, or Sun data. All computations are now deferred until
222
+ the corresponding method is first called. This means ephemeris-related errors
223
+ will surface on first property access rather than during instantiation.
224
+
225
+ ### `SolarSystemBody#geometric` is now a lazy method
226
+
227
+ `geometric` was previously exposed via `attr_reader` and eagerly computed in
228
+ `initialize`. It is now a lazy memoized method. The public interface is
229
+ unchanged — `body.geometric` still returns a `Geometric` object.
230
+
231
+ ### `SolarSystemBody#ephem` is now publicly accessible
232
+
233
+ The `ephem` object passed to `initialize` is now exposed via `attr_reader`.
234
+
235
+ ### `ReferenceFrame#center_identifier` replaced by `#center`
236
+
237
+ Every reference frame previously exposed `#center_identifier`, an `Integer`
238
+ (e.g. `Astronoby::SolarSystemBody::EARTH`) for barycentric/geocentric frames or
239
+ a `[longitude, latitude]` array for topocentric frames. It is replaced by
240
+ `#center`, which returns an `Astronoby::Center` value object.
241
+
242
+ ```rb
243
+ # Before
244
+ frame.center_identifier # => 399 or [longitude, latitude]
245
+
246
+ # After
247
+ frame.center # => #<Astronoby::Center ...>
248
+ frame.center.geocentric? # => true
249
+ frame.center == Astronoby::Center.geocentric # => true
250
+ frame.center.observer # => the Observer, for topocentric frames
251
+ ```
252
+
253
+ Two topocentric centers are equal when their observers share the same
254
+ latitude, longitude and elevation (atmospheric parameters are ignored).
255
+
256
+ ### `Sun#equation_of_time` now returns a `Duration`
257
+
258
+ Lengths of time are now wrapped in a new `Astronoby::Duration` value object,
259
+ consistent with `Angle`, `Distance` and `Velocity`. As a result,
260
+ `Sun#equation_of_time` returns an `Astronoby::Duration` instead of an
261
+ `Integer` of seconds. Call `#seconds` to get the previous value.
262
+
263
+ ```rb
264
+ # Before
265
+ sun.equation_of_time # => -185
266
+
267
+ # After
268
+ sun.equation_of_time # => #<Astronoby::Duration ...>
269
+ sun.equation_of_time.seconds # => -185
270
+ sun.equation_of_time.minutes # => -3.08...
271
+ ```
272
+
273
+ A `Duration` can be built with `from_seconds`, `from_minutes`, `from_hours`
274
+ and `from_days`, and read back in any of those units. It is immutable,
275
+ comparable, and supports `+` and `-`.
276
+
277
+ Note that `EclipsePhase#duration`, also introduced in this release, returns
278
+ an `Astronoby::Duration` as well.
279
+
10
280
  ## Upgrading from 0.8.0 to 0.9.0
11
281
 
12
282
  ### Constant `MINUTES_PER_DEGREE` renamed