-
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More accurate rising, transit and setting times #50
Conversation
b724ca9
to
ef43684
Compare
db35a08
to
985a075
Compare
What's the motivation for this change? For me it seems not to be an improvement:
btw. astronoby is a great library with very readable code so far. :-) |
@janfri Thanks a lot for the feedback. It means a lot to me to know some people are actually following the project and I'm glad to receive feedback to increase its quality 🙏 The main reason of this API change is to be more performant. By implementing all these methods independently, the program will compute all the data at each call, regardless of if only one value will be accessed by the developer in the end. If would need to find a way to memoize each Another way to solve this would be to add Do you have an opinion on how to resolve this? |
985a075
to
af894a5
Compare
af894a5
to
7979386
Compare
@janfri Your feedback (and what I first answered) got me thinking and I think you're right, the developer should not be impacted by internal constraints. If the calculation is expensive and calculates all the data immediately, the developer should not have to adapt to this situation but only benefit from a clear and pleasant API. I implemented a memoization mechanism based on the I kept Thank you for the feedback, I would be happy to know what you think. |
If I understand it correct the new algorithm calculates data which is horizon related: times and azimuths. If I'm correct it could be also used to calculate values for twilight related data (astronomical twilight, nautical twilight, civil twilight). In your current approach you would need a method which returns an array with very many values and a very long name. So maybe it would be better to return an object with explicit accessors (for example implemented as Struct): sun = Astronoby::Sun.new(epoch: epoch)
he = sun.horizontal_events(observer: observer)
he.astronomical_twilight_end_time
he.nautical_twilight_end_time
he.civil_twilight_end_time
he.rising_time
he.transit_time
he.setting_time
he.civil_twilight_begin_time
he.nautical_twilight_begin_time
he.astronomical_twilight_begin_time
# same for azimuth Yes, we need a better name for The advantages of this approach would be:
The only disadvantage I see is a new class with a good name and an according method name for the sun instance. ;-) What do you think? |
@janfri Something is bothering me about having a "horizontal events" class: the fact that it looks universal, while some events only apply to the Sun. I have this PR ready for twilight times, they are currently available from I can see the value of extracting twilight events times into a dedicated class if it doesn't feel right to have them in I would like also to point out that part of what you suggested (and thank you for suggesting solutions 🙏) is currently possible with the current implementation of he = Astronoby::RiseTransitSet.new(
observer: observer,
date: date,
coordinates_of_the_previous_day: coordinates_of_the_previous_day,
coordinates_of_the_day: coordinates_of_the_day,
coordinates_of_the_next_day: coordinates_of_the_next_day,
additional_altitude: Angle.from_dms(0, 50, 0) # Sun's semi-diameter
)
he.times
he.azimuths
he.transit_altitude I admit it's not perfect, having three different coordinates is important for close moving objects (by opposition with stars that look almost fixed within a few days) and the current API is not split into multiple methods like |
How about having a "universal" class for "universal events" and a subclass for "events" of the sun: class UniversalEvents
attr_accessor :rising_time, :rising_azimuth, :transit_time, :transit_altitude, :setting_time, :setting_azimuth
end
class SunEvents < UniversalEvents
attr_accessor :morning_civil_twilight_time, :evening_civil_twilight_time, :morning_nautical_twilight_time # ...
end
events1 = some_star.events(observer: observer)
events1.class # => UniversalEvents
events1.rising_time
events2 = sun.events(observer: observer)
events2.class # => SunEvents
events2.morning_civil_twilight_time
events2.rising_time
events3 = sun.events(observer: a_different_observer)
events3.class # => SunEvents
events3.morning_civil_twilight_time
events3.rising_time The names of the classes "UniversalEvents" and "SunEvents" and the method name "events" are only to demonstrate my idea. I'm sure there are better alternatives. This approach doesn't need any memoization for different observers because the data is stored in an explicit instance of UniversalEvents or SunEvents. My main point is: use an object with clever method names instead of an array as return value of the method called with the sun (or other celestial body). |
Btw. I'm only a weired Ruby guy who looks with a naive view at your api. But one who is developing in Ruby since over two decades. You are doing all the hard work with the maths. :) |
I like this approach, @janfri! I think I'm going to implement this in a follow-up PR as this one is already quite big and is required for other work. However I won't make a new version until this is fully worked out, so that hopefully the Sun's API is stable.
I really appreciate you taking time to share your experience. Because this kind of work already exists in other languages, but not in Ruby, it is important to me to develop the library with quality Ruby code, following conventions and Ruby's spirit. |
## What's Changed _If you are upgrading: please see [UPGRADING.md]._ [UPGRADING.md]: https://github.com/rhannequin/astronoby/blob/main/UPGRADING.md ### Bug fixes * Fix ecliptic to equatorial epoch ([#56]) [#56]: #56 ### Features * Add twilight times ([#49]) * Add interpolation method ([#52]) * Add decimal_hour_to_time util ([#53]) * Calculate leap seconds for an instant ([#54]) * Add `Angle#-@` ([#55]) * Enable equivalence and hash equality to `Observer` ([#57]) * Twilight events dedicated class ([#61]) [#49]: #49 [#52]: #52 [#53]: #53 [#54]: #54 [#55]: #55 [#57]: #57 [#61]: #61 ### Improvements * Upgrade bundler from 2.3.11 to 2.5.7 by @dorianmariecom ([#45]) * Drop `BigDecimal` ([#46]) * Bump rake from 13.1.0 to 13.2.0 ([#47]) * Increase Ruby versions support ([#48]) * Bump rake from 13.2.0 to 13.2.1 ([#51]) * Dedicated constants class ([#62]) * Improve accuracy of equation of time ([#63]) * Twilight times better accuracy ([#65]) * Update UPGRADING.md ([#66]) * release: Bump version to 0.4.0 ([#67]) [#45]: #45 [#46]: #46 [#47]: #47 [#48]: #48 [#51]: #51 [#62]: #62 [#63]: #63 [#65]: #65 [#66]: #66 [#67]: #67 ### Backward-incompatible changes * More accurate rising, transit and setting times ([#50]) * Observation events dedicated and centralized class ([#60]) * Change `Astronoby::Sun` constructor ([#64]) [#50]: #50 [#60]: #60 [#64]: #64 ## New Contributors * @dorianmariecom made their first contribution in [#45] [#45]: #45 **Full Changelog**: v0.3.0...v0.4.0
## What's Changed _If you are upgrading: please see [UPGRADING.md]._ [UPGRADING.md]: https://github.com/rhannequin/astronoby/blob/main/UPGRADING.md ### Bug fixes * Fix ecliptic to equatorial epoch ([#56]) [#56]: #56 ### Features * Add twilight times ([#49]) * Add interpolation method ([#52]) * Add decimal_hour_to_time util ([#53]) * Calculate leap seconds for an instant ([#54]) * Add `Angle#-@` ([#55]) * Enable equivalence and hash equality to `Observer` ([#57]) * Twilight events dedicated class ([#61]) [#49]: #49 [#52]: #52 [#53]: #53 [#54]: #54 [#55]: #55 [#57]: #57 [#61]: #61 ### Improvements * Upgrade bundler from 2.3.11 to 2.5.7 by @dorianmariecom ([#45]) * Drop `BigDecimal` ([#46]) * Bump rake from 13.1.0 to 13.2.0 ([#47]) * Increase Ruby versions support ([#48]) * Bump rake from 13.2.0 to 13.2.1 ([#51]) * Dedicated constants class ([#62]) * Improve accuracy of equation of time ([#63]) * Twilight times better accuracy ([#65]) * Update UPGRADING.md ([#66]) * release: Bump version to 0.4.0 ([#67]) [#45]: #45 [#46]: #46 [#47]: #47 [#48]: #48 [#51]: #51 [#62]: #62 [#63]: #63 [#65]: #65 [#66]: #66 [#67]: #67 ### Backward-incompatible changes * More accurate rising, transit and setting times ([#50]) * Observation events dedicated and centralized class ([#60]) * Change `Astronoby::Sun` constructor ([#64]) [#50]: #50 [#60]: #60 [#64]: #64 ## New Contributors * @dorianmariecom made their first contribution in [#45] [#45]: #45 **Full Changelog**: v0.3.0...v0.4.0
This change is a complete refactoring of rising and setting times and azimuth.
It is based on Astronomical Algorithms by Jean Meeus with a more complex but more accurate method than the ones used so far.
It also introduces transit time and altitude.
The overall precision of these events have been increased, especially for the Sun. Most of the times are accurate with the IMCCE within 2 minutes precision, with results sometimes accurate to a few seconds.
More work may be needed in the future to increase the precision for distant stars, that should be in theory simpler to deal with but are less accurate for some reason (angles are off by a dozen minutes of arc).
The following methods have been added to
Sun
:#rise_transit_set_times
#rise_set_azimuths
#transit_time
#transit_altitude
They all require an
observer
key argument. Memoization on the observer has been implemented so that each of these methods calls don't compute the values all over again.This change includes a breaking change:
Astronoby::Body
is dropped. It will probably be replaced by something likeDistantStar
,Moon
andPlanet
in the future, in the same way we haveSun
.