Skip to content
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

Add sources and results for comparison #114

Merged
merged 3 commits into from
Dec 10, 2024
Merged

Add sources and results for comparison #114

merged 3 commits into from
Dec 10, 2024

Conversation

rhannequin
Copy link
Owner

@rhannequin rhannequin commented Dec 4, 2024

SunCalc

CSV generation script

The following script helped generating sun_calc.csv with 474,337 combinations.

require "csv"
require "sun_calc"

tries = 0
days_range = 0..365
latitude_range = (-89..89).step(5)
longitude_range = (-179..179).step(10)
estimated_tries = days_range.size * latitude_range.size * longitude_range.size

CSV.open("sun_calc.csv", "wb") do |csv|
  csv << %w[
    date
    latitude
    longitude
    sun_rising_time
    sun_transit_time
    sun_setting_time
    moon_rising_time
    moon_transit_time
    moon_setting_time
    illuminated_fraction
  ]

  days_range.each do |i|
    latitude_range.each do |latitude|
      longitude_range.each do |longitude|
        puts "Try #{tries}/#{estimated_tries}"

        date = Date.new(2024, 1, 1).next_day(i)
        noon = Time.utc(date.year, date.month, date.day, noon)
        sun_results = SunCalc.sun_times(noon, latitude, longitude)
        moon_results = SunCalc.moon_times(noon, latitude, longitude)
        moon_illumination_results = SunCalc.moon_illumination(noon)

        csv << [
          date,
          latitude,
          longitude,
          sun_results[:sunrise],
          sun_results[:solar_noon],
          sun_results[:sunset],
          moon_results[:moonrise],
          moon_results[:lunar_noon],
          moon_results[:moonset],
          moon_illumination_results[:fraction]
        ]

        tries += 1
      end
    end
  end
end

IMCCE

CSV generation script

The following script helped generating imcce.csv with 474,337 combinations.

# frozen_string_literal: true

require "csv"
require "faraday"

class DataExtractorMiddleware < Faraday::Middleware
  def on_complete(env)
    json_response = JSON.parse(env.body, symbolize_names: true)
    env.body = json_response.dig(:response, :data)
  end
end

Faraday::Response.register_middleware(
  data_extractor_middleware: DataExtractorMiddleware
)

class OpaleClient
  BASE_URL = "https://opale.imcce.fr/api/v1"

  CELESTIAL_BODIES = [
    SUN = 10,
    MOON = 301
  ].freeze

  def initialize(latitude, longitude)
    @latitude = latitude
    @longitude = longitude
  end

  def self.sun_rise_transit_set(latitude, longitude)
    new(latitude, longitude).sun_rise_transit_set
  end

  def self.moon_rise_transit_set(latitude, longitude)
    new(latitude, longitude).moon_rise_transit_set
  end

  def self.moon_illuminated_fraction(latitude, longitude)
    new(latitude, longitude).moon_illuminated_fraction
  end

  def sun_rise_transit_set
    request(
      "#{BASE_URL}/phenomena/rts/#{SUN}/2024-01-01/#{latitude},#{longitude}?twilight=true&nbd=366"
    )[0][SUN.to_s.to_sym]
  end

  def moon_rise_transit_set
    request(
      "#{BASE_URL}/phenomena/rts/#{MOON}/2024-01-01/#{latitude},#{longitude}?nbd=366"
    )[0][MOON.to_s.to_sym]
  end

  def moon_illuminated_fraction
    request(
      "#{BASE_URL}/positions/#{MOON}?date=2024-01-01T12:00:00&step=1D&nbd=366&quantities=il"
    )
  end

  private

  attr_reader :latitude, :longitude

  def request(url)
    conn = Faraday.new(url: url) do |faraday|
      faraday.use DataExtractorMiddleware
    end

    conn.get(url).body
  end
end

tries = 0
latitude_range = (-89..89).step(5)
longitude_range = (-179..179).step(10)
estimated_tries = latitude_range.size * longitude_range.size

