1- from __future__ import division , print_function
2-
31import os
2+ import sys
43import glob
54import datetime
6- import re
75from pathlib import Path
8- import ftplib
6+ from .generaldir import httpDir
7+ from astropy .io import fits
8+
99
1010"""
1111From the FITS file:
5050
5151
5252class clockErrData :
53- # URL is never used on David Palmer's machine (updates handled by ...swift-trend/getit)
54- # clockurl = "https://heasarc.gsfc.nasa.gov/FTP/swift/calib_data/sc/bcf/clock/"
55- clockurl = "ftps://heasarc.gsfc.nasa.gov/caldb/data/swift/mis/bcf/clock/"
56- clockhost = 'heasarc.gsfc.nasa.gov'
57- clockhostdir = '/caldb/data/swift/mis/bcf/clock/'
58- clockfile_regex = 'swclockcor20041120v\d*.fits'
53+ clockurl = "https://heasarc.gsfc.nasa.gov/FTP/swift/calib_data/sc/bcf/clock/"
54+ clockhost = "heasarc.gsfc.nasa.gov"
55+ clockhostdir = "/caldb/data/swift/mis/bcf/clock/"
56+ clockfile_regex = "swclockcor20041120v\d*.fits"
57+ clockfilepattern = "swclockcor20041120v*.fits"
5958 # FIXME this should be derived from the dotswift params
60- clocklocalsearchpath = ['/opt/data/Swift/swift-trend/clock' ,
61- os .path .expanduser ('~/.swift/swiftclock' ),
62- '/tmp/swiftclock' ]
63- clockfilepattern = 'swclockcor20041120v*.fits'
59+ clocklocalsearchpath = [
60+ "/opt/data/Swift/swift-trend/clock" ,
61+ os .path .expanduser ("~/.swift/swiftclock" ),
62+ "/tmp/swiftclock" ,
63+ ]
6464
6565 def __init__ (self ):
6666 try :
6767 self ._clockfile = self .clockfile ()
68- from astropy . io import fits
68+
6969 f = fits .open (self ._clockfile )
7070 # copies are needed to prevent pyfits from holding open a file handle for each item
71- self ._tstart = f [1 ].data .field (' TSTART' ).copy ()
72- self ._tstop = f [1 ].data .field (' TSTOP' ).copy ()
73- self ._toffset = f [1 ].data .field (' TOFFSET' ).copy ()
74- self ._c0 = f [1 ].data .field ('C0' ).copy ()
75- self ._c1 = f [1 ].data .field ('C1' ).copy ()
76- self ._c2 = f [1 ].data .field ('C2' ).copy ()
71+ self ._tstart = f [1 ].data .field (" TSTART" ).copy ()
72+ self ._tstop = f [1 ].data .field (" TSTOP" ).copy ()
73+ self ._toffset = f [1 ].data .field (" TOFFSET" ).copy ()
74+ self ._c0 = f [1 ].data .field ("C0" ).copy ()
75+ self ._c1 = f [1 ].data .field ("C1" ).copy ()
76+ self ._c2 = f [1 ].data .field ("C2" ).copy ()
7777 f .close ()
7878 except :
7979 self ._clockfile = ""
8080 raise RuntimeError ("No clock UTCF file" )
8181
82- def utcf (self , t , trow = None ): # Returns value in seconds to be added to MET to give correct UTCF
82+ def utcf (
83+ self , t , trow = None
84+ ): # Returns value in seconds to be added to MET to give correct UTCF
8385 if not self ._clockfile :
8486 return 0.0 , "No UTCF file"
8587 if trow is None :
@@ -93,9 +95,13 @@ def utcf(self, t, trow=None): # Returns value in seconds to be added to MET to
9395 else :
9496 row = row [- 1 ]
9597 if self ._tstop [row ] + caveat_time < t :
96- caveats += "Time %.1f days after clock correction interval\n " % ((t - self ._tstop [row ]) / 86400 )
98+ caveats += "Time %.1f days after clock correction interval\n " % (
99+ (t - self ._tstop [row ]) / 86400
100+ )
97101 ddays = (t - self ._tstart [row ]) / 86400.0
98- tcorr = self ._toffset [row ] + 1e-6 * (self ._c0 [row ] + ddays * (self ._c1 [row ] + ddays * self ._c2 [row ]))
102+ tcorr = self ._toffset [row ] + 1e-6 * (
103+ self ._c0 [row ] + ddays * (self ._c1 [row ] + ddays * self ._c2 [row ])
104+ )
99105 return - tcorr , caveats
100106
101107 def updateclockfiles (self , clockdir , ifolderthan_days = 30 , test_days = 1 ):
@@ -108,39 +114,44 @@ def updateclockfiles(self, clockdir, ifolderthan_days=30, test_days=1):
108114 """
109115 testfile = os .path .join (clockdir , "clocktest" )
110116 try :
111- clockfile = sorted (list (glob .glob (os .path .join (clockdir , self .clockfilepattern ))))[- 1 ]
112- age = datetime .datetime .utcnow () - datetime .datetime .fromtimestamp (os .path .getmtime (clockfile ))
117+ clockfile = sorted (
118+ list (glob .glob (os .path .join (clockdir , self .clockfilepattern )))
119+ )[- 1 ]
120+ age = datetime .datetime .utcnow () - datetime .datetime .fromtimestamp (
121+ os .path .getmtime (clockfile )
122+ )
113123 if age .total_seconds () < (86400 * ifolderthan_days ):
114124 return
115125 # Check no more than once a day
116- testage = datetime .datetime .utcnow () - datetime .datetime .fromtimestamp (os .path .getmtime (testfile ))
126+ testage = datetime .datetime .utcnow () - datetime .datetime .fromtimestamp (
127+ os .path .getmtime (testfile )
128+ )
117129 if testage .total_seconds () < (86400 * test_days ):
118130 return
119131 except :
120132 pass
121- # Requires wget. If this is a problem, use ftplib.FTP
122- # os.system(
123- # "wget -q --directory-prefix=%s --no-host --no-clobber --cut-dirs=6 -r %s"
124- # % (clockdir, self.clockurl) )
125133 try :
126- ftps = ftplib .FTP_TLS (self .clockhost )
127- ftps .login () # anonymous
128- ftps .prot_p () # for ftps
129- ftps .cwd (self .clockhostdir )
130- clockreg = re .compile (self .clockfile_regex )
131- ftplatest = sorted ([f for f in ftps .nlst () if clockreg .match (f )])[- 1 ]
132- locallatest = Path (clockdir ).joinpath (ftplatest )
133- if not locallatest .exists ():
134- with open (locallatest , "wb" ) as newfile :
135- ftps .retrbinary (f'RETR { ftplatest } ' , newfile .write )
136- open (testfile ,'w' ).write (' ' ) # touch
134+ clockremotedir = httpDir (self .clockurl )
135+ clockremote = sorted (clockremotedir .getMatches ("" , self .clockfile_regex ))[
136+ - 1
137+ ]
138+ locallatest = Path (clockdir ).joinpath (Path (clockremote ).name )
139+ clockremotedir .copyToFile (clockremote , locallatest )
140+ open (testfile , "w" ).write (" " ) # touch
137141 except Exception as e :
138142 print (e , file = sys .stdout )
139143
140-
141144 def clockfile (self ):
142145 for clockdir in self .clocklocalsearchpath :
146+ # Directory must exist and have readable clock files in it.
143147 if os .path .exists (clockdir ):
148+ try :
149+ clockfile = sorted (
150+ list (glob .glob (os .path .join (clockdir , self .clockfilepattern )))
151+ )[- 1 ]
152+ clockdata = fits .getdata (clockfile )
153+ except :
154+ continue
144155 break
145156 else :
146157 for clockdir in self .clocklocalsearchpath :
@@ -154,11 +165,15 @@ def clockfile(self):
154165 pass
155166 else :
156167 try :
157- os .makedirs (clockdir ) # Force directory to exist in the temp directory
168+ os .makedirs (
169+ clockdir
170+ ) # Force directory to exist in the temp directory
158171 except FileExistsError :
159172 pass
160173 self .updateclockfiles (clockdir )
161- clockfile = sorted (list (glob .glob (os .path .join (clockdir , self .clockfilepattern ))))[- 1 ]
174+ clockfile = sorted (
175+ list (glob .glob (os .path .join (clockdir , self .clockfilepattern )))
176+ )[- 1 ]
162177 return clockfile
163178
164179
@@ -175,9 +190,7 @@ def utcf(met, printCaveats=True, returnCaveats=False):
175190 theClockData = clockErrData ()
176191 try :
177192 uc = [theClockData .utcf (t_ ) for t_ in met ]
178- # http://muffinresearch.co.uk/archives/2007/10/16/python-transposing-lists-with-map-and-zip/
179- # Not valid after Python 2.7
180- u , c = map (None , * uc )
193+ u , c = zip (* uc )
181194 if printCaveats and any (c ):
182195 print ("\n " .join (["**** " + c_ for c_ in c if c_ ]))
183196 except TypeError :
0 commit comments