py4sci

Source code for mascara.observer.coordinates

# Copyright 2014 - 2015 Anna-Lea Lesage for MASCARA
#
#    This file is part of the mascara package.
#    mascara is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    mascara is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with mascara.  If not, see <http://www.gnu.org/licenses/>.

'''
.. module: coordinates
.. Author: Anna-Lea Lesage
The coordinates module defines a set of function which are exclusively related
to coordinates conversions and coordinates updates.

:mod:`mascara.observer.coordinates` contains the functions to compute nutation and 
precession parameters. Furthermore, it also contains the functions to compute many
planetary elements (mean longitude, mean anomaly ...) for the Sun, the Earth, the
Moon and some other planets. 


'''
__version__ = '15.10.07'

### ***  Latest Changes Record  *** ###
### 17.11.2014  Corrected the sun coordinates function to deliver correct altitudes:
###             Added the JD1900 entry.
### 08.07.2015  Updated the SunAlt function to use now JD2000 instead of JD1900
### 07.10.2015  Moved the functions greenwich_mean_siderial_time, and Earth_rotation_angle
###             from Masfunct to here.
### ******************************* ###


import numpy as np
from mascara.constants import deg2as, ciras, as2rad, JD2000, JDyr

[docs]def Nutation(jd): # TESTED, WORKING ... but carefull when comparing with other results... ''' Nutation calculates for a given date the mean obliquity, the nutation longitude and the nutation obliquity according to the IAU 2000B model. The Delaunay coefficients are from Simon and al. (1994). The model is simplified to the coefficients higher than 0.05". Obliquity is calculated for J2000. Input: - scalar julian date (only one date per call) Outputs : - Obl, the obliquity of the ecliptic - psi, the nutation in the longitude of the ecliptic - eps, the nutation in the obliquity of the ecliptic All outputs are in RADIAN Comments: - The Delaunay angles are extracted from the paper of Simon and al (1994) - The nutation angles are calculated according to the formulas of the IAU2000B model which can be found in the paper of McCarthy and Luzum (2002) ''' from mascara.constants import NutationCoeff as NC # Nutation coefficients are tested and OK from numpy.polynomial.polynomial import polyval t = (jd - JD2000)/JDyr # Calculating the mean obliquity for the epoch 2000, using the coefficients # from N.Capitaine and al (2003), IAU2000 Precession Table 8, PO3. epsa = (84381.406, -46.836769, -0.0001831, 0.00200340, -0.000000576) Obl = (polyval(t, epsa))*as2rad # Defining the Delaunay angles (from Simon and al. 1994) # Mean Anomaly of the Moon (l) maM = MoonMeanAnomaly(t) # Mean anomaly of the Sun (l') maS = SunMeanAnomaly(t) # Mean elongation of the Moon (D) meM = MoonMeanElong(t)[0] # Mean argument of the latitude of the Moon (F) mlM = MoonArgLatitude(t) # Longitude of the ascending node of the Moon (Omega) Om = MoonAscendingNode(t) args = np.outer(NC.ll, maM) + np.outer(NC.lpl, maS) + np.outer(NC.Dl, meM) + \ np.outer(NC.Fl, mlM) + np.outer(NC.oml, Om) sarg = np.sin(args) carg = np.cos(args) uas2rad = 1e-7*as2rad mas2rad = 1e-3*as2rad sls = np.meshgrid(t, NC.sls)[1] cls = np.meshgrid(t, NC.cls)[1] csls = np.meshgrid(t, NC.csls)[1] ccls = np.meshgrid(t, NC.ccls)[1] DP = np.sum((sls + np.outer(NC.dsls,t))*sarg + csls*carg, axis=0) * uas2rad DE = np.sum((cls + np.outer(NC.dcls,t))*carg + ccls*sarg, axis=0) * uas2rad CDP = -0.135*mas2rad CDE = 0.388*mas2rad Dpsi = DP + CDP Deps = DE + CDE return Obl, Dpsi, Deps # in radians-> to be used with rotation matrix rotmat
[docs]def precession_matrix(jd): # TESTED WORKING very fine! ''' Precession calculates the RA and Dec coordinates changes from a reference epoch to a new epoch. Inputs: - the date, in Julian Date format Output: - the precession rotation matrix Comments: the formulas used here respected the IAU 2000 resolution. They were extracted from the paper by Capitaine and al (2003), "Expressions for IAU 2000 precession quantities" ''' from numpy.polynomial.polynomial import polyval from mascara.funcs.utils import rotmat # Convert the date to Julian century: tt = (jd - JD2000)/JDyr # The precession matrix coefficients extracted from # Capitaine and al (2003) "Precession quantities" : pzta = [2.650545, 2306.083227, 0.2988499, 0.01801828, 0.000005971, 0.0000003173] pza = [-2.650545, 2306.077181, 1.0927348, 0.01826837, -0.000028596, -0.0000002904] ptheta = [0, 2004.191903, -0.4294934, -0.04182264, -0.000007089, -0.0000001274] zta = polyval(tt,pzta)/3600 za = polyval(tt, pza)/3600 theta = polyval(tt, ptheta)/3600 Pmatrix = rotmat(-za,'z',degree=True)*rotmat(theta,'y',degree=True)*rotmat(-zta,'z',degree=True) return Pmatrix
[docs]def nutation_matrix(*args): ''' Nutation_matrix returns the rotation matrix required for the correction of the Earth's nutation effects. The angles should have been calculated via Nutation before input. The matrix is calculated according to the IAU 2000 standard, using the formulas from the USNO circular n179. Inputs: - a date (in jd or datetime format) OR - obli, the obliquity of the ecliptic - dpsi, the nutation longitude - deps, the nutation in obliquity Keywords: ? Output : Nmatrix, the nutation rotation matrix. ''' from datetime import datetime from mascara.funcs.utils import rotmat from mascara.funcs.timing import calendar2jd # If only one argument is supplied then it is probably a date, # but it could be a datetime object.... if type(args) == datetime: jd = calendar2jd(args) obli, dpsi, deps = Nutation(jd) if len(args)==1: jd = np.float64(args) obli,dpsi,deps = Nutation(jd) if len(args) == 3: obli, dpsi, deps = args Nmatrix = rotmat(-(obli+deps),'x')*rotmat(-dpsi,'z')*rotmat(obli,'x') return Nmatrix
[docs]def bias_matrix(FK5='False'): ''' A Bias matrix is required to convert from ICRS data to the dynamical mean equation and equinox J2000. Keywords: - if FK5 is true , then the bias matrix is calculated for ICRS to FK5 system, else it generates a general matrix Output: - The Bias rotation matrix between the ICRS and the J2000 frame, or the bias matrix between the GCRS and the CIO. ''' from mascara.funcs.utils import rotmat from mascara.constants import as2rad if FK5: da0 = -22.9e-3 * as2rad et0 = 9.1e-3 * as2rad nt0 = 19.9e-3 * as2rad else: da0 = -14.6e-3 * as2rad et0 = -16.6170e-3 * as2rad nt0 = -6.8192e-3 * as2rad Bmatrix = rotmat(-nt0, 'x')*rotmat(et0, 'y')*rotmat(da0,'z') return Bmatrix
def Aberration(ra, dec, jd): ''' Calculates the changes in ra and dec due to annual aberration Inputs: - ra, dec the equatorial coordinates - date, the date in Julian Date format Outputs: - sra, sdec, the corrected coordinates. ''' from mascara.constants import aber, deg2rad, rad2as jt = (jd - JD2000)/JDyr ## Calculates the Sun's coordinates at the given date. sunra, sundec, sunlon = SunCoord(jd, longitude=True) ## Calculate obliquity of the ecliptic: obli, dpsi, deps = Nutation(jd) eps0 = (23*deg2as+26.*60+21.448)-46.815*jt-0.00059*jt**2 +0.001813*jt**3 eps = (eps0+deps*rad2as)/3600*deg2rad ## Earth's orbital excentricity: Ee = EarthExcentricity(jt) ## Longitude of Perihelion: epi = EarthLongPerihelion(jt) cd = np.cos(dec * deg2rad) sd = np.sin(dec * deg2rad) ce = np.cos(eps) te = np.tan(eps) cp = np.cos(epi) sp = np.sin(epi) cs = np.cos(sunlon*deg2rad) ss = np.sin(sunlon*deg2rad) ca = np.cos(ra*deg2rad) sa = np.sin(ra*deg2rad) term1 = (ca*cs*ce+sa*ss)/cd term2 = (ca*cp*ce+sa*sp)/cd term3 = (cs*ce*(te*cd-sa*sd)+ca*sd*ss) term4 = (cp*ce*(te*cd-sa*sd)+ca*sd*sp) sra = - aber*term1+Ee*aber*term2 sdec = -aber *term3 + Ee*aber*term4 return sra/3600, sdec/3600
[docs]def greenwich_mean_sidereal_time(date, apparent=True): #TESTED WORKING ''' Calculates the GMST at the current observation date. This is the first step towards the calculation of the Local Mean Sidereal Time (LMST). The coefficients are extracted from the circular 179 of USNO. Input: - date, the date in Julian days, or in datetime format Keyword: - Apparent, if set, the program will calculate the apparement sidereal time at the given date, taking into account the Earth's nutation. Output: - the GMST in fractional hours ''' from numpy.polynomial.polynomial import polyval from mascara.constants import as2rad from mascara.funcs.timing import calendar2jd from datetime import datetime # Check what is the input format, and convert the date to JD if type(date)==datetime: jd = calendar2jd(date, UTC=True) elif type(date) == np.float64: jd = date else: raise SyntaxError('The date format is not recognized') t = (jd - JD2000)/JDyr pgmst = np.array([0.014506, 4612.156534, 1.3915817,-0.00000044, -0.000029956, -0.0000000368]) pgmst = pgmst*as2rad era = earth_rotation_angle(jd, degree=False) gmst = era + polyval(t, pgmst) if apparent: eps0, dpsi, deps = Nutation(jd) gmst = gmst + dpsi*np.cos(eps0) return (gmst*12/ np.pi)%24
def earth_rotation_angle(date, UTC=True, degree= None): # TESTED WORKING ''' Calculates the Earth Rotation Angle (ERA) at the input date. The coefficients and formula are from the circular 179 of the USNO. Input: - date, the date chosen to calculate the ERA. Either a datetime object or JD date Output: - era the earth rotation angle in term of rotation units (rad or degree) ''' from mascara.funcs.timing import calendar2jd from datetime import datetime if type(date)== datetime: jd = calendar2jd(date, UTC=UTC) else: jd=date Du = jd - JD2000 era = (0.7790572732640 + 0.00273781191135448 * Du + (Du%1.0)) %1.0 if degree == None: return era if degree == True: return era/360 if degree == False: return era*2*np.pi
[docs]def EarthExcentricity(jdc): ''' Calculates the Earth's orbital excentricity at the given date; Input: - t, the date in Julian format Ouput: - the Earth's Excentricity (no dimension) ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr ee = 0.0167086342 - 0.00004203654*jdc - 0.000000126734*jdc**2 return ee
def EarthLongPerihelion(jdc): ''' Calculates the longitude of perihelion for the Earth at the given date Input: jdc the date in Julian format Output: elp in radian ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr elp = (102.93734808*deg2as + 11612.35290*jdc + 53.27577*jdc**2)%ciras * as2rad return elp def EarthMeanLong(jdc): ''' Calculates the Mean Longitude of the Earth Input: jdc the date in Julian format Output: Earth Mean Longitude in radian ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr eml = (100.46645683*deg2as + 129597742.283429*jdc - 2.04411*jdc**2)%ciras * as2rad return eml def EarthMeanAnomaly(jdc): ''' Forms the mean anomaly term for the Earth at the given Julian date t. Input: - t, the date in Julian days Outputs: - ema, the Earth's mean anomaly in radian - ecorr, the ellipticity of the orbit in radian!! **Comments**: the correction term is calculated from the equation of centre in the Moon-Earth system ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr return SunMeanAnomaly(jdc) def MoonDistance(jdc, perturbate = True): ''' Calculates the Moon-Earth distance (in km!!!) at the given date. Input: - jd, the date in Julian format Keyword: - perturbate, if True include perturbations terms in the computatino Output: - d, the Moon-Earth distance in km!!! ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr dm = 383397.7725 + 0.0040*jdc if perturbate: D = MoonMeanElong(jdc)[0] l = MoonMeanAnomaly(jdc) lp = SunMeanAnomaly(jdc) pert = 3400.4*np.cos(2*D) - 635.6*np.cos(2*D-l) - 235.6*np.cos(l) + \ 218.1*np.cos(2*D-lp) + 181.0*np.cos(2*D+l) dm = dm + pert return dm def MoonLongPerihelion(jdc, perturbate =True): ''' Calculates the longitude of perihelion for the Moon at the given date Input: -jd, the date in Julian format Keyword: - perturbate, to compute the additional perturbation terms of the Moon's excentricity ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mlp = (83.35324312*deg2as + 14643420.2669*jdc - 38.2702*jdc**2)%ciras * as2rad if perturbate: D = MoonMeanElong(jdc)[0] l = MoonMeanAnomaly(jdc) lp = SunMeanAnomaly(jdc) ad1 = (-55609*np.sin(2*D-l) - 34711*np.sin(2*D-2*l) - 9792*np.sin(l))*as2rad ad2 = (9385*np.sin(4*D-3*l) + 7505*np.sin(4*D-2*l) + 5318*np.sin(2*D+l))*as2rad ad3 = (3484*np.sin(4*D-4*l) - 3417*np.sin(2*D-lp-l) - 2530*np.sin(6*D-4*l))*as2rad ad4 = (-2376*np.sin(2*D) - 2075*np.sin(2*D-3*l) - 1883*np.sin(2*l))*as2rad ad5 = (-1736*np.sin(6*D-5*l) + 1626*np.sin(lp) - 1370*np.sin(6*D-3*l))*as2rad mlp = mlp + ad1 + ad2 + ad3 + ad4 + ad5 return mlp def MoonExcentricity(jdc, perturbate=False): ''' Computes the excentricity of the Moon at the given date Input: -jd, the date in Julian format Keyword: - perturbate, to compute the additional perturbation terms of the Moon's excentricity Output: - Mex, the Moon's excentricity ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mex = 0.055545526-0.000000016*jdc if perturbate: D = MoonMeanElong(jdc)[0] l = MoonMeanAnomaly(jdc) lp = SunMeanAnomaly(jdc) F = MoonArgLatitude(jdc) ad1 = (0.014216*np.cos(2*D-l) + 0.008551*np.cos(2*D - 2*l) - 0.001383*np.cos(l)) ad2 = (0.001356*np.cos(2*D+l) - 0.001147*np.cos(4*D-3*l) - 0.000914*np.cos(4*D - 2*l)) ad3 = (0.000869*np.cos(2*D-lp-l)-0.000627*np.cos(2*D) - 0.000394*np.cos(4*D-4*l)) ad4 = (0.000282*np.cos(2*D-lp-2*l)-0.000279*np.cos(D-l) - 0.000236*np.cos(2*l)) ad5 = (0.000231*np.cos(4*D) + 0.000229*np.cos(6*D-4*l) - 0.000201*np.cos(2*l-2*F)) mex = mex + ad1 + ad2 + ad3 + ad4 + ad5 return mex def MoonInclination(jdc, perturbate=True): ''' computes the inclination angle of the Moon at the given date ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mincl = (5.15668983*deg2as - 0.00008*jdc)*as2rad if perturbate: D = MoonMeanElong(jdc)[0] l = MoonMeanAnomaly(jdc) lp = SunMeanAnomaly(jdc) F = MoonArgLatitude(jdc) pert = (486.26*np.cos(2*D-2*F) - 40.13*np.cos(2*D) + 37.51*np.cos(2*F) + \ 25.73*np.cos(2*l - 2*F) + 19.97*np.cos(2*D-lp-2*F))*as2rad mincl = mincl+pert return mincl def MoonArgLatitude(jdc): ###WORKING ''' Forms the Moon's argument of latitude at the given Julian date t. Input: - jdc, the Julian date (or in format (JD - JD2000)/Jdyr ) Output: - the Mean argument of latitude of the Moon Comment: the formula is from the Simon and al (1994) paper " Precession formulae and mean elements for the Moon and the planets" ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mal = (93.27209062*deg2as + 1739527262.8478*jdc -12.7512*jdc**2)%ciras * as2rad return mal def MoonAscendingNode(jdc, perturbate = True): ###WORKING ''' Calculates the longitude of the ascending node of the Moon at the given date. Input: - jdc, the Julian date perturbat Keyword: - perturbate, if True, include the perturbation terms Ouput: - the ascending node Omega Comment: From Simon and al (1994) ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr Om = (125.04455501*deg2as - 6962890.5431*jdc + 7.4722*jdc**2)%ciras * as2rad if perturbate: D = MoonMeanElong(jdc)[0] l = MoonMeanAnomaly(jdc) lp = SunMeanAnomaly(jdc) F = MoonArgLatitude(jdc) per1 = (-5392*np.sin(2*D-2*l) - 540*np.sin(lp) - 441*np.sin(2*D)+423*np.sin(2*F) - \ 288*np.sin(2*l-2*F))*as2rad Om = Om + per1 return Om
[docs]def MoonMeanAnomaly(jdc): ### WORKING ''' Forms the mean anomaly term for the Moon at the given Julian date t. Input: - t, the date dafined as (Jd - JD2000)/JDyr Ouput: - mma, the Moon's mean anomaly Comment: The formula is extracted from Simon and al (1994). ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mam = (134.96340251*deg2as + 1717915923.2178*jdc + 31.8792*jdc**2)%ciras * as2rad return mam
[docs]def MoonMeanLong(jdc, perturbate = True): ''' Defines the Mean longitude of the Moon referred to the mean equinox of the date Input: - t, the date expressed in Julian days Keyword: - perturbate, if True then include perturbation terms to the calculation of the Moon's Mean Longitude Outputs: - mml, the Moon's mean longitude ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mml = (218.31664563*deg2as + 1732564372.30470*jdc - 5.2790*jdc**2)%ciras *as2rad if perturbate: print 'perturabting' D = MoonMeanElong(jdc)[0] l = MoonMeanAnomaly(jdc) lp = SunMeanAnomaly(jdc) pert = (-3332.9*np.sin(2*D) + 1197.4*np.sin(2*D-l) - 662.5*np.sin(lp) + \ 396.3*np.sin(l) - 218.0*np.sin(2*D-lp))*as2rad mml = mml + pert return mml
[docs]def MoonMeanElong(jdc): # OK ''' Gives the mean elongation of the Moon from the Sun, and the corresponding correction term at the given date t. Input: - jdc, the date in Julian format (JD - JD2000)/JDyr Outputs: - mme, the Moon's mean elongation term - mocorr, the correction term Comment: THe formula is from the Simon and al (1994) paper "Precession formulae and mean elements for the Moon and the planets" ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mme = (297.85019547*deg2as + 1602961601.2090*jdc - 6.33706*jdc**2 + 0.006593*jdc**3)%ciras * as2rad mocorr = 6.5 * np.sin(mme) * as2rad return mme, mocorr
def SunMeanLng(jdc): ''' Defines the Sun's mean longitude for a given time t. Input: - t, the date expressed in Julian days Output: - sml, the Sun's mean longitude Comment: using the formulas in the Simon and al (1994) paper ''' from mascara.constants import deg2rad if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr sml = ((280.46645 +36000.768925*jdc+0.0003032*jdc**2)%360)*deg2rad return sml
[docs]def SunMeanAnomaly(jdc): ''' Forms the mean anomaly for the Sun at teh given Julian date t. Input: - t, the date defined as (JD - JD2000)/JDyr Output: - sma, the Sun's mean anomaly ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr sma = (357.52910918*deg2as + 129596581.0481*jdc -0.5532*jdc**2+0.000136*jdc**3)%ciras * as2rad return sma
[docs]def EquationCenter(jdc, sma): ''' Computes the equation of centre of the Sun at the given date. Input: - t the Julian date - sma the mean Anomaly Output: - stl, the equation of centre for the Sun, in RADIAN ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr # Sun's equation of center in RADIAN!!!: ee = EarthExcentricity(jdc) sec = (2*ee-0.25*ee**3)*np.sin(sma) + 5./4*ee**2*np.sin(2*sma) + 13./12 *ee**3 * np.sin(3*sma) return sec
def SunTrueLongitude(*args): ''' Calculates the True Longitude of the Sun/Earth at the given date... Input: - t, the date in Julian format - sml, the mean longitude of the Sun Output: - the True Longitude of the Sun ''' ### Number of arguments passed: if len(args) == 1: jdc = args[0] if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr sml = SunMeanLng(jdc) elif len(args) == 2: jdc, sml = args if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr ### Get the excentric anomaly sec = EquationCenter(jdc) stl = sml + sec return stl def SunTrueAnomaly(*args): ''' Calculates the True Anomaly of the Sun/Earth at the given date... Input: - t, the date in Julian format - sml, the mean longitude of the Sun Output: - the True Anomaly of the Sun ''' ### Number of arguments passed: if len(args) == 1: jdc = args[0] if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr sma = SunMeanAnomaly(jdc) elif len(args) == 2: jdc, sml = args if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr ### Get the excentric anomaly sec = EquationCenter(jdc) sta = sma + sec return sta def VenusMeanLong(jdc): ''' Forms the mean Longitude term for Venus at the given Julian date jdc Input: - jdc, in Julian days Output: - vml, Venus' mean longitude ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr vml = (181.97980085*deg2as + 2106641364*jdc + 0.59381*jdc**2)%ciras *as2rad return vml def VenusPerihelion(jdc): ''' Compute the longitude of the perihelion of Venus for the given date ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr vpe = (131.56370300*deg2as + 175.48640*jdc - 498.48184*jdc**2 - \ 20.50042*jdc**3 - 0.72432*jdc**4)%ciras * as2rad return vpe def VenusMeanAnomaly(jdc): ''' Forms the mean anomaly term for Venus at the given julian date t. Input: - jdc, in Julian days (JD - JD1900)/JDyr Output: - vma, venus's mean anomaly term in radian - vcorr, the correction term for Venus's perturbations in radian ''' from mascara.constants import deg2rad if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr vma = VenusMeanLong(jdc) - VenusPerihelion(jdc) sma = SunMeanAnomaly(jdc) vcorr = 4.8*np.cos(299.1017*deg2rad + 1.0*vma - 1.0*sma) + \ 5.5*np.cos(148.3133*deg2rad + 2.0*vma - 2.0*sma) + \ 2.5*np.cos(315.9433*deg2rad + 2.0*vma - 3.0*sma) + \ 1.6*np.cos(345.2533*deg2rad + 3.0*vma - 4.0*sma) + \ 1.0*np.cos(318.1500*deg2rad + 3.0*vma - 5.0*sma) return vma, vcorr *as2rad def JupiterPerihelion(jdc): ''' Computes the Longitude of perihelion for Jupiter at the given time ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr jpe = (14.33120687*deg2as + 7758.75163*jdc + 259.95938*jdc**2 - 16.14731*jdc**3)%ciras *as2rad return jpe def JupiterMeanLong(jdc): ''' Computes the Mean Longitude of Jupiter at the given Julian Date ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr jml = (34.35151874*deg2as + 109256603.77991*jdc - 30.60378*jdc**2)%ciras *as2rad return jml def JupiterMeanAnomaly(jdc): ''' Forms the mean anomaly term for Jupiter, and the corresponding perturbations at the given date. Input: - jdc, the date in Julian format (JD - JD1900)/JDyr Ouputs: - jma, Jupiter's mean anomaly term - jcorr, the correction term ''' from mascara.constants import deg2rad if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr jma = JupiterMeanLong(jdc) - JupiterPerihelion(jdc) ema = EarthMeanAnomaly(jdc) jcorr = 7.2*np.cos(179.5317*deg2rad - jma + ema) + \ 2.6*np.cos(263.2167*deg2rad - jma) + \ 2.7*np.cos( 87.1450*deg2rad - 2.0*jma + 2.0*ema) + \ 1.6*np.cos(109.4933*deg2rad - 2.0*jma + 1.0*ema) return jma, jcorr * as2rad def MarsPerihelion(jdc): ''' Computes the longitude of Perihelion of Mars for the given Julian date ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr mpe = (336.06023395*deg2as + 15980.45908*jdc - 62.3280*jdc**2 + 1.86464*jdc**3)%ciras *as2rad return mpe def MarsMeanLong(jdc): ''' Computes the mean longitude of Mars at the given Julian date ''' if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr maml = (355.43299958*deg2as + 689050774.93988*jdc+0.94264*jdc**2)%ciras * as2rad return maml def MarsMeanAnomaly(jdc): '''Same as above but for Mars... Input: - jdc, the date in Julian format (JD - JD1900)/JDyr ''' from mascara.constants import deg2rad if (jdc > 2e6).all(): jdc = (jdc - JD2000)/JDyr #mma = 319.529425 + ((19139.858500*jdc) %360.0) mma = MarsMeanLong(jdc) - MarsPerihelion(jdc) ema = EarthMeanAnomaly(jdc) macorr = 2.0*np.cos(343.8883*deg2rad - 2.0*mma + 2.0*ema) + \ 1.8*np.cos(200.4017*deg2rad - 2.0*mma + ema) return mma, macorr * as2rad def ComputeExcentricAnomaly(ex, ma): ''' Computes iteratively the Excentric Anomaly for the given excentricity and mean anomaly. Inputs: - ex, the excentricity - ma, the mean anomaly in RADIAN Output: - exa, the excentric anomaly ''' ### Define the ending criterion: tolerance for the iterations: endtol = 1e-3 ### First computation: E0 = ma + ex*np.sin(ma) * ( 1.+ex*np.cos(ma)) diff = np.abs(E0 - 1.) while diff > endtol: E1 = E0 - (E0 - ex * np.sin(E0)-ma)/(1.-ex*np.cos(E0)) diff = np.abs(E1-E0) E0 = E1 return E1
[docs]def SunCoord(*args, **kwargs): ''' SunCorrLng computes the corrected Sun's Mean Longitude. It takes into account the perturbation terms of Venus, Mars, Jupiter and the Moon, the mean ellipticity of the Earth, the long term variations and the abberations. Input: - t, in Julian format Outputs: - ra, dec, the Sun's coordinates at the given time. There remain some long term annual/semi-annual variations in the coordinates. These affect the ra and dec values at the most at the solstice. However the errors induced are less than one degree. The code uses the latest formulas for the mean elements of the planets. ''' from mascara.constants import rad2deg from datetime import datetime from mascara.funcs.timing import calendar2jd from mascara.funcs.utils import pol2rect, rect2pol try: t = args[0] except TypeError: print 'No input given. Input is: date in Julian Date format' return ### What is t? datetime or julian date? if isinstance(t, datetime): jd = calendar2jd(t) elif isinstance(t, np.float64): jd = t else: print 'No valid input' return jdc = (jd - JD2000)/(JDyr) longitude = kwargs.get('longitude', False) ### All these quantities are in radiants sml = np.pi + EarthMeanLong(jdc) sma = SunMeanAnomaly(jdc) sec = EquationCenter(jdc, sma) ### Sun's true longitude: stl = sml + sec # Longitude term converted to degree: if longitude: elong = stl * rad2deg ## Get the true Obliquity Obl, dpsi, deps = Nutation(t) ### And convert in ra dec ra = np.arctan2(np.cos(Obl)*np.sin(stl), np.cos(stl)) dec = np.arcsin(np.sin(Obl)*np.sin(stl)) ### Some slight correction for Precession? P = precession_matrix(jd) B = bias_matrix() X = pol2rect(ra, dec, degree=False) Y = P*B*X.T ra, dec = rect2pol(Y) if longitude: return ra, dec, elong else: return ra, dec
def MoonCoord(t, longitude=False): ''' MoonCoord computes the Moon's coordinates (right ascension and declination) at the given date. Inputs: - date, in Julian date format or datetime format Outputs: - ra, dec, the Moon's celestial coordinates at that date ''' from mascara.constants import rad2deg from datetime import datetime from mascara.funcs.timing import calendar2jd ### What is t? datetime or julian date? if isinstance(t, datetime): jd = calendar2jd(t) elif isinstance(t, np.float64): jd = t else: print 'No valid input' return jdc = (jd - JD2000)/JDyr ### Get Delaunay elements of the Moon: Dm = MoonMeanElong(jdc)[0] Fm = MoonArgLatitude(jdc) mphi = (310.17137918*deg2as - 6967051.4360*jdc + 6.2068*jdc**2)*as2rad ### Get Orbital mean elements of the Moon: mml = MoonMeanLong(jdc, perturbate=True) mincl = MoonInclination(jdc, perturbate=True) mex = MoonExcentricity(jdc, perturbate=True) mperih = MoonLongPerihelion(jdc, perturbate = True) mom = MoonAscendingNode(jdc, perturbate=True) ### Add complementary terms: mml = mml + ((2.116*np.sin(mphi)-0.111*np.sin(2*Dm-2*Fm-mphi))*jdc - \ 0.0015*np.sin(mphi)*jdc**2)*as2rad mperih = mperih + ((2.116*np.sin(mphi)-0.111*np.sin(2*Dm-2*Fm-mphi))*jdc - \ 0.0015*np.sin(mphi)*jdc**2)*as2rad mom = mom + ((-520.77*np.sin(mphi)+13.66*np.sin(2*Dm-2*Fm+mphi))*jdc*as2rad) mincl = mincl + 46.997*np.cos(mphi)*jdc*as2rad ### Compute the Mean Anomaly with the perturbation: MMA = MoonMeanAnomaly(jdc) #mml - mperih ### Compute the excenttric anomaly: MEA = ComputeExcentricAnomaly(mex, MMA) ### Compute true anomaly and distance: MTA = 2* np.arctan(np.sqrt((1-mex)/(1+mex)) * np.tan(MEA/2)) ### Compute the heliocentric ecliptic longitude and latitude hlong = np.arctan(np.tan(mperih - mom + MTA) * np.cos(mincl)) + mom hlat = np.arctan(np.sin(hlong - mom) * np.tan(mincl)) ### get orbit obliquity obl, npsi, neps = Nutation(jd) ### Convert in Ra and Dec: mra = np.arctan2(np.sin(hlong)*np.cos(obl) - np.tan(hlat)*np.sin(obl), np.cos(hlong)) mdec = np.arcsin(np.sin(hlat)*np.cos(obl) + np.cos(hlat)*np.sin(obl)*np.sin(hlong)) if longitude: return mra*rad2deg %360, mdec*rad2deg, hlong, hlat else: return mra*rad2deg %360, mdec*rad2deg