CSV.open("imcce.csv", "wb") do |csv|
  csv << %w[
    date
    latitude
    longitude
    sun_rising_time
    sun_transit_time
    sun_setting_time
    sun_civil_dawn_time
    sun_civil_dusk_time
    sun_nautical_dawn_time
    sun_nautical_dusk_time
    sun_astronomical_dawn_time
    sun_astronomical_dusk_time
    moon_rising_time
    moon_transit_time
    moon_setting_time
    illuminated_fraction
  ]

  latitude_range.each do |latitude|
    longitude_range.each do |longitude|
      puts "Try #{tries}/#{estimated_tries}"

      sun_results = OpaleClient.sun_rise_transit_set(latitude, longitude)
      moon_results = OpaleClient.moon_rise_transit_set(latitude, longitude)
      moon_illumination_results = OpaleClient.moon_illuminated_fraction(latitude, longitude)

      sun_results.each do |sun_result|
        date = sun_result[:calendarDate]
        moon_result = moon_results.find { _1[:calendarDate] == date }
        moon_illumination_result = moon_illumination_results.find { _1[:date] == "#{date}T12:00:00.000" }

        csv << [
          date,
          latitude,
          longitude,
          sun_result[:rise].dig(0, :date),
          sun_result[:upperTransit].dig(0, :date),
          sun_result[:set].dig(0, :date),
          sun_result[:civilDawn].dig(0, :date),
          sun_result[:civilDusk].dig(0, :date),
          sun_result[:nauticalDawn].dig(0, :date),
          sun_result[:nauticalDusk].dig(0, :date),
          sun_result[:astronomicalDawn].dig(0, :date),
          sun_result[:astronomicalDusk].dig(0, :date),
          moon_result[:rise].dig(0, :date),
          moon_result[:upperTransit].dig(0, :date),
          moon_result[:set].dig(0, :date),
          moon_illumination_result[:illuminatedFraction]
        ]
      end

      sleep(1)
      tries += 1
    end
  end
end

Fixed #113

@rhannequin rhannequin self-assigned this Dec 4, 2024
@trevorturk
Copy link

This is amazing to watch! Thank you for sharing along the way. I did have one question that I forgot to mention earlier. Is it recommended to take the middle of the day (noon) for these calculations? I experimented with various weather data sources that provide sun/moon data and couldn't really tell if there was an agreement on beginning vs middle of the day. For some sources, at least, it seems like they take the current time exactly to calculate the moon limitation, but some kept stable throughout the day.

If there's a recommendation (perhaps from IMCCE?) to take noon, perhaps it's worth adding to the documentation/examples or even adding a setting to enable/disable normalizing any dates/times passed in? (I have no idea if any of this would be a good idea, just some food for thought considering that I had an open question around this...)

@rhannequin
Copy link
Owner Author

@trevorturk I wouldn't say it is recommended, in my case I could have taken any fixed hour. The reason I selected noon instead of midnight, is that I noticed strange results with SunCalc providing data for the previous day. By using noon, I excluded this problem but I'm not sure why.

Astronoby provides illuminated_fraction for the instant. I selected noon just so that it can be comparable with other data sources. Same goes for the IMCCE. I'm not sure about SunCalc, the argument is called date but the default value is a Time.
I'm not able to see any recommendation from the IMCCE because their service provides a value for any date and any time, so there's no point in recommending people to constrain themselves in the data they can access.

For Astronoby, prefer to keep it without recommendation because it is really a real-time computed value, technically it changes at each instant.
However, for an app that would provide a single daily value my personal opinion would be:

  • Local midnight if possible
  • UTC midnight otherwise
    I would take midnight because it's kind of the middle of the night, period of the day when we usually notice the most objects in the sky. Local because for locations far from the Greenwich meridian, the difference of time could make a difference of percentage close to 10%. This is probably not something the common user can notice with the naked eye, so maybe it's not that important.

What do you think?

@rhannequin rhannequin marked this pull request as ready for review December 9, 2024 22:07
@trevorturk
Copy link

Seems reasonable to me, thank you for your consideration and advice!

@rhannequin rhannequin merged commit db23343 into main Dec 10, 2024
26 checks passed
@rhannequin rhannequin deleted the comparison-sources branch December 10, 2024 10:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Compare Astronoby results with SunCalc and document results
2 participants