Skip to content
Snippets Groups Projects
Commit 3a097571 authored by jay's avatar jay
Browse files

Merge remote-tracking branch 'upstream/master'

parents 497dfeb1 1945670b
No related branches found
No related tags found
No related merge requests found
'''
Borrowed from Dave Pawlowski.
(http://marstiming.readthedocs.io/en/latest/_modules/marstiming.html)
Mars timing information based on MARS24: http://www.giss.nasa.gov/tools/mars24/help/algorithm.html
Contains several functions for calculating Mars time parameters from Earth time and vice versa.
Probably the most useful functions are:
getMTfromTime: gets mars time data given a 6 element time list
getSZAfromTime: gets the SZA from a 6 element time list and coordinates
getLTfromTime: gets the LTST from a 6 element time list and longitude
getUTCfromLS: Estimates the Earth time from LS and a Mars year
'''
import datetime
from numpy import pi, floor,array,shape, cos, sin,ceil,arcsin,arccos,arange,abs
from collections import namedtuple
d2R = pi/180.
def getJD(iTime):
'''Get the Julian date in seconds'''
offset = 2440587.5 #JD on 1/1/1970 00:00:00
year = iTime[0]
month = iTime[1]
day = iTime[2]
hour = iTime[3]
minute = iTime[4]
sec = iTime[5]
date = datetime.datetime(year,month,day,hour,minute,sec)
iTime = [1970,1,1,0,0,0]
year = iTime[0]
month = iTime[1]
day = iTime[2]
hour = iTime[3]
minute = iTime[4]
sec = iTime[5]
ref = datetime.datetime(year,month,day,hour,minute,sec)
deltaTime = (date-ref)
return deltaTime.total_seconds()/86400. + offset
def getUTC(jd):
'''Get UTC given jd'''
offset = 2440587.5 #JD on 1/1/1970 00:00:00
iTime = [1970,1,1,0,0,0]
year = iTime[0]
month = iTime[1]
day = iTime[2]
hour = iTime[3]
minute = iTime[4]
sec = iTime[5]
d1970 = datetime.datetime(year,month,day,hour,minute,sec)
return d1970 + datetime.timedelta(seconds=((jd-offset)*86400.))
def getJ2000(iTime):
'''get date in J2000 epoch.'''
jd = getJD(iTime)
T = (jd - 2451545.0)/36525 if iTime[0] < 1972 else 0
conversion = 64.184 + 59* T - 51.2* T**2 - 67.1* T**3 - 16.4* T**4
#convert to Terrestrial Time
jdTT = jd+(conversion/86400)
return jdTT - 2451545.0
def getMarsParams(j2000):
'''Mars time parameters'''
Coefs = array(
[[0.0071,2.2353,49.409],
[0.0057,2.7543,168.173],
[0.0039,1.1177,191.837],
[0.0037,15.7866,21.736],
[0.0021,2.1354,15.704],
[0.0020,2.4694,95.528],
[0.0018,32.8493,49.095]])
dims = shape(Coefs)
#Mars mean anomaly:
M = 19.3870 + 0.52402075 * j2000
#angle of Fiction Mean Sun
alpha = 270.3863 + 0.52403840*j2000
#Perturbers
PBS = 0
for i in range(dims[0]):
PBS += Coefs[i,0]*cos(((0.985626* j2000 / Coefs[i,1]) + Coefs[i,2])*d2R)
#Equation of Center
vMinusM = ((10.691 + 3.0e-7 *j2000)*sin(M*d2R) + 0.623*sin(2*M*d2R) +
0.050*sin(3*M*d2R) + 0.005*sin(4*M*d2R) + 0.0005*sin(5*M*d2R) + PBS)
return M, alpha, PBS, vMinusM
def getMTfromTime(iTime):
'''Get Mars time information.
:param iTime: 6 element time list [y,m,d,h,m,s]
:returns: a named tuple containing the LS value as well as
several parameters necessary for other calculations
'''
if isinstance(iTime, datetime.datetime):
iTime = [iTime.year, iTime.month, iTime.day, iTime.hour, iTime.minute, iTime.second]
DPY = 686.9713
refTime = [1955,4,11,10,56,0] #Mars year 1
rDate = getJD(refTime)
thisTime = getJD(iTime)
year = floor((thisTime - rDate)/DPY)+1
j2000 = getJ2000(iTime)
M,alpha,PBS,vMinusM = getMarsParams(j2000)
LS = (alpha + vMinusM)
while LS > 360:
LS -= 360
if LS < 0:
LS = 360. + 360.*(LS/360. - ceil(LS/360.0))
EOT = 2.861*sin(2*LS*d2R)-0.071*sin(4*LS*d2R)+0.002*sin(6*LS*d2R)-vMinusM
MTC = (24*(((j2000 - 4.5)/1.027491252)+44796.0 - 0.00096 )) % 24
subSolarLon = ((MTC+EOT*24/360.)*(360/24.)+180) % 360
solarDec = (arcsin(0.42565*sin(LS*d2R))/d2R+0.25*sin(LS*d2R))
data = namedtuple('data','ls year M alpha PBS vMinusM MTC EOT subSolarLon solarDec')
d1 = data(ls = LS,year=year,M=M,alpha=alpha,PBS=PBS,vMinusM=vMinusM,MTC=MTC,EOT=EOT,
subSolarLon=subSolarLon,solarDec=solarDec)
return d1
def getUTCfromLS(marsyear,LS):
'''Get a UTC starting with an estimate of LS using an orbit angle approximation
then iteratively closing in on the correct LS by incrementing the a day first and then hour.
:param marsyear: an int mars year
:param ls: ls- mars solar longitude
:returns: UTC1 (python datetime)'''
#Get LS to within this value:
error = 0.001
DPY = 686.9713
###Start with estimate
refTime = [1955,4,11,10,56,0] #Mars year 1
rDate = getJD(refTime)
iTime = getUTC(rDate+(marsyear-1)*DPY) #LS 0 of given mars year
#Now we have a guess, iterate over the day to get closer and closer.
thisTime = [iTime.year,iTime.month,iTime.day,iTime.hour,iTime.minute,iTime.second]
thisLS = 0
factor = 1 #do we increment up or down?
iTry = 0
dt = 60 #hours. This will get smaller as we get closer
counter = 0
olddiff = 1000.
diff = 100
while diff > error:
iTime = iTime+factor*datetime.timedelta(hours=dt)
thisTime = [iTime.year,iTime.month,iTime.day,iTime.hour,iTime.minute,iTime.second]
timedata = getMTfromTime(thisTime)
thisLS,myear = timedata.ls, timedata.year
diff = abs(thisLS - LS)
if diff > olddiff:
factor = -1*factor
counter += 1
if counter > 1:
dt = dt/60.
olddiff = diff
iTry += 1
if iTry > 1000:
print('Problem getting UTC from Ls in 2nd diff loop')
print('Quitting if function getUTCfromLS...')
exit(1)
return iTime
def getSZAfromTime(time,lon,lat):
'''Get SZA from Earth time and Mars coordinates.
:param the time: [y,m,d,h,m,s] or datetime object
:param lon: the longitude in degrees
:param lat: the latitude in degrees
:returns: the solar zenith angle (float)'''
if type(time) == datetime.datetime:
time = [time.year,time.month,time.day,time.hour,time.minute,time.second]
timedata = getMTfromTime(time)
SZA = arccos(sin(timedata.solarDec*d2R)*sin(lat*d2R)+
cos(timedata.solarDec*d2R)*cos(lat*d2R)*cos((lon-timedata.subSolarLon)*d2R))/d2R
return SZA
def SZAGetTime(sza,date, lon, lat):
'''Find the time on a given date and location when the SZA is a given value.
:param sza: Solar zenith angle in degrees
:param date: [y,m,d]<
:param lon: the longitude in degrees
:param lat: the latitude in degrees
:returns: A python datetime object
'''
thisDate = datetime.datetime(date[0],date[1],date[2])
count = 0
counter = 0
error = 1
factor = 1
dt = 15 #minutes
thisSza = getSZAfromTime(thisDate,lon,lat)
diff = abs(thisSza - sza)
while diff > error:
thisDate += factor*datetime.timedelta(minutes=dt)
thisSza = getSZAfromTime(thisDate,lon,lat)
newdiff = abs(thisSza - sza)
if newdiff > diff:
factor = -1*factor
counter += 1
if counter > 1: #Wait until counter is > 1 in case we start off going the wrong way!
dt = dt/2.
count += 1
if abs(diff - newdiff)/2. < error and counter > 5:
print('this location doesnt reach the given SZA. Returning closest value... {:f}'.format(thisSza))
return thisDate, thisSza
diff = newdiff
return thisDate, thisSza
def getLTfromTime(iTime,lon):
'''The mars local solar time from an earth time and mars longitude.
:param iTime: 6 element list: [y,m,d,h,m,s]
:param lon: the longitude in degrees
:returns: The local time (float)'''
timedata = getMTfromTime(iTime)
LMST = timedata.MTC-lon*(24/360.)
LTST = LMST + timedata.EOT*(24/360.)
return LTST
import numpy as np
import unittest
import datetime
from .. import marstime
class TestMarsTime(unittest.TestCase):
def equality_test(self):
earth = marstime.getUTCfromLS(24, 130)
mars = marstime.getMTfromTime(earth)
assert(earth.date() == marstime.getUTCfromLS(mars.year,mars.ls).date())
def test_J2000(self):
iTime = [2001,11,13,2,45,2]
testJD = marstime.getJ2000(iTime)
callibration = 58891502.000000 #test should be this value.
diff = testJD - callibration
print(testJD)
print(diff)
self.assertTrue(diff == -58890820.38465065)
def test_UTC(self):
jd = 2452226.614606
date = marstime.getUTC(jd)
callibration = datetime.datetime(2001,11,13,2,45,2)
diff = callibration - date
self.assertTrue(str(diff) == '0:00:00.041599')
def test_LS(self):
iTime = [2000,1,6,0,0,0]
lsdata = marstime.getMTfromTime(iTime)
ls = lsdata.ls
year = lsdata.year
callibration = 277.18677
diff = ls - callibration
print(diff)
self.assertAlmostEqual(diff, 0.0)
def test_SZA(self):
'''test getSZAfromTime'''
itime = [2000,1,6,0,0,0]
lon = 0.0
lat = 0.0
expected = 154.261908004
sza = marstime.getSZAfromTime(itime,lon,lat)
self.assertAlmostEqual(sza, expected)
def test_SZAGetTime(self):
out = marstime.SZAGetTime(0, [1,1,1], 0,0)
self.assertAlmostEqual(out[1], 9.454213735250395)
def test_LTfromTime(self):
'''test getLTfromTime function'''
iTime = [2000,1,6,0,0,0]
lon = 0.0
LTST = marstime.getLTfromTime(iTime,lon)
expected = 23.648468934
self.assertAlmostEqual(LTST, expected)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment