moon.py

Go to the documentation of this file.
00001 ##
00002 # 
00003 # Script to print moon phase times for a given year, which should be the
00004 # single parameter passed on the command line.  The times will be converted
00005 # to your local time by the ut_offset value, which gets added to the 
00006 # calculated universal time for the phase.  You'll want to modify the
00007 # ConvertToLocalTime() function to make its output appropriate for your
00008 # location.  You can also make it do nothing, which results in the 
00009 # program printing its times in UT.
00010 # 
00011 # Converted to python from moon.c program from June 1995.  Algorithms
00012 # from Meeus, Astronomical Formulas for Calculators, 2nd ed., 1982.
00013 # 
00014 # Copyright (C) 2002 GDS Software
00015 # 
00016 # This program is free software; you can redistribute it and/or
00017 # modify it under the terms of the GNU General Public License as
00018 # published by the Free Software Foundation; either version 2 of
00019 # the License, or (at your option) any later version.
00020 # 
00021 # This program is distributed in the hope that it will be useful,
00022 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 # GNU General Public License for more details.
00025 # 
00026 # You should have received a copy of the GNU General Public
00027 # License along with this program; if not, write to the Free
00028 # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00029 # MA  02111-1307  USA
00030 # 
00031 # See http://www.gnu.org/licenses/licenses.html for more details.
00032 # 
00033 
00034 #########################################################################
00035 
00036 from math import pi, sin, cos, floor
00037 import sys
00038 import pdb
00039 xx = pdb.set_trace
00040 
00041 NEW   = 0
00042 FIRST = 1
00043 FULL  = 2
00044 LAST  = 3
00045 RAD   = pi/180.0    # Converts degrees to radians
00046 desired_year = 0
00047 
00048 # GetJulianFromPhase  Derive the julian day number corresponding to the 
00049 # number k.  k is the integer corresponding to new moon and phase is 0 
00050 # for new, 1 for first quarter, 2 for full, and 3 for last quarter.
00051 # Returns a float.  From Meeus, pg 159.
00052 
00053 def GetJulianFromPhase(k, phase):
00054     if phase != NEW and phase != FIRST and phase != FULL and phase != LAST:
00055         raise "Illegal phase value"
00056     k1 = k + phase/4.0
00057     T = k1/1236.85
00058     T2 = T*T
00059     T3 = T2*T
00060     # Get time of mean phase
00061     julian = 2415020.75933 + 29.53058868*k1 + 1.178e-4*T2 - 1.55e-7*T3              +3.3e-4*sin(RAD*(166.56 + 132.87*T - 0.009173*T2))
00062     # Compute the corrections to get the time of true phase
00063     M      = 359.2242 + 29.10535608*k - 3.33e-5*T2 - 3.47e-6*T3
00064     Mprime = 306.0253 + 385.81691806*k + 0.0107306*T2 + 1.236e-5*T3
00065     F      = 21.2964 + 390.67050646*k - 1.6528e-3*T2 - 2.39e-6*T3
00066     # Adjust these values to the interval [0, 360] 
00067     M      = M - 360.0*(floor(M/360.0))
00068     Mprime = Mprime - 360.0*(floor(Mprime/360.0))
00069     F      = F - 360.0*(floor(F/360.0))
00070     # Convert them to radians
00071     M      = M*RAD
00072     Mprime = Mprime*RAD
00073     F      = F*RAD
00074     # Perform the corrections
00075     if phase == NEW or phase == FULL:
00076         correction = (0.1734 - 3.93e-4*T)*sin(M)                  + 0.0021*sin(2*M)                  - 0.4068*sin(Mprime)                  + 0.0161*sin(2*Mprime)                  - 0.0004*sin(3*Mprime)                  + 0.0104*sin(2*F)                  - 0.0051*sin(M+Mprime)                  - 0.0074*sin(M-Mprime)                  + 0.0004*sin(2*F+M)                  - 0.0004*sin(2*F-M)                  - 0.0006*sin(2*F+Mprime)                  + 0.0010*sin(2*F-Mprime)                  + 0.0005*sin(M+2*Mprime)
00077     else:
00078         correction = (0.1721 - 0.0004*T)*sin(M)                  + 0.0021*sin(2*M)                  - 0.6280*sin(Mprime)                  + 0.0089*sin(2*Mprime)                  - 0.0004*sin(3*Mprime)                  + 0.0079*sin(2*F)                  - 0.0119*sin(M+Mprime)                  - 0.0047*sin(M-Mprime)                  + 0.0003*sin(2*F+M)                  - 0.0004*sin(2*F-M)                  - 0.0006*sin(2*F+Mprime)                  + 0.0021*sin(2*F-Mprime)                  + 0.0003*sin(M+2*Mprime)                  + 0.0004*sin(M-2*Mprime)                  - 0.0003*sin(2*M+Mprime)
00079     julian = julian + correction
00080     if phase == FIRST:
00081         julian = julian + 0.0028 - 0.0004*cos(M) + 0.0003*cos(Mprime)
00082     if phase == LAST:
00083         julian = julian + -0.0028 + 0.0004*cos(M) - 0.0003*cos(Mprime)
00084     return julian
00085 
00086 # Returns a structure that contains the calendar date associated 
00087 # with a julian day.  The tuple is (year, month, day) where year
00088 # and month are integers; day is a float.  The julian parameter
00089 # is expected to be a float.  Ref. Meeus pg 26.
00090 
00091 def caldate(julian):
00092     julian = julian + 0.5
00093     Z = int(julian)
00094     F = julian - Z
00095     if Z < 2299161:
00096         A = Z
00097     else:
00098         alpha = int((Z-1867216.25)/36524.25)
00099         A = Z + 1 + alpha - int(alpha/4)
00100     B = A + 1524
00101     C = int((B - 122.1)/365.25)
00102     D = int(365.25*C)
00103     E = int((B - D)/30.6001)
00104     day = B - D - int(30.6001*E) + F
00105     if E < 13.5:
00106         month = int(E - 1)
00107     else:
00108         month = int(E - 13)
00109     if month > 2.5:
00110       year =  int(C - 4716)
00111     else:
00112       year =  int(C - 4715)
00113     return (year, month, day)
00114 
00115 # UnivTimeCorrect  Ref. Meeus pg 35.  Calculates the correction to ephemeris
00116 # time to get universal time.  The correction is gotten purely by his 
00117 # approximate formula; the error is a maximum of 1.2 minutes between 1710
00118 # and 1987.  
00119 
00120 def UnivTimeCorrect(year):
00121   T = (year - 1900.0)/100.0
00122   return (0.41 + 1.2053*T + 0.4992*T*T)/60.0
00123 
00124 def GetPhaseData(desired_year, phase):
00125     # Return a list of the julian days for the given year of each phase.
00126     # Start by getting a k that is in the middle of the previous year
00127     if desired_year < 1900:
00128         raise "Desired year should be > 1900"
00129     k1 = (desired_year - .5 - 1900) * 12.3685
00130     k = int(k1)
00131     done = 0
00132     data = []
00133     while not done:
00134         julian = GetJulianFromPhase(k, phase)
00135         year, month, day = caldate(julian)
00136         if year == desired_year:
00137             data.append([julian, phase])
00138         if year > desired_year:
00139             done = 1
00140         k = k + 1
00141     return data
00142 
00143 def PrintItem(julian):
00144     month_name = ["", "Jan", "Feb", "Mar", "Apr", "May",
00145            "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
00146     year, month, day = caldate(julian)
00147     Day = int(day)
00148     fraction = day - Day
00149     hours = 24.0*fraction
00150     decimal_time = hours + 12.0 + UnivTimeCorrect(year)
00151     if decimal_time > 24.0:
00152         day = day + 1
00153         decimal_time = decimal_time - 24.0
00154     minutes = int((decimal_time - int(decimal_time))*60)
00155     print "  %02d %s %02d:%02d " %         (Day, month_name[month], int(decimal_time), minutes)
00156 
00157 def main():
00158     desired_year = 2002
00159     if len(sys.argv) > 1:
00160         desired_year = int(sys.argv[1])
00161     # Get a list of the phase times in julian days.  Each element of the
00162     # list is another list containing the julian day and the phase number.
00163     results = []
00164     data = GetPhaseData(desired_year, NEW)
00165     results = results + data
00166     data = GetPhaseData(desired_year, FIRST)
00167     results = results + data
00168     data = GetPhaseData(desired_year, FULL)
00169     results = results + data
00170     data = GetPhaseData(desired_year, LAST)
00171     results = results + data
00172     # Print header
00173     print "Moon phases for", desired_year
00174     # Convert to a dictionary keyed by the phase
00175     dict = {}
00176     for result in results:
00177         julian = result[0]
00178         phase  = result[1]
00179         if dict.has_key(phase):
00180             dict[phase].append(julian)
00181         else:
00182             dict[phase] = [julian]
00183     phases = ["New", "First", "Full", "Last"]
00184     for phase in range(4):
00185         print phases[phase]
00186         for date in dict[phase]:
00187             PrintItem(date)
00188             
00189 
00190 main()
00191 
00192 

© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved; If you reference this document or any part of this document you must use the citation verbatim (including the link) "© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved."

Notice: This source code contained in this document is NOT open source and is NOT being distributed as open source.

122,241 lines of code and growing...