Astro.Lunar.CrescentVisibility (Astro v2.11.0)

Copy Markdown View Source

Implements three criteria for predicting the visibility of the new crescent moon: Yallop (1997), Odeh (2004), and Schaefer (1988/2000).

All three functions accept a normalized location and a moment (midnight UTC for the date of interest) and return {:ok, visibility} where visibility is one of :A, :B, :C, :D, or :E.

Yallop (1997)

An empirical single-parameter criterion based on the geocentric arc of vision (ARCV) and crescent width (W). The q-value is the scaled residual between the observed ARCV and a cubic polynomial fit to Bruin's (1977) visibility curves:

ARCV' = 11.8371 − 6.3226·W + 0.7319·W² − 0.1018·W³
q = (ARCV − ARCV') / 10

Odeh (2004)

An updated empirical criterion using the same polynomial family as Yallop but fitted to 737 observations (vs Yallop's 295). Uses topocentric ARCV and a different intercept:

ARCV' = 7.1651 − 6.3226·W + 0.7319·W² − 0.1018·W³
V = ARCV − ARCV'

Odeh also enforces a Danjon limit of 6.4° (ARCL < 6.4° → not visible).

Schaefer (1988/2000)

A physics-based model that computes the contrast between the crescent moon's brightness and the twilight sky brightness, then compares against the human contrast detection threshold (Blackwell 1946). The best observation time is found by scanning from sunset to moonset.

The visibility parameter is:

Rs = log₁₀(contrast / threshold)

where Rs > 0 means the crescent is detectable. This implementation uses the V-band sky brightness model from Schaefer (1993) with default atmospheric parameters suitable for a sea-level site with clean air.

Visibility categories

CodeMeaning
:AVisible to the naked eye
:BVisible with optical aid
:CMay need optical aid
:DNot visible with optical aid
:ENot visible

References

  • Yallop, B. D. (1997). A Method for Predicting the First Sighting of the New Crescent Moon. NAO Technical Note No. 69.

  • Odeh, M. Sh. (2004). New Criterion for Lunar Crescent Visibility. Experimental Astronomy, 18, 39–64.

  • Schaefer, B. E. (1993). Astronomy and the Limits of Vision. Vistas in Astronomy, 36, 311–361.

  • Schaefer, B. E. (2000). New Methods and Techniques for Historical Astronomy and Archaeoastronomy. Archaeoastronomy, XV, 121–136.

Summary

Functions

Returns the evening of the next first sighting of a new crescent on or after an evening.

Returns the evening of the last first sighting of a new crescent on or before an evening.

Computes the Odeh (2004) visibility criterion for the new crescent moon.

Computes the Schaefer (1988/2000) visibility criterion for the new crescent moon.

Computes the Yallop (1997) visibility criterion for the new crescent moon.

Types

visibility()

@type visibility() :: :A | :B | :C | :D | :E

Functions

first_visible_crescent_on_or_after(location, day, method, options \\ [])

(since 2.10.0)
@spec first_visible_crescent_on_or_after(Geo.PointZ.t(), integer(), atom(), keyword()) ::
  {:ok, integer()} | {:error, atom()}

Returns the evening of the next first sighting of a new crescent on or after an evening.

See first_visible_crescent_on_or_before/4 for the first sighting.

Arguments

Returns

  • {:ok, day}, the evening as an integer number of days since 0000-01-01.

  • {:error, :no_visible_crescent} if a lunation's crescent is not seen within 30 evenings of its new moon.

Raises ArgumentError for a day more than 50,000 years from J2000.

Examples

iex> mecca = %Geo.PointZ{coordinates: {39.8262, 21.4225, 277.0}}
iex> day = Date.to_gregorian_days(~D[2024-12-20])
iex> {:ok, evening} = Astro.Lunar.CrescentVisibility.first_visible_crescent_on_or_after(mecca, day, :odeh)
iex> Date.from_gregorian_days(evening)
~D[2025-01-01]

first_visible_crescent_on_or_before(location, day, method, options \\ [])

(since 2.10.0)
@spec first_visible_crescent_on_or_before(
  Geo.PointZ.t(),
  integer(),
  atom(),
  keyword()
) ::
  {:ok, integer()} | {:error, atom()}

Returns the evening of the last first sighting of a new crescent on or before an evening.

A lunation's crescent is first seen on the first evening, from the evening before the day of its new moon, on which method classes it visible. This is the latest such evening on or before day: the evening a lunar month that begins at first sighting began on.

Arguments

  • location is a Geo.PointZ.t/0 struct (already normalized).

  • day is the evening as an integer number of days since 0000-01-01.

  • method is :odeh, :yallop or :schaefer.

  • options is a keyword list of options.

Options

  • :visible is the list of categories that count as a sighting. The default is [:A, :B, :C].

  • :utc_offset and :extinction are as for the criteria.

Returns

  • {:ok, day}, the evening as an integer number of days since 0000-01-01.

  • {:error, :no_visible_crescent} if a lunation's crescent is not seen within 30 evenings of its new moon, as at high latitudes.

Raises ArgumentError for a day more than 50,000 years from J2000.

Examples

iex> mecca = %Geo.PointZ{coordinates: {39.8262, 21.4225, 277.0}}
iex> day = Date.to_gregorian_days(~D[2024-12-20])
iex> {:ok, evening} = Astro.Lunar.CrescentVisibility.first_visible_crescent_on_or_before(mecca, day, :odeh)
iex> Date.from_gregorian_days(evening)
~D[2024-12-02]

odeh_new_visible_crescent(location, moment, options \\ [])

@spec odeh_new_visible_crescent(Geo.PointZ.t(), Astro.Time.moment(), keyword()) ::
  {:ok, visibility()} | {:error, atom()}

Computes the Odeh (2004) visibility criterion for the new crescent moon.

Uses topocentric ARCV, the same polynomial family as Yallop with an updated intercept (7.1651), and enforces a Danjon limit of 6.4°.

Arguments

Returns

  • {:ok, visibility} where visibility is one of :A, :B, :C, :D, or :E.

  • {:error, :no_sunset} if no sunset occurs on the given date at the given location.

Examples

iex> mecca = %Geo.PointZ{coordinates: {39.8579, 21.3891, 0.0}}
iex> Astro.Lunar.CrescentVisibility.odeh_new_visible_crescent(mecca, Astro.Time.date_time_to_moment(~D[2024-12-02]))
{:ok, :A}
iex> Astro.Lunar.CrescentVisibility.odeh_new_visible_crescent(mecca, Astro.Time.date_time_to_moment(~D[2024-11-01]))
{:ok, :E}

schaefer_new_visible_crescent(location, moment, options \\ [])

@spec schaefer_new_visible_crescent(Geo.PointZ.t(), Astro.Time.moment(), keyword()) ::
  {:ok, visibility()} | {:error, atom()}

Computes the Schaefer (1988/2000) visibility criterion for the new crescent moon.

This physics-based model computes the contrast between the crescent moon's brightness and the twilight sky brightness, comparing against the human contrast detection threshold. The best observation time is found by scanning from sunset to moonset.

Arguments

Options

  • :extinction is the V-band zenith extinction coefficient. The default is 0.172, a clean sea-level site. Typical values are 0.12 on a high mountain, 0.17 at sea level and 0.25 in hazy conditions.

Returns

  • {:ok, visibility} where visibility is one of :A, :B, :C, :D, or :E.

  • {:error, :no_sunset} if no sunset occurs on the given date at the given location.

Examples

iex> mecca = %Geo.PointZ{coordinates: {39.8579, 21.3891, 0.0}}
iex> moment = Astro.Time.date_time_to_moment(~D[2024-12-02])
iex> Astro.Lunar.CrescentVisibility.schaefer_new_visible_crescent(mecca, moment, extinction: 0.25)
{:ok, :A}

yallop_new_visible_crescent(location, moment, options \\ [])

@spec yallop_new_visible_crescent(Geo.PointZ.t(), Astro.Time.moment(), keyword()) ::
  {:ok, visibility()} | {:error, atom()}

Computes the Yallop (1997) visibility criterion for the new crescent moon.

Uses geocentric ARCV and the polynomial fit to Bruin's visibility curves.

Arguments

Returns

  • {:ok, visibility} where visibility is one of :A, :B, :C, :D, or :E.

  • {:error, :no_sunset} if no sunset occurs on the given date at the given location.

Examples

iex> mecca = %Geo.PointZ{coordinates: {39.8579, 21.3891, 0.0}}
iex> Astro.Lunar.CrescentVisibility.yallop_new_visible_crescent(mecca, Astro.Time.date_time_to_moment(~D[2024-12-02]))
{:ok, :A}
iex> Astro.Lunar.CrescentVisibility.yallop_new_visible_crescent(mecca, Astro.Time.date_time_to_moment(~D[2024-11-01]))
{:ok, :E}