astronoby 0.10.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +134 -0
- data/README.md +13 -0
- data/UPGRADING.md +186 -0
- data/docs/README.md +32 -8
- data/docs/altitude_crossings.md +92 -0
- data/docs/configuration.md +8 -0
- data/docs/deep_sky_bodies.md +45 -0
- data/docs/glossary.md +2 -0
- data/docs/instant.md +14 -7
- data/docs/lunar_eclipses.md +128 -13
- data/docs/twilight_times.md +26 -11
- data/lib/astronoby/bodies/deep_sky_object_position.rb +6 -24
- data/lib/astronoby/cache.rb +13 -0
- data/lib/astronoby/constants.rb +1 -2
- data/lib/astronoby/constellations/data.rb +1 -1
- data/lib/astronoby/coordinates/equatorial.rb +15 -5
- data/lib/astronoby/delta_t.rb +44 -0
- data/lib/astronoby/events/altitude_crossing.rb +29 -0
- data/lib/astronoby/events/altitude_crossing_calculator.rb +511 -0
- data/lib/astronoby/events/altitude_extreme.rb +31 -0
- data/lib/astronoby/events/lunar_eclipse.rb +49 -37
- data/lib/astronoby/events/lunar_eclipse_calculator.rb +143 -31
- data/lib/astronoby/events/lunar_eclipse_geometry.rb +115 -0
- data/lib/astronoby/events/lunar_eclipse_phase.rb +45 -0
- data/lib/astronoby/events/lunar_eclipse_visibility.rb +296 -0
- data/lib/astronoby/events/rise_transit_set_calculator.rb +9 -13
- data/lib/astronoby/events/twilight_calculator.rb +37 -147
- data/lib/astronoby/horizon.rb +40 -0
- data/lib/astronoby/horizontal_transformation.rb +112 -0
- data/lib/astronoby/instant.rb +50 -13
- data/lib/astronoby/precession.rb +1 -1
- data/lib/astronoby/reference_frame.rb +8 -3
- data/lib/astronoby/reference_frames/apparent.rb +20 -8
- data/lib/astronoby/reference_frames/mean_of_date.rb +6 -0
- data/lib/astronoby/reference_frames/teme.rb +6 -0
- data/lib/astronoby/reference_frames/topocentric.rb +6 -0
- data/lib/astronoby/root_finder.rb +16 -9
- data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +10 -8
- data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +11 -9
- data/lib/astronoby/util/time.rb +0 -22
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +9 -1
- metadata +40 -5
- data/lib/astronoby/events/eclipse_phase.rb +0 -27
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1093c9a0d077cfa9c2a9fcf60e2af2a21ec4c1f74c268ef22dca8e93b5badadb
|
|
4
|
+
data.tar.gz: e12ccfad49e7a63821cde3b382e8584efdff3c0c06a42ffddf60119ad213b2f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc73661c433669d3b9efcd816088513a031d7c8c609844988e0ecabed36959e9a361d15d8cbd87905f83bfcb3685640dbad1a7862d624a6895b0b78fe0aa54f7
|
|
7
|
+
data.tar.gz: 7c544cd27042ec8436d2c11a9f27c6269e039256dadb1ba80a62dac6b3140669420c336df950077aa6a54786158f5c2f3b91744b3cacf67de2003db686ffca37
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,139 @@
|
|
|
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
|
+
|
|
3
137
|
## 0.10.0 - 2026-06-26
|
|
4
138
|
|
|
5
139
|
_If you are upgrading: please see [UPGRADING.md]._
|
data/README.md
CHANGED
|
@@ -73,6 +73,19 @@ automated guiding of amateur telescopes and some professional use-cases.
|
|
|
73
73
|
The sources used for comparison are: [IMCCE], [JPL Horizons], [Stellarium],
|
|
74
74
|
and the [Skyfield] library.
|
|
75
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
|
+
|
|
76
89
|
## Development
|
|
77
90
|
|
|
78
91
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
data/UPGRADING.md
CHANGED
|
@@ -7,6 +7,192 @@ 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
|
+
|
|
10
196
|
## Upgrading from 0.9.0 to 0.10.0
|
|
11
197
|
|
|
12
198
|
### Minimum Ruby version bumped to 3.2.0
|
data/docs/README.md
CHANGED
|
@@ -108,26 +108,47 @@ calculator = Astronoby::TwilightCalculator.new(
|
|
|
108
108
|
event = calculator.event_on(Date.new(2025, 5, 1))
|
|
109
109
|
|
|
110
110
|
event.morning_astronomical_twilight_time
|
|
111
|
-
# => 2025-05-01 02:17:
|
|
111
|
+
# => 2025-05-01 02:17:02 UTC
|
|
112
112
|
|
|
113
113
|
event.morning_nautical_twilight_time
|
|
114
|
-
# => 2025-05-01 03:09:
|
|
114
|
+
# => 2025-05-01 03:09:39 UTC
|
|
115
115
|
|
|
116
116
|
event.morning_civil_twilight_time
|
|
117
|
-
# => 2025-05-01 03:54:
|
|
117
|
+
# => 2025-05-01 03:54:36 UTC
|
|
118
118
|
|
|
119
119
|
event.evening_civil_twilight_time
|
|
120
|
-
# => 2025-05-01 19:41:
|
|
120
|
+
# => 2025-05-01 19:41:58 UTC
|
|
121
121
|
|
|
122
122
|
event.evening_nautical_twilight_time
|
|
123
|
-
# => 2025-05-01 20:
|
|
123
|
+
# => 2025-05-01 20:27:15 UTC
|
|
124
124
|
|
|
125
125
|
event.evening_astronomical_twilight_time
|
|
126
|
-
# => 2025-05-01 21:
|
|
126
|
+
# => 2025-05-01 21:20:32 UTC
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
You can learn more about this calculator on the [Twilight times page].
|
|
130
130
|
|
|
131
|
+
## Find when a body reaches any altitude
|
|
132
|
+
|
|
133
|
+
```rb
|
|
134
|
+
calculator = Astronoby::AltitudeCrossingCalculator.new(
|
|
135
|
+
body: Astronoby::Sun,
|
|
136
|
+
observer: observer,
|
|
137
|
+
ephem: ephem
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
crossing = calculator.crossings_between(
|
|
141
|
+
Time.utc(2025, 5, 1),
|
|
142
|
+
Time.utc(2025, 5, 2),
|
|
143
|
+
altitude: Astronoby::Angle.from_degrees(30)
|
|
144
|
+
).first
|
|
145
|
+
|
|
146
|
+
crossing.direction
|
|
147
|
+
# => :rising
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
You can learn more about this calculator on the [Altitude crossings page].
|
|
151
|
+
|
|
131
152
|
## Moon phases
|
|
132
153
|
|
|
133
154
|
You can either get all the major Moon phases that will happen in a month, or get
|
|
@@ -191,7 +212,7 @@ eclipses = Astronoby::Moon.eclipse_events(
|
|
|
191
212
|
)
|
|
192
213
|
|
|
193
214
|
eclipses.map { |eclipse| [eclipse.instant.to_time, eclipse.kind] }
|
|
194
|
-
# => [[2025-03-14 06:58:
|
|
215
|
+
# => [[2025-03-14 06:58:46 UTC, :total], [2025-09-07 18:11:49 UTC, :total]]
|
|
195
216
|
```
|
|
196
217
|
|
|
197
218
|
You can learn more about umbral and penumbral magnitudes, phases and contact
|
|
@@ -263,7 +284,9 @@ vega_position.apparent.equatorial.right_ascension.str(:hms)
|
|
|
263
284
|
# => "18h 37m 48.2804s"
|
|
264
285
|
```
|
|
265
286
|
|
|
266
|
-
You can learn more about deep-sky objects
|
|
287
|
+
You can learn more about deep-sky objects, and about converting many points to
|
|
288
|
+
horizontal coordinates at once with `HorizontalTransformation`, on the
|
|
289
|
+
[Deep-sky Bodies page].
|
|
267
290
|
|
|
268
291
|
## See also
|
|
269
292
|
|
|
@@ -281,6 +304,7 @@ You can learn more about deep-sky objects on the [Deep-sky Bodies page].
|
|
|
281
304
|
[Coordinates page]: coordinates.md
|
|
282
305
|
[Rise, transit and setting times page]: rise_transit_set_times.md
|
|
283
306
|
[Twilight times page]: twilight_times.md
|
|
307
|
+
[Altitude crossings page]: altitude_crossings.md
|
|
284
308
|
[Moon phases page]: moon_phases.md
|
|
285
309
|
[Lunar observation page]: lunar_observation.md
|
|
286
310
|
[Lunar eclipses page]: lunar_eclipses.md
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Altitude crossings
|
|
2
|
+
|
|
3
|
+
`Astronoby::AltitudeCrossingCalculator` finds when a body reaches any altitude above the observer's horizon, positive or negative, with instants that are not rounded. [Twilight times](twilight_times.md) are built on it.
|
|
4
|
+
|
|
5
|
+
## Initialization
|
|
6
|
+
|
|
7
|
+
It takes as key arguments:
|
|
8
|
+
|
|
9
|
+
- `body`: the body to track, for example `Astronoby::Sun`
|
|
10
|
+
- `observer` (`Astronoby::Observer`): location on Earth of the observer
|
|
11
|
+
- `ephem`: ephemeris to provide the initial raw data
|
|
12
|
+
- `refraction` (optional, `false` by default): whether atmospheric refraction is applied to the altitude, `false` being the twilight convention
|
|
13
|
+
- `reference` (optional, `:center` by default): which point of the body reaches the altitude, `:center`, `:upper_limb` or `:lower_limb`. The limbs use the body's true semi-diameter and need a solar system body.
|
|
14
|
+
|
|
15
|
+
```rb
|
|
16
|
+
calculator = Astronoby::AltitudeCrossingCalculator.new(
|
|
17
|
+
body: Astronoby::Sun,
|
|
18
|
+
observer: observer,
|
|
19
|
+
ephem: ephem
|
|
20
|
+
)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## `#crossings_between`
|
|
24
|
+
|
|
25
|
+
It returns the `Astronoby::AltitudeCrossing` objects in a time range, sorted by time.
|
|
26
|
+
|
|
27
|
+
```rb
|
|
28
|
+
crossings = calculator.crossings_between(
|
|
29
|
+
Time.utc(2026, 10, 23),
|
|
30
|
+
Time.utc(2026, 10, 24),
|
|
31
|
+
altitude: Astronoby::Angle.from_degrees(-17.5)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
crossing = crossings.first
|
|
35
|
+
|
|
36
|
+
crossing.instant # => Astronoby::Instant, unrounded
|
|
37
|
+
crossing.direction # => :rising or :setting
|
|
38
|
+
crossing.grazing? # => true when the body only just reaches the altitude
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A crossing is `:rising` when the altitude increases through the target. It is `grazing?` when the target is within 0.05° of the body's highest or lowest altitude, where the instant is sensitive to small errors.
|
|
42
|
+
|
|
43
|
+
## `#multiple_crossings_between`
|
|
44
|
+
|
|
45
|
+
It does the same for several altitudes at once and returns one array of crossings per altitude, in the order given. The culminations and the computed positions are shared between the altitudes, which makes it much cheaper than one call per altitude.
|
|
46
|
+
|
|
47
|
+
```rb
|
|
48
|
+
civil, nautical = calculator.multiple_crossings_between(
|
|
49
|
+
start_time,
|
|
50
|
+
end_time,
|
|
51
|
+
altitudes: [Astronoby::Angle.from_degrees(-6), Astronoby::Angle.from_degrees(-12)]
|
|
52
|
+
)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## `#crossing_on`
|
|
56
|
+
|
|
57
|
+
It returns the first crossing of a given direction on a local day, or `nil`.
|
|
58
|
+
|
|
59
|
+
```rb
|
|
60
|
+
calculator.crossing_on(
|
|
61
|
+
Date.new(2026, 10, 23),
|
|
62
|
+
altitude: Astronoby::Angle.from_degrees(-17.5),
|
|
63
|
+
direction: :setting,
|
|
64
|
+
utc_offset: "+02:00"
|
|
65
|
+
)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## `#extremes_between`
|
|
69
|
+
|
|
70
|
+
It returns the upper and lower culminations in a time range, as `Astronoby::AltitudeExtreme` objects with `#kind`, `#instant` and `#altitude`. They are useful to explain why a crossing is absent: the body never got as high as, or as low as, the target.
|
|
71
|
+
|
|
72
|
+
```rb
|
|
73
|
+
calculator.extremes_between(start_time, end_time)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Accuracy
|
|
77
|
+
|
|
78
|
+
The altitude at the returned instant is within 10⁻⁵° of the target, and crossings agree with independent tools. The Sun's centre, without refraction, was compared on 2026-10-23 in Paris, 2026-03-20 in Makkah and 2026-12-21 at 60° N 10° E and 75° N 10° E, at -6°, -12° and -18° (22 crossings, observer at sea level):
|
|
79
|
+
|
|
80
|
+
| Tool | Resolution | Largest difference with Astronoby |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| [IMCCE OPALE](https://opale.imcce.fr) | 1 s | 0.6 s |
|
|
83
|
+
| [JPL Horizons](https://ssd.jpl.nasa.gov/horizons/) | 1 min table, interpolated | 0.10 s |
|
|
84
|
+
| [Skyfield](https://rhodesmills.github.io/skyfield/) on the same DE440s excerpt | 1 ms | 0.19 s |
|
|
85
|
+
| [USNO](https://aa.usno.navy.mil/data/api) | 1 min, civil twilight only | within its rounding |
|
|
86
|
+
|
|
87
|
+
The Skyfield differences are a time-scale effect rather than a geometric one: they are 0.00 s in March, 0.14 s in October and 0.18 s in December, which is the difference between Skyfield's built-in ΔT prediction and the IERS value Astronoby uses on those days. The remaining differences with Horizons and IMCCE come from the ephemerides (DE441 and INPOP19A against DE440s). The comparison also includes the polar night at 75° N, where the Sun does not rise but reaches -12° and -18°, and where the Sun never reaches -6°, as every tool agrees.
|
|
88
|
+
|
|
89
|
+
## See also
|
|
90
|
+
|
|
91
|
+
- [Twilight Times](twilight_times.md)
|
|
92
|
+
- [Rise, Transit and Set Times](rise_transit_set_times.md)
|
data/docs/configuration.md
CHANGED
|
@@ -26,6 +26,14 @@ with default precision values:
|
|
|
26
26
|
- [Moon phases]
|
|
27
27
|
- Nutation
|
|
28
28
|
- Precession
|
|
29
|
+
- Greenwich mean and apparent sidereal times, which also cover the local
|
|
30
|
+
apparent sidereal time
|
|
31
|
+
|
|
32
|
+
Sidereal times are cached for the exact UTC time, with no rounding. The cache
|
|
33
|
+
helps when the same instant is used many times, for example when converting
|
|
34
|
+
many points to horizontal coordinates for one observer. Calling
|
|
35
|
+
`DeepSkyObject#at(instant).observed_by(observer).horizontal` repeatedly at one
|
|
36
|
+
instant is about 2.5 times faster with the cache enabled.
|
|
29
37
|
|
|
30
38
|
## Cache precision
|
|
31
39
|
|
data/docs/deep_sky_bodies.md
CHANGED
|
@@ -96,6 +96,51 @@ event.rising_time
|
|
|
96
96
|
# => 2025-10-01 01:31:25 UTC
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
## Many points at once
|
|
100
|
+
|
|
101
|
+
Getting the horizontal coordinates of a single object goes through the whole
|
|
102
|
+
chain of reference frames. Doing so for thousands of points at the same instant
|
|
103
|
+
for the same observer, like the stars of a catalogue for a sky chart, repeats
|
|
104
|
+
the same work for each of them: the rotation from the ICRS to the true equator
|
|
105
|
+
and equinox of date, and the sidereal time only depend on the observer and the
|
|
106
|
+
instant.
|
|
107
|
+
|
|
108
|
+
`Astronoby::HorizontalTransformation` computes them once, and then converts
|
|
109
|
+
any equatorial coordinates at J2000 epoch into horizontal coordinates. It is
|
|
110
|
+
about 70 times faster per point than going through
|
|
111
|
+
`DeepSkyObject#at(instant).observed_by(observer).horizontal`.
|
|
112
|
+
|
|
113
|
+
```rb
|
|
114
|
+
observer = Astronoby::Observer.new(
|
|
115
|
+
latitude: Astronoby::Angle.from_degrees(51.5072),
|
|
116
|
+
longitude: Astronoby::Angle.from_degrees(-0.1276)
|
|
117
|
+
)
|
|
118
|
+
instant = Astronoby::Instant.from_time(Time.utc(2025, 10, 1, 3))
|
|
119
|
+
|
|
120
|
+
sirius = Astronoby::Coordinates::Equatorial.new(
|
|
121
|
+
right_ascension: Astronoby::Angle.from_hms(6, 45, 8.917),
|
|
122
|
+
declination: Astronoby::Angle.from_dms(-16, 42, 58.02)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
transformation = Astronoby::HorizontalTransformation.new(
|
|
126
|
+
observer: observer,
|
|
127
|
+
instant: instant
|
|
128
|
+
)
|
|
129
|
+
horizontal = transformation.apply(sirius)
|
|
130
|
+
|
|
131
|
+
horizontal.altitude.str(:dms, precision: 0)
|
|
132
|
+
# => "+10° 36′ 27″"
|
|
133
|
+
horizontal.azimuth.str(:dms, precision: 0)
|
|
134
|
+
# => "+134° 56′ 25″"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The result is the same as the one of a `DeepSkyObject` without an ephemeris,
|
|
138
|
+
which means the points are treated as fixed directions: there is no aberration,
|
|
139
|
+
no proper motion and no parallax. Atmospheric refraction is not applied by
|
|
140
|
+
default, and can be requested with `transformation.apply(sirius, refraction:
|
|
141
|
+
true)`. The coordinates must be at J2000 epoch, otherwise an
|
|
142
|
+
`Astronoby::IncompatibleArgumentsError` is raised.
|
|
143
|
+
|
|
99
144
|
[ephemerides]: ephem.md
|
|
100
145
|
[reference frames]: reference_frames.md
|
|
101
146
|
[SIMBAD Astronomical Database]: https://simbad.u-strasbg.fr/simbad/
|
data/docs/glossary.md
CHANGED
|
@@ -238,6 +238,8 @@ The primary time standard used worldwide. All astronomical calculations in Astro
|
|
|
238
238
|
|
|
239
239
|
- **Julian Day**: Continuous day count since 4713 BCE
|
|
240
240
|
- **Terrestrial Time (TT)**: Astronomical time scale used for calculations
|
|
241
|
+
- **International Atomic Time (TAI)**: The atomic time scale TT is defined against, 32.184 seconds behind it
|
|
242
|
+
- **Barycentric Dynamical Time (TDB)**: Time at the Solar System barycentre, within about 1.7 milliseconds of TT
|
|
241
243
|
- **UTC**: Coordinated Universal Time, the standard for civil time
|
|
242
244
|
|
|
243
245
|
## See also
|
data/docs/instant.md
CHANGED
|
@@ -25,7 +25,10 @@ International Astronomical Union, as a [Julian Date].
|
|
|
25
25
|
From this instant in <abbr title="Terrestrial Time">TT</abbr>, other time
|
|
26
26
|
standards can be expressed, such as the
|
|
27
27
|
<abbr title="International Atomic Time">TAI</abbr> or the
|
|
28
|
-
<abbr title="Barycentric
|
|
28
|
+
<abbr title="Barycentric Dynamical Time">TDB</abbr>. Those two are computed by
|
|
29
|
+
the [horologium] gem, which owns the time scales that convert by definition or
|
|
30
|
+
by model. UT1 is not one of them: it follows the actual rotation of the Earth,
|
|
31
|
+
so it stays in Astronoby, backed by [IERS data](iers.md).
|
|
29
32
|
|
|
30
33
|
## Initialization
|
|
31
34
|
|
|
@@ -93,7 +96,7 @@ instant.gmst
|
|
|
93
96
|
instant = Astronoby::Instant.from_terrestrial_time(2460796)
|
|
94
97
|
|
|
95
98
|
instant.tai.to_f
|
|
96
|
-
# => 2460795.
|
|
99
|
+
# => 2460795.9996275
|
|
97
100
|
```
|
|
98
101
|
|
|
99
102
|
- UTC offset (difference with UTC in days)
|
|
@@ -105,17 +108,20 @@ instant.utc_offset.to_f
|
|
|
105
108
|
# => 0.0008003974106626159
|
|
106
109
|
```
|
|
107
110
|
|
|
108
|
-
- Barycentric
|
|
111
|
+
- Barycentric Dynamical Time
|
|
109
112
|
|
|
110
113
|
```rb
|
|
111
|
-
# This is not handled for now, and returns TT
|
|
112
|
-
|
|
113
114
|
instant = Astronoby::Instant.from_terrestrial_time(2460796)
|
|
114
115
|
|
|
115
|
-
instant.tdb
|
|
116
|
-
# => 2460796
|
|
116
|
+
instant.tdb.to_f
|
|
117
|
+
# => 2460796.000000017
|
|
117
118
|
```
|
|
118
119
|
|
|
120
|
+
`tai` and `tdb` are read as a `Rational`. A Julian Date is around 2.46
|
|
121
|
+
million, so a single `Float` rounds to about 47 microseconds of the day, which
|
|
122
|
+
is more than the whole TDB - TT correction. Call `to_f` when a `Float` is what
|
|
123
|
+
you want.
|
|
124
|
+
|
|
119
125
|
## Value Equality
|
|
120
126
|
|
|
121
127
|
As a value object, it is possible to compare different instants.
|
|
@@ -131,6 +137,7 @@ instant1 < instant2
|
|
|
131
137
|
# => true
|
|
132
138
|
```
|
|
133
139
|
|
|
140
|
+
[horologium]: https://github.com/rhannequin/horologium
|
|
134
141
|
[Gregorian calendar]: https://en.wikipedia.org/wiki/Gregorian_calendar
|
|
135
142
|
[Terrestrial Time]: https://en.wikipedia.org/wiki/Terrestrial_Time
|
|
136
143
|
[Julian Date]: https://en.wikipedia.org/wiki/Julian_day
|