This notebook explains how to add a leap second to the leapsecond.fits file on the rare occasions that a leap second is added
References:
See the pycaldb routine update_caldb_leapsec.py for the implementation of the code below
In [1]:
from astropy.io import fits as pyfits
from astropy.time import Time
from astropy.table import Table
import ftputil
from datetime import datetime
import time
In [2]:
NewLeapSecondDate = '2017-01-01T00:00:00' # in isot format
NewLeapSecond = 1.0
In [3]:
#
# this block retrieves the lastest leapsecond file from /FTP/caldb/data/gen/bcf
# based on the leapsecond file naming convention, "leapsec_mmddyy.fits"
#
LSdir="FTP/caldb/data/gen/bcf/"
host=ftputil.FTPHost('heasarc.gsfc.nasa.gov',"anonymous","mcorcoran@usra.edu")
genbcf=host.listdir(LSdir) # get directory listing
LeapsecFileList= [f for f in genbcf if 'leapsec' in f]
LeapsecFileYear = [y.split("_")[1].split(".fits")[0][4:6] for y in LeapsecFileList]
LeapsecFileYear = [('19'+y if int(y) > 50 else '20'+y) for y in LeapsecFileYear]
LeapsecFileMonth = [m.split("_")[1].split(".fits")[0][2:4] for m in LeapsecFileList]
LeapsecFileDay = [d.split("_")[1].split(".fits")[0][0:2] for d in LeapsecFileList]
maxjd=0.0
for i in arange(len(LeapsecFileList)):
tiso=LeapsecFileYear[i]+"-"+LeapsecFileMonth[i]+"-"+LeapsecFileDay[i]
fjd = Time(tiso).jd
if fjd > maxjd:
maxjd = fjd
LatestLSF = LeapsecFileList[i]
print("Latest Leapsecond File = {0}".format(LatestLSF))
In [4]:
hdu=pyfits.open("http://heasarc.gsfc.nasa.gov/"+LSdir+"/"+LatestLSF)
In [5]:
tbdata=hdu[1].data
In [7]:
lsdate = tbdata['DATE']
lstime = tbdata['TIME']
lsmjd = tbdata['MJD'] # this is the MJD corresponding to the tabulated DATE and TIME
lssec = tbdata['SECONDS'] # elapsed seconds from MJDREF to MJD, with 1 day = 86400 seconds
lsleapsec = tbdata['LEAPSECS']
# lsmjd[0] - Time((lsdate[0]+'T'+lstime[0]).strip(), format='isot').mjd
In [8]:
test=np.asarray(lsdate)
test=np.append(lsdate,'2017')
test
Out[8]:
In [9]:
lssec
Out[9]:
In [10]:
mjdref = hdu[1].header['MJDREF']
sec = (lsmjd[26] - mjdref)*86400
print("{0:10.8e}".format(sec))
In [11]:
outfile='leapsec_'+(time.strftime("%d%m")+(time.strftime("%Y"))[2:])+'.fits'
outfile
Out[11]:
In [12]:
time.strftime('%Y-%m-%d %H:%M:%S')
Out[12]:
In [13]:
tbdata.columns
Out[13]:
In [14]:
#
# create new row for new leapsecond information
#
newdate = NewLeapSecondDate.split('T')[0]
newtime = NewLeapSecondDate.split('T')[1]
newmjd = Time(NewLeapSecondDate, format='isot').mjd
newsecs = (newmjd - mjdref)*86400
newLS = NewLeapSecond
NewLeapSecondRow=[newdate,newtime,newmjd,newsecs,newLS]
NewLeapSecondRow
Out[14]:
In [15]:
#
# append new leapsecond info to table and write to output file
#
tbdata=hdu[1].data
t=Table(tbdata) # convert hdu data to a python Table to add new row
t.add_row(NewLeapSecondRow) # add row of data
hdunew=pyfits.table_to_hdu(t) # convert table back to hdu (with minimal header)
hdunew.header=hdu[1].header # use header from original file
hdunew.header['COMMENT']='added 2016-12-31 leap sec by MFC'
hdunew.header['HISTORY']='updated by MFC 2016-07-12'
pyfits.writeto(outfile,hdunew.data,hdunew.header, clobber=True)
In [ ]:
#
# append new leapsecond info to table using FITS columns and write to output file
#
tbdata=hdu[1].data
t=Table(tbdata) # convert hdu data to a python Table to add new row
newdate = np.append(lsdate, NewLeapSecondDate.split('T')[0])
newtime = np.append(lstime, NewLeapSecondDate.split('T')[1])
newmjd = np.append(lsmjd,Time(NewLeapSecondDate, format='isot').mjd)
newsecs = np.append(lssec,newmjd - mjdref)*86400)
newLS = np.append(lsleapsec, NewLeapSecond)
t.add_row(NewLeapSecondRow) # add row of data
hdunew=pyfits.table_to_hdu(t) # convert table back to hdu (with minimal header)
hdunew.header=hdu[1].header # use header from original file
hdunew.header['COMMENT']='added 2016-12-31 leap sec by MFC'
hdunew.header['HISTORY']='updated by MFC 2016-07-12'
pyfits.writeto(outfile,hdunew.data,hdunew.header, clobber=True)
In [16]:
tbdata['DATE']
Out[16]:
In [17]:
(57204-mjdref)*86400
Out[17]:
In [18]:
(57754-mjdref)*86400
Out[18]:
In [19]:
# table_to_hdu doesn't seem to preserve the units of the column, so fix that
hdunew.columns.change_unit('LEAPSECS','s')
hdunew.columns
Out[19]:
In [29]:
def update_caldb_leapsec(NewLeapSecondDate, NewLeapSecond, updater="MFC", outdir=".", clobber=True):
"""
Given the date of a new leapsecond (for example 2017-01-01T00:00:00)
creates a new leapsecond file for transfer to the caldb
NewLeapSecDate = date of new leap second in ISOT format YYYY-MM-DDTHH:MM:SS
NewLeapSecond = amount of new leap second (usually 1.0)
writes a new FITS file to the current working directory by default
"""
from astropy.io import fits as pyfits
from astropy.time import Time
from astropy.table import Table
import ftputil
import time
#
# this block retrieves the lastest leapsecond file from /FTP/caldb/data/gen/bcf
# based on the leapsecond file naming convention, "leapsec_mmddyy.fits"
#
LSdir = "FTP/caldb/data/gen/bcf/"
host = ftputil.FTPHost('heasarc.gsfc.nasa.gov', "anonymous", "mcorcoran@usra.edu")
genbcf = host.listdir(LSdir) # get directory listing
LeapsecFileList = [f for f in genbcf if 'leapsec' in f]
LeapsecFileYear = [y.split("_")[1].split(".fits")[0][4:6] for y in LeapsecFileList]
LeapsecFileYear = [('19' + y if int(y) > 50 else '20' + y) for y in LeapsecFileYear]
LeapsecFileMonth = [m.split("_")[1].split(".fits")[0][2:4] for m in LeapsecFileList]
LeapsecFileDay = [d.split("_")[1].split(".fits")[0][0:2] for d in LeapsecFileList]
maxjd = 0.0
for i in range(len(LeapsecFileList)):
tiso = LeapsecFileYear[i] + "-" + LeapsecFileMonth[i] + "-" + LeapsecFileDay[i]
fjd = Time(tiso).jd
if fjd > maxjd:
maxjd = fjd
LatestLSF = LeapsecFileList[i]
print("Latest Leapsecond File = {0}".format(LatestLSF))
hdu = pyfits.open("http://heasarc.gsfc.nasa.gov/" + LSdir + "/" + LatestLSF) # open the file
orig_header = hdu[1].header
mjdref = orig_header['MJDREF']
UpdateDate = time.strftime('%Y-%m-%d %H:%M:%S')
#outfile = 'leapsec_' + (time.strftime("%d%m") + (time.strftime("%Y"))[2:]) + '.fits'
outfile = 'leapsec_' + NewLeapSecondDate[8:10] + NewLeapSecondDate[5:7] + NewLeapSecondDate[2:4] + '.fits'
#
# create new row for new leapsecond information
#
newdate = NewLeapSecondDate.split('T')[0]
newtime = NewLeapSecondDate.split('T')[1]
newmjd = Time(NewLeapSecondDate, format='isot').mjd
newsecs = (newmjd - mjdref) * 86400
newLS = NewLeapSecond
NewLeapSecondRow = [newdate, newtime, newmjd, newsecs, newLS]
#
# append new leapsecond to table and write to output file
#
tbdata = hdu[1].data
t = Table(tbdata) # convert hdu data to a python Table to add new row
t.add_row(NewLeapSecondRow) # add row of data
hdunew = pyfits.table_to_hdu(t) # convert table back to hdu (with minimal header)
hdunew.columns.change_unit('SECONDS', 's') # table_to_hdu doesn't seem to preserve the Unit
hdunew.columns.change_unit('LEAPSECS', 's') # table_to_hdu doesn't seem to preserve the Unit
hdunew.header = orig_header # use header from original file
hdunew.header['COMMENT'] = UpdateDate+": "+updater+" ADDED "+NewLeapSecondDate+" LEAP SECOND"
hdunew.header['HISTORY'] = "File modified by user "+updater+" on "+UpdateDate
pyfits.writeto(outdir + "/" + outfile, hdunew.data, hdunew.header, clobber=clobber, checksum=True)
return outfile
if __name__ == "__main__":
file = update_caldb_leapsec('2017-01-01T00:00:00', 1.0)
print file