astronoby 0.7.0 → 0.9.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/.ruby-version +1 -1
- data/CHANGELOG.md +145 -3
- data/README.md +59 -33
- data/UPGRADING.md +75 -21
- data/docs/README.md +224 -0
- data/docs/angles.md +137 -0
- data/docs/configuration.md +98 -0
- data/docs/coordinates.md +167 -0
- data/docs/deep_sky_bodies.md +101 -0
- data/docs/ephem.md +85 -0
- data/docs/equinoxes_solstices_times.md +31 -0
- data/docs/glossary.md +152 -0
- data/docs/instant.md +139 -0
- data/docs/moon_phases.md +79 -0
- data/docs/observer.md +65 -0
- data/docs/reference_frames.md +138 -0
- data/docs/rise_transit_set_times.md +119 -0
- data/docs/solar_system_bodies.md +107 -0
- data/docs/twilight_times.md +123 -0
- data/lib/astronoby/angle.rb +6 -2
- data/lib/astronoby/angular_velocity.rb +76 -0
- data/lib/astronoby/bodies/deep_sky_object.rb +44 -0
- data/lib/astronoby/bodies/deep_sky_object_position.rb +127 -0
- data/lib/astronoby/bodies/earth.rb +12 -2
- data/lib/astronoby/bodies/jupiter.rb +17 -0
- data/lib/astronoby/bodies/mars.rb +17 -0
- data/lib/astronoby/bodies/mercury.rb +21 -0
- data/lib/astronoby/bodies/moon.rb +50 -36
- data/lib/astronoby/bodies/neptune.rb +21 -0
- data/lib/astronoby/bodies/saturn.rb +26 -0
- data/lib/astronoby/bodies/solar_system_body.rb +162 -27
- data/lib/astronoby/bodies/sun.rb +25 -2
- data/lib/astronoby/bodies/uranus.rb +5 -0
- data/lib/astronoby/bodies/venus.rb +25 -0
- data/lib/astronoby/cache.rb +189 -0
- data/lib/astronoby/configuration.rb +92 -0
- data/lib/astronoby/constants.rb +11 -3
- data/lib/astronoby/constellation.rb +12 -0
- data/lib/astronoby/constellations/data.rb +42 -0
- data/lib/astronoby/constellations/finder.rb +35 -0
- data/lib/astronoby/constellations/repository.rb +20 -0
- data/lib/astronoby/coordinates/equatorial.rb +5 -8
- data/lib/astronoby/data/constellations/constellation_names.dat +88 -0
- data/lib/astronoby/data/constellations/indexed_abbreviations.dat +88 -0
- data/lib/astronoby/data/constellations/radec_to_index.dat +238 -0
- data/lib/astronoby/data/constellations/sorted_declinations.dat +202 -0
- data/lib/astronoby/data/constellations/sorted_right_ascensions.dat +237 -0
- data/lib/astronoby/distance.rb +6 -0
- data/lib/astronoby/equinox_solstice.rb +2 -2
- data/lib/astronoby/events/extremum_calculator.rb +233 -0
- data/lib/astronoby/events/extremum_event.rb +15 -0
- data/lib/astronoby/events/moon_phases.rb +15 -14
- data/lib/astronoby/events/rise_transit_set_calculator.rb +39 -12
- data/lib/astronoby/events/twilight_calculator.rb +116 -61
- data/lib/astronoby/events/twilight_events.rb +28 -0
- data/lib/astronoby/instant.rb +34 -6
- data/lib/astronoby/julian_date.rb +78 -0
- data/lib/astronoby/mean_obliquity.rb +8 -10
- data/lib/astronoby/nutation.rb +11 -3
- data/lib/astronoby/observer.rb +1 -1
- data/lib/astronoby/precession.rb +48 -38
- data/lib/astronoby/reference_frame.rb +2 -1
- data/lib/astronoby/reference_frames/apparent.rb +1 -11
- data/lib/astronoby/reference_frames/mean_of_date.rb +1 -1
- data/lib/astronoby/reference_frames/topocentric.rb +2 -12
- data/lib/astronoby/stellar_propagation.rb +162 -0
- data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +22 -0
- data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +64 -0
- data/lib/astronoby/time/greenwich_sidereal_time.rb +20 -58
- data/lib/astronoby/time/local_apparent_sidereal_time.rb +42 -0
- data/lib/astronoby/time/local_mean_sidereal_time.rb +42 -0
- data/lib/astronoby/time/local_sidereal_time.rb +35 -26
- data/lib/astronoby/time/sidereal_time.rb +42 -0
- data/lib/astronoby/true_obliquity.rb +2 -3
- data/lib/astronoby/util/time.rb +62 -44
- data/lib/astronoby/velocity.rb +5 -0
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +19 -1
- metadata +71 -11
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -102
- data/benchmark/README.md +0 -131
- data/benchmark/benchmark.rb +0 -259
- data/benchmark/data/imcce.csv.zip +0 -0
- data/benchmark/data/sun_calc.csv.zip +0 -0
- data/lib/astronoby/epoch.rb +0 -22
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Reference Frames
|
|
2
|
+
|
|
3
|
+
A given body at a given time can be perceived at different positions, depending
|
|
4
|
+
on the reference frame and the corrections applied.
|
|
5
|
+
|
|
6
|
+
Astronoby provides five reference frames for each celestial body:
|
|
7
|
+
|
|
8
|
+
* Geometric
|
|
9
|
+
* Astrometric
|
|
10
|
+
* Mean of date
|
|
11
|
+
* Apparent
|
|
12
|
+
* Topocentric
|
|
13
|
+
|
|
14
|
+
All reference frames provide this common interface:
|
|
15
|
+
|
|
16
|
+
* `#position`: Vector of position as x,y,z `Astronoby::Distance` objects
|
|
17
|
+
* `#velocity`: Vector of velocity as x,y,z `Astronoby::Velocity` objects
|
|
18
|
+
* `#distance`: Distance from the centre (`Astronoby::Distance`)
|
|
19
|
+
* `#equatorial`: Equatorial coordinates (`Astronoby::Coordinates::Equatorial`)
|
|
20
|
+
* `#ecliptic`: Ecliptic coordinates (`Astronoby::Coordinates::Ecliptic`)
|
|
21
|
+
|
|
22
|
+
## Geometric
|
|
23
|
+
|
|
24
|
+
Also called "mean J2000", this reference frame is related to the mean ecliptic
|
|
25
|
+
or terrestrial equator and the mean equinox of the reference date (J2000). It is
|
|
26
|
+
the strict position computed from the ephemeris file in a reference frame
|
|
27
|
+
centered on the Solar System barycentre, with no corrections applied.
|
|
28
|
+
|
|
29
|
+
```rb
|
|
30
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
31
|
+
time = Time.utc(1962, 7, 24)
|
|
32
|
+
instant = Astronoby::Instant.from_time(time)
|
|
33
|
+
|
|
34
|
+
moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
|
|
35
|
+
geometric = moon.geometric
|
|
36
|
+
# => #<Astronoby::Geometric:0x000000011e7ffd40
|
|
37
|
+
|
|
38
|
+
geometric.distance.au
|
|
39
|
+
# => 1.0095091198501744
|
|
40
|
+
|
|
41
|
+
geometric.equatorial.right_ascension.str(:hms, precision: 0)
|
|
42
|
+
# => "20h 13m 52s"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Astrometric
|
|
46
|
+
|
|
47
|
+
Also called "astrometric J2000", this reference frame is related to the ecliptic
|
|
48
|
+
or the mean terrestrial equator and the mean equinox of the reference date
|
|
49
|
+
(J2000). It applies light-time correction between the celestial body and the
|
|
50
|
+
observer. The frame is centred on the Earth's centre, as are all the following
|
|
51
|
+
reference frames.
|
|
52
|
+
|
|
53
|
+
```rb
|
|
54
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
55
|
+
time = Time.utc(1962, 7, 24)
|
|
56
|
+
instant = Astronoby::Instant.from_time(time)
|
|
57
|
+
|
|
58
|
+
moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
|
|
59
|
+
astrometric = moon.astrometric
|
|
60
|
+
|
|
61
|
+
astrometric.distance.km.round
|
|
62
|
+
# => 371187
|
|
63
|
+
|
|
64
|
+
astrometric.equatorial.right_ascension.str(:hms, precision: 0)
|
|
65
|
+
# => "1h 54m 27s"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Mean of date
|
|
69
|
+
|
|
70
|
+
This reference frame is related to the ecliptic or the mean equator and the mean
|
|
71
|
+
equinox of the date. It provides the geometric position corrected for the
|
|
72
|
+
precessional motion of the Earth's rotation axis (precession and nutation).
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
```rb
|
|
76
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
77
|
+
time = Time.utc(1962, 7, 24)
|
|
78
|
+
instant = Astronoby::Instant.from_time(time)
|
|
79
|
+
|
|
80
|
+
moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
|
|
81
|
+
mean_of_date = moon.mean_of_date
|
|
82
|
+
|
|
83
|
+
mean_of_date.equatorial.right_ascension.str(:hms, precision: 0)
|
|
84
|
+
# => "1h 52m 29s"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Apparent
|
|
88
|
+
|
|
89
|
+
This reference frame is related to the true ecliptic or equator and the true
|
|
90
|
+
equinox of the date. It is the actual position in the sky of a celestial object
|
|
91
|
+
as seen from the centre of the Earth. It applies several corrections to the
|
|
92
|
+
astrometric position:the deflection of light, the aberration, the precession and
|
|
93
|
+
the nutation.
|
|
94
|
+
|
|
95
|
+
```rb
|
|
96
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
97
|
+
time = Time.utc(1962, 7, 24)
|
|
98
|
+
instant = Astronoby::Instant.from_time(time)
|
|
99
|
+
|
|
100
|
+
moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
|
|
101
|
+
apparent = moon.apparent
|
|
102
|
+
|
|
103
|
+
apparent.equatorial.right_ascension.str(:hms, precision: 0)
|
|
104
|
+
# => "1h 52m 28s"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Topocentric
|
|
108
|
+
|
|
109
|
+
This reference frame is the final transformation of a position. It provides the
|
|
110
|
+
apparent position of a celestial body as seen from a location on Earth. It can
|
|
111
|
+
only be produced given an observer (`Astronoby::Observer`). It provides another
|
|
112
|
+
set of coordinates: horizontal (`Astronoby::Coordinates::Horizontal`).
|
|
113
|
+
|
|
114
|
+
```rb
|
|
115
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
116
|
+
time = Time.utc(1962, 7, 24)
|
|
117
|
+
instant = Astronoby::Instant.from_time(time)
|
|
118
|
+
observer = Astronoby::Observer.new(
|
|
119
|
+
latitude: Astronoby::Angle.from_degrees(48.838),
|
|
120
|
+
longitude: Astronoby::Angle.from_degrees(2.4843)
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
|
|
124
|
+
topocentric = moon.observed_by(observer)
|
|
125
|
+
|
|
126
|
+
topocentric.horizontal.azimuth.str(:dms, precision: 0)
|
|
127
|
+
# => "+90° 14′ 19″"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
You can learn more about observers on the [Observer page].
|
|
131
|
+
|
|
132
|
+
## See also
|
|
133
|
+
- [Coordinates](coordinates.md) - for understanding coordinate systems
|
|
134
|
+
- [Observer](observer.md) - for location setup
|
|
135
|
+
- [Solar System Bodies](solar_system_bodies.md) - for object positions
|
|
136
|
+
- [Ephemerides](ephem.md) - for data sources
|
|
137
|
+
|
|
138
|
+
[Observer page]: observer.md
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Rise, Transit and Set Times
|
|
2
|
+
|
|
3
|
+
Astronoby provides a calculator to compute all the rise, transit and set times
|
|
4
|
+
that will happen for a celestial body as observed from Earth during a period
|
|
5
|
+
of time: `Astronoby::RiseTransitSetCalculator`.
|
|
6
|
+
|
|
7
|
+
## Initialization
|
|
8
|
+
|
|
9
|
+
Once instantiated, the calculator doesn't do anything yet, it waits for your
|
|
10
|
+
instruction.
|
|
11
|
+
|
|
12
|
+
It takes as key arguments:
|
|
13
|
+
* `body` (`Astronoby::SolarSystemBody` or `Astronoby::DeepSkyObject`): any
|
|
14
|
+
supported celestial body, e.g. `Astronoby::Sun`
|
|
15
|
+
* `observer` (`Astronoby::Observer`): location on Earth of the observer
|
|
16
|
+
* `ephem`: ephemeris to provide the initial raw data
|
|
17
|
+
|
|
18
|
+
You can learn more about [Solar System bodies] and [ephemerides].
|
|
19
|
+
|
|
20
|
+
```rb
|
|
21
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
22
|
+
|
|
23
|
+
observer = Astronoby::Observer.new(
|
|
24
|
+
latitude: Astronoby::Angle.from_degrees(41.0082),
|
|
25
|
+
longitude: Astronoby::Angle.from_degrees(28.9784),
|
|
26
|
+
elevation: Astronoby::Distance.from_meters(40)
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
calculator = Astronoby::RiseTransitSetCalculator.new(
|
|
30
|
+
body: Astronoby::Saturn,
|
|
31
|
+
observer: observer,
|
|
32
|
+
ephem: ephem
|
|
33
|
+
)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
You can learn more about observers on the
|
|
37
|
+
[Observer page](https://github.com/rhannequin/astronoby/wiki/Observer).
|
|
38
|
+
|
|
39
|
+
## `#events_between`
|
|
40
|
+
|
|
41
|
+
This is the main method of the calculator. It provides all the rising, transit
|
|
42
|
+
and setting times that will happen between two dates. It returns a
|
|
43
|
+
`Astronoby::RiseTransitSetEvents` object which exposes the methods
|
|
44
|
+
`#rising_times`, `#transit_times` and `#setting_times`.
|
|
45
|
+
|
|
46
|
+
```rb
|
|
47
|
+
events = calculator.events_between(
|
|
48
|
+
Time.utc(2025, 5, 1),
|
|
49
|
+
Time.utc(2025, 5, 3)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
events.rising_times
|
|
53
|
+
# => [2025-05-01 01:28:48 UTC, 2025-05-02 01:25:07 UTC]
|
|
54
|
+
|
|
55
|
+
events.transit_times
|
|
56
|
+
# => [2025-05-01 07:21:34 UTC, 2025-05-02 07:18:01 UTC]
|
|
57
|
+
|
|
58
|
+
events.setting_times
|
|
59
|
+
# => [2025-05-01 13:14:24 UTC, 2025-05-02 13:10:59 UTC]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## `#events_on`
|
|
63
|
+
|
|
64
|
+
You can call `#events_on` to compute the event times that will happen during a
|
|
65
|
+
civil day. You can provide a UTC offset to specify the boundaries of the civil
|
|
66
|
+
day for your location.
|
|
67
|
+
|
|
68
|
+
This method also returns a `Astronoby::RiseTransitSetEvents` object because some
|
|
69
|
+
celestial bodies could occasionally have the same event happen multiple times in
|
|
70
|
+
a single day. This is the case for the Moon, for example, which can seem to rise
|
|
71
|
+
twice in the same civil day because of its quick motion around the Earth.
|
|
72
|
+
|
|
73
|
+
```rb
|
|
74
|
+
events = calculator.events_on(Date.new(2025, 5, 1))
|
|
75
|
+
|
|
76
|
+
events.rising_times
|
|
77
|
+
# => [2025-05-01 01:28:48 UTC]
|
|
78
|
+
|
|
79
|
+
events.transit_times
|
|
80
|
+
# => [2025-05-01 07:21:34 UTC]
|
|
81
|
+
|
|
82
|
+
events.setting_times
|
|
83
|
+
# => [2025-05-01 13:14:24 UTC]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## `#event_on`
|
|
87
|
+
|
|
88
|
+
For convenience, `Astronoby::RiseTransitSetCalculator` also exposes a
|
|
89
|
+
`#event_on` method that behaves the same way as `#events_on` but returns the
|
|
90
|
+
first time of rising, transit and setting for the civil date, as these events
|
|
91
|
+
only happen once in most cases. It returns a `Astronoby::RiseTransitSetEvent`
|
|
92
|
+
which exposes the instance methods `#rising_time`, `#transit_time` and
|
|
93
|
+
`#setting_time`.
|
|
94
|
+
|
|
95
|
+
```rb
|
|
96
|
+
utc_offset = "+03:00"
|
|
97
|
+
event = calculator.event_on(
|
|
98
|
+
Date.new(2025, 5, 1),
|
|
99
|
+
utc_offset: utc_offset
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
event.rising_time.localtime(utc_offset)
|
|
103
|
+
# => 2025-05-01 04:28:48 +0300
|
|
104
|
+
|
|
105
|
+
event.transit_time.localtime(utc_offset)
|
|
106
|
+
# => 2025-05-01 10:21:34 +0300
|
|
107
|
+
|
|
108
|
+
event.setting_time.localtime(utc_offset)
|
|
109
|
+
# => 2025-05-01 16:14:24 +0300
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
[Solar System bodies]: solar_system_bodies.md
|
|
113
|
+
[ephemerides]: ephem.md
|
|
114
|
+
|
|
115
|
+
## See also
|
|
116
|
+
- [Twilight Times](twilight_times.md) - for sun-related events
|
|
117
|
+
- [Solar System Bodies](solar_system_bodies.md) - for object information
|
|
118
|
+
- [Observer](observer.md) - for location setup
|
|
119
|
+
- [Ephemerides](ephem.md) - for data sources
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Solar System Bodies
|
|
2
|
+
|
|
3
|
+
Currently, Astronoby only supports the following major bodies of the Solar
|
|
4
|
+
System:
|
|
5
|
+
* the Sun (`Astronoby::Sun`)
|
|
6
|
+
* planets from Mercury to Neptune, including the Earth (`Astronoby::Earth`, ...)
|
|
7
|
+
* the Moon (`Astronoby::Moon`)
|
|
8
|
+
|
|
9
|
+
Given an ephemeris (`Astronoby::Ephem`) and an instant object
|
|
10
|
+
(`Astronoby::Instant`), these classes enable you to get instances which provide
|
|
11
|
+
positions in different reference frames.
|
|
12
|
+
|
|
13
|
+
You can learn more about [ephemerides] and [reference frames].
|
|
14
|
+
|
|
15
|
+
```rb
|
|
16
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
17
|
+
time = Time.utc(2021, 7, 8)
|
|
18
|
+
instant = Astronoby::Instant.from_time(time)
|
|
19
|
+
|
|
20
|
+
venus = Astronoby::Venus.new(ephem: ephem, instant: instant)
|
|
21
|
+
apparent_position = venus.apparent.position
|
|
22
|
+
|
|
23
|
+
apparent_position.x.km.round
|
|
24
|
+
# => -148794622
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Each of these bodies also provides its own equatorial radius
|
|
28
|
+
(`Astronoby::Distance`).
|
|
29
|
+
|
|
30
|
+
```rb
|
|
31
|
+
Astronoby::Venus::EQUATORIAL_RADIUS.meters
|
|
32
|
+
# => 6051800
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Attributes of planets
|
|
36
|
+
|
|
37
|
+
For all Solar System bodies, except the Sun and the Earth, the following
|
|
38
|
+
attributes are available. Note that dynamic values are accessible through
|
|
39
|
+
instance methods, while absolute values are accessible through class methods.
|
|
40
|
+
|
|
41
|
+
### `#angular_diameter`
|
|
42
|
+
|
|
43
|
+
Size of the body in the sky. Returns a `Astronoby::Angle` object.
|
|
44
|
+
|
|
45
|
+
```rb
|
|
46
|
+
venus.angular_diameter.str(:dms)
|
|
47
|
+
# => "+0° 0′ 11.4587″"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### `#constellation`
|
|
51
|
+
|
|
52
|
+
Constellation where the body appears in the sky as seen from Earth. Returns
|
|
53
|
+
a `Astronoby::Constellation` object.
|
|
54
|
+
|
|
55
|
+
```rb
|
|
56
|
+
venus.constellation.name
|
|
57
|
+
# => "Cancer"
|
|
58
|
+
|
|
59
|
+
venus.constellation.abbreviation
|
|
60
|
+
# => "Cnc"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `#phase_angle`
|
|
64
|
+
|
|
65
|
+
"Sun-object-Earth" angle. Returns a `Astronoby::Angle` object.
|
|
66
|
+
|
|
67
|
+
```rb
|
|
68
|
+
venus.phase_angle.degrees.round
|
|
69
|
+
# => 40
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### `#illuminated_fraction`
|
|
73
|
+
|
|
74
|
+
Fraction of the object's disk illuminated as seen from Earth. Returns a `Float`
|
|
75
|
+
between `0` and `1`.
|
|
76
|
+
|
|
77
|
+
```rb
|
|
78
|
+
venus.illuminated_fraction.round(2)
|
|
79
|
+
# => 0.88
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `#apparent_magnitude`
|
|
83
|
+
|
|
84
|
+
Apparent brightness of the body. Returns a `Float`.
|
|
85
|
+
|
|
86
|
+
```rb
|
|
87
|
+
venus.apparent_magnitude.round(2)
|
|
88
|
+
# => -3.89
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `::absolute_magnitude`
|
|
92
|
+
|
|
93
|
+
Absolute brightness of the body. Returns a `Float`.
|
|
94
|
+
|
|
95
|
+
```rb
|
|
96
|
+
Astronoby::Venus.absolute_magnitude
|
|
97
|
+
# => -4.384
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
[ephemerides]: ephem.md
|
|
101
|
+
[reference frames]: reference_frames.md
|
|
102
|
+
|
|
103
|
+
## See also
|
|
104
|
+
- [Ephemerides](ephem.md) - for understanding data sources
|
|
105
|
+
- [Reference Frames](reference_frames.md) - for coordinate systems
|
|
106
|
+
- [Observer](observer.md) - for setting up observation locations
|
|
107
|
+
- [Angles](angles.md) - for working with angular measurements
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Twilight times
|
|
2
|
+
|
|
3
|
+
In astronomy, twilight is a period of time when the Sun is already set but
|
|
4
|
+
some of its light still illuminates the atmosphere, making the sky brighter than
|
|
5
|
+
during full night.
|
|
6
|
+
|
|
7
|
+
We usually define 4 moments when talking about twilight:
|
|
8
|
+
* sunrise/sunset: right when the Sun goes above the horizon or right after it
|
|
9
|
+
goes below the horizon. The Sun's horizon angle is 0°.
|
|
10
|
+
* civil twilight: when the horizon angle is between 0° and -6°. Usually, during
|
|
11
|
+
this time, artificial light is not needed yet.
|
|
12
|
+
* nautical twilight: when the horizon angle is between -6° and -12°. When the
|
|
13
|
+
nautical twilight starts, the difference between the horizon at sea and the
|
|
14
|
+
sky cannot be seen clearly anymore.
|
|
15
|
+
* astronomical twilight: when the horizon angle is between -12° and -18°. Some
|
|
16
|
+
stars can be seen during this time.
|
|
17
|
+
|
|
18
|
+
These moments change every day and depend on the observer's location. They can
|
|
19
|
+
be computed using `Astronoby::TwilightCalculator`.
|
|
20
|
+
|
|
21
|
+
## Initialization
|
|
22
|
+
|
|
23
|
+
Once instantiated, the calculator doesn't do anything yet, it waits for your
|
|
24
|
+
instruction.
|
|
25
|
+
|
|
26
|
+
It takes as key arguments:
|
|
27
|
+
* `observer` (`Astronoby::Observer`): location on Earth of the observer
|
|
28
|
+
* `ephem`: ephemeris to provide the initial raw data
|
|
29
|
+
|
|
30
|
+
You can learn more about ephemerides on the [Ephem page].
|
|
31
|
+
|
|
32
|
+
```rb
|
|
33
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
34
|
+
|
|
35
|
+
observer = Astronoby::Observer.new(
|
|
36
|
+
latitude: Astronoby::Angle.from_degrees(41.0082),
|
|
37
|
+
longitude: Astronoby::Angle.from_degrees(28.9784),
|
|
38
|
+
elevation: Astronoby::Distance.from_meters(40)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
calculator = Astronoby::TwilightCalculator.new(
|
|
42
|
+
observer: observer,
|
|
43
|
+
ephem: ephem
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
You can learn more about observers on the [Observer page].
|
|
48
|
+
|
|
49
|
+
## `events_between`
|
|
50
|
+
|
|
51
|
+
This is the main method of the calculator. It provides all the twilight times
|
|
52
|
+
that will happen between two dates.
|
|
53
|
+
|
|
54
|
+
It returns a `Astronoby::TwilightEvents` object which exposes the 6 following
|
|
55
|
+
instance methods:
|
|
56
|
+
* `#morning_astronomical_twilight_times`: when the rising Sun reaches 18° below
|
|
57
|
+
the horizon
|
|
58
|
+
* `#morning_nautical_twilight_times`: when the rising Sun reaches 12° below the
|
|
59
|
+
horizon
|
|
60
|
+
* `#morning_civil_twilight_times`: when the rising Sun reaches 6° below the
|
|
61
|
+
horizon
|
|
62
|
+
* `#evening_civil_twilight_times`: when the setting Sun reaches 6° below the
|
|
63
|
+
horizon
|
|
64
|
+
* `#evening_nautical_twilight_times`: when the setting Sun reaches 12° below the
|
|
65
|
+
horizon
|
|
66
|
+
* `#evening_astronomical_twilight_times`: when the setting Sun reaches 18° below
|
|
67
|
+
the horizon
|
|
68
|
+
|
|
69
|
+
```rb
|
|
70
|
+
events = calculator.events_between(
|
|
71
|
+
Time.utc(2025, 8, 1),
|
|
72
|
+
Time.utc(2025, 8, 8)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
events.morning_civil_twilight_times
|
|
76
|
+
# =>
|
|
77
|
+
# [2025-08-01 02:29:17 UTC,
|
|
78
|
+
# 2025-08-02 02:30:21 UTC,
|
|
79
|
+
# 2025-08-03 02:31:26 UTC,
|
|
80
|
+
# 2025-08-04 02:32:30 UTC,
|
|
81
|
+
# 2025-08-05 02:33:35 UTC,
|
|
82
|
+
# 2025-08-06 02:34:40 UTC,
|
|
83
|
+
# 2025-08-07 02:35:45 UTC]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## `#event_on`
|
|
87
|
+
|
|
88
|
+
The calculator exposes the instance method `#event_on` to compute the twilight
|
|
89
|
+
times for a given `date` (`Date`) parameter.
|
|
90
|
+
|
|
91
|
+
It returns a `Astronoby::TwilightEvent` object which exposes the 6 following
|
|
92
|
+
instance methods: `#morning_astronomical_twilight_time`,
|
|
93
|
+
`#morning_nautical_twilight_time`, `#morning_civil_twilight_time`,
|
|
94
|
+
`#evening_civil_twilight_time`, `#evening_nautical_twilight_time` and
|
|
95
|
+
`#evening_astronomical_twilight_time`.
|
|
96
|
+
|
|
97
|
+
```rb
|
|
98
|
+
event = calculator.event_on(Date.new(2025, 5, 1))
|
|
99
|
+
|
|
100
|
+
event.morning_astronomical_twilight_time
|
|
101
|
+
# => 2025-05-01 01:17:18 UTC
|
|
102
|
+
|
|
103
|
+
event.morning_nautical_twilight_time
|
|
104
|
+
# => 2025-05-01 01:56:48 UTC
|
|
105
|
+
|
|
106
|
+
event.evening_civil_twilight_time
|
|
107
|
+
# => 2025-05-01 17:29:41 UTC
|
|
108
|
+
|
|
109
|
+
event.evening_nautical_twilight_time
|
|
110
|
+
# => 2025-05-01 18:06:08 UTC
|
|
111
|
+
|
|
112
|
+
event.evening_astronomical_twilight_time
|
|
113
|
+
# => 2025-05-01 18:45:38 UTC
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
[Ephem page]: ephem.md
|
|
117
|
+
[Observer page]: observer.md
|
|
118
|
+
|
|
119
|
+
## See also
|
|
120
|
+
- [Rise, Transit and Set Times](rise_transit_set_times.md) - for sun and moon events
|
|
121
|
+
- [Observer](observer.md) - for location setup
|
|
122
|
+
- [Ephemerides](ephem.md) - for data sources
|
|
123
|
+
- [Moon Phases](moon_phases.md) - for lunar events
|
data/lib/astronoby/angle.rb
CHANGED
|
@@ -73,6 +73,10 @@ module Astronoby
|
|
|
73
73
|
@radians * Constants::PI_IN_DEGREES / Math::PI
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
def degree_milliarcseconds
|
|
77
|
+
degrees * Constants::MILLIARCSECONDS_PER_DEGREE
|
|
78
|
+
end
|
|
79
|
+
|
|
76
80
|
def hours
|
|
77
81
|
@radians / Constants::RADIAN_PER_HOUR
|
|
78
82
|
end
|
|
@@ -139,10 +143,10 @@ module Astronoby
|
|
|
139
143
|
sign = degrees.negative? ? "-" : "+"
|
|
140
144
|
absolute_degrees = degrees.abs
|
|
141
145
|
deg = absolute_degrees.floor
|
|
142
|
-
decimal_minutes = Constants::
|
|
146
|
+
decimal_minutes = Constants::ARCMINUTES_PER_DEGREE *
|
|
143
147
|
(absolute_degrees - deg)
|
|
144
148
|
absolute_decimal_minutes = (
|
|
145
|
-
Constants::
|
|
149
|
+
Constants::ARCMINUTES_PER_DEGREE * (absolute_degrees - deg)
|
|
146
150
|
).abs
|
|
147
151
|
minutes = decimal_minutes.floor
|
|
148
152
|
seconds = Constants::SECONDS_PER_MINUTE * (
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Astronoby
|
|
4
|
+
class AngularVelocity
|
|
5
|
+
include Comparable
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def zero
|
|
9
|
+
new(0)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def from_radians_per_second(radians_per_second)
|
|
13
|
+
new(radians_per_second)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def from_milliarcseconds_per_year(mas_per_year)
|
|
17
|
+
angle = Angle.from_degree_arcseconds(mas_per_year / 1000.0)
|
|
18
|
+
radians_per_second = angle.radians / Constants::SECONDS_PER_JULIAN_YEAR
|
|
19
|
+
new(radians_per_second)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attr_reader :radians_per_second
|
|
24
|
+
alias_method :rps, :radians_per_second
|
|
25
|
+
|
|
26
|
+
def initialize(radians_per_second)
|
|
27
|
+
@radians_per_second = radians_per_second
|
|
28
|
+
freeze
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def milliarcseconds_per_year
|
|
32
|
+
angle = Angle.from_radians(@radians_per_second)
|
|
33
|
+
angle.degree_milliarcseconds * Constants::SECONDS_PER_JULIAN_YEAR
|
|
34
|
+
end
|
|
35
|
+
alias_method :mas_per_year, :milliarcseconds_per_year
|
|
36
|
+
|
|
37
|
+
def +(other)
|
|
38
|
+
self.class.from_radians_per_second(
|
|
39
|
+
@radians_per_second + other.radians_per_second
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def -(other)
|
|
44
|
+
self.class.from_radians_per_second(
|
|
45
|
+
@radians_per_second - other.radians_per_second
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def -@
|
|
50
|
+
self.class.from_radians_per_second(-@radians_per_second)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def positive?
|
|
54
|
+
@radians_per_second > 0
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def negative?
|
|
58
|
+
@radians_per_second < 0
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def zero?
|
|
62
|
+
@radians_per_second.zero?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def hash
|
|
66
|
+
[@radians_per_second, self.class].hash
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def <=>(other)
|
|
70
|
+
return unless other.is_a?(self.class)
|
|
71
|
+
|
|
72
|
+
@radians_per_second <=> other.radians_per_second
|
|
73
|
+
end
|
|
74
|
+
alias_method :eql?, :==
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Astronoby
|
|
4
|
+
class DeepSkyObject
|
|
5
|
+
# @param equatorial_coordinates [Astronoby::Coordinates::Equatorial]
|
|
6
|
+
# Equatorial coordinates at epoch J2000.0
|
|
7
|
+
# @param proper_motion_ra [Astronoby::AngularVelocity, nil] Proper motion in
|
|
8
|
+
# right ascension
|
|
9
|
+
# @param proper_motion_dec [Astronoby::AngularVelocity, nil] Proper motion
|
|
10
|
+
# in declination
|
|
11
|
+
# @param parallax [Astronoby::Angle, nil] Parallax angle
|
|
12
|
+
# @param radial_velocity [Astronoby::Velocity, nil] Radial velocity
|
|
13
|
+
def initialize(
|
|
14
|
+
equatorial_coordinates:,
|
|
15
|
+
proper_motion_ra: nil,
|
|
16
|
+
proper_motion_dec: nil,
|
|
17
|
+
parallax: nil,
|
|
18
|
+
radial_velocity: nil
|
|
19
|
+
)
|
|
20
|
+
@initial_equatorial_coordinates = equatorial_coordinates
|
|
21
|
+
@proper_motion_ra = proper_motion_ra
|
|
22
|
+
@proper_motion_dec = proper_motion_dec
|
|
23
|
+
@parallax = parallax
|
|
24
|
+
@radial_velocity = radial_velocity
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param instant [Astronoby::Instant] Instant of the observation
|
|
28
|
+
# @param ephem [Astronoby::Ephemeris, nil] Ephemeris to use for Earth
|
|
29
|
+
# position calculation
|
|
30
|
+
# @return [Astronoby::DeepSkyObjectPosition] Position of the deep-sky object
|
|
31
|
+
# at the given instant
|
|
32
|
+
def at(instant, ephem: nil)
|
|
33
|
+
DeepSkyObjectPosition.new(
|
|
34
|
+
instant: instant,
|
|
35
|
+
equatorial_coordinates: @initial_equatorial_coordinates,
|
|
36
|
+
ephem: ephem,
|
|
37
|
+
proper_motion_ra: @proper_motion_ra,
|
|
38
|
+
proper_motion_dec: @proper_motion_dec,
|
|
39
|
+
parallax: @parallax,
|
|
40
|
+
radial_velocity: @radial_velocity
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|