def spitztiming(jdstart, jdend): """ NAME: SPITZTIMING PURPOSE: This function prints a list, in Spitzer AOR format, of timing constraints. Also returns the output as a string. Originally adapted from Dr. Joe Harrington's IDL routine, spitztiming.pro. INPUTS: jdstart: Julian date of the start of the timing window (may be array). jdend: Julian date of the end of the timing window (may be array). OUTPUTS: This function returns a list of strings. Each cell of the list represents a separate constraint. SIDE EFFECTS: None. RESTRICTIONS: Numpy must be imported. Caldat must be imported. Jdstart and Jdend must both be arrays of the same shape. Each element of of jdstart must be less than the corresponding element of jdend. EXAMPLE/TEST: import numpy from julday import * from spitztiming import * print spitztiming(julday(10, 10, 2005, 2, 34, 56), julday(12, 12, 2006, 3, 45, 34) MODIFICATION HISTORY: 2008-12-29 0.1 Christopher Campo, UCF Initial version. [email protected] 2009-01-06 0.2 Christopher Campo, UCF Added support for arrays [email protected] 2009-01-06 0.3 Christopher Campo, UCF Added support for scalars [email protected] """ # default assumes input is a scalar scalar = True # check if input is an array if type(jdstart) == np.ndarray and type(jdend) == np.ndarray: scalar = False # check shape of arrays if(jdstart.shape != jdend.shape): raise TypeError, 'Error: arrays jdstart and jdend must have the same shape' else: try: # simple arithmetic test; lists and tupples do not # support this action however, and will throw an # exception. test = jdend * jdstart except: raise IOError, 'Error: input must be either scalars or arrays' dif = jdend - jdstart if scalar == False: # make sure each end date is after the start date difar = dif < 0 if(difar.all() == True): raise TypeError, 'Error: each end time must be later than corresponding start time' elif dif < 0: raise TypeError, 'Error: each end time must be later than corresponding start time' if scalar == False: # number of timing constraints to be generated ntime = jdstart.size else: ntime = 1 # the list of strings (constraints) to be returned tlist = [] # converts julian to gregorian sdate = caldat.caldat(jdstart, verbose=True) edate = caldat.caldat(jdend, verbose=True) # append the list with each timing constraint; # loops through the entire range of timing constraints. for i in range(ntime): if scalar == True: hr = np.array([sdate[3], edate[3]]) min = np.array([sdate[4], edate[4]]) sec = np.array([sdate[5], edate[5]]) else: hr = np.array([sdate[i][3], edate[i][3]]) min = np.array([sdate[i][4], edate[i][4]]) sec = np.array([sdate[i][5], edate[i][5]]) # FINDME: 7/20/2010 remove 60 seconds bug if np.round(sec[0]) == 60: min[0] += 1 sec[0] = 0 if np.round(sec[1]) == 60: min[1] += 1 sec[1] = 0 # FINDME: 7/28/2011 remove 60 minute bug if np.round(min[0]) == 60: hr[0] += 1 min[0] = 0 if np.round(min[1]) == 60: hr[1] += 1 min[1] = 0 # get start and end times stvals = (hr[0], min[0], sec[0]) etvals = (hr[1], min[1], sec[1]) stime = '%02d:%02d:%02.0f' % (stvals) etime = '%02d:%02d:%02.0f' % (etvals) if scalar == False: str_var = (i+1, sdate[i][2], sdate[i][0], sdate[i][1], stime, \ edate[i][2], edate[i][0], edate[i][1], etime) else: str_var = (i+1, sdate[2], sdate[0], sdate[1], stime, edate[2],\ edate[0], edate[1], etime) tstr = 'TIMING%d: START_DATE=%d %s %2d, START_TIME=%8s, END_DATE=%d %s %2d, END_TIME=%s' % str_var tlist.append(tstr) # the list of strings (timing constraints) return tlist
def spitztimingrep(planet, event, evphase, obsdur, startwin, obswin,\ teph, period, toff=0, ctrshift=0,\ type='ingress', errphase=0, ecldur=None): """ NAME: spitztimingrep PURPOSE: This function calculates when planetary transit and eclipse events occur within a set of observing windows. It also prints the corresponding Spitzer timing constraints in AOR format. It returns the timing constraint string list. It can also return the event mid-times with their error estimates. INPUTS: planet: String name of the planet event: String name of the event evphase: Float, in range [0,1), giving phase of event to be reported. obsdur: Duration (in seconds) of observations startwin: Duration (in seconds) of observation start-time window. obswin: [2,nwin] array of Julian dates for the start and end of each observing window. Only events within these pairs of times will be returned. teph: Passed to routine circorbphase; see that routine's header. period: Passed to routine circorbphase; see that routine's header. toff: Optional parameter; Passed to routine circorbphase; see that routine's header. ctrshift: Shift (in seconds) of event center relative to observation center. Positive shift puts more time before the event. type: Optional; the type of constraints you want returned (ingress / egress) or the mid-times (midtimes). All other inputs will return the ingress timing constraints by default. OUTPUTS: This function returns the spitzer timing constraint string for ingress or egress OR the event mid-times with error estimates. RESTRICTIONS: Numpy must be installed, and the routines circorbphase, spitztiming, and caldat must be in Python's search path. SIDE EFFECTS: None. EXAMPLE/TEST: import spitztimingrep as sptr import julday as jd import numpy as np teph = np.array([24445678.0, 0.04]) period = np.array([2.18575, 0.000003]) planet = 'mars' obswin = np.array([[jd.julday(11, 12, 2005, 15, 34, 0),\ jd.julday(12, 27, 2005, 8, 14, 0)]]) obsdur = 6 * 3600. startwin = 60. * 60. evphase = .5 event = 'secl' sptr.spitztimingrep(planet, event, evphase, obsdur, startwin, obswin, \ teph, period) NOTES: This routine is adopted from Dr. Joseph Harrington's original IDL routine, spitztimingrep.pro. MODIFICATION HISTORY: 2009-01-07 0.1 Christopher Campo, UCF Initial version [email protected] 2009-01-11 0.2 Christopher Campo, UCF Added mid-times [email protected] """ import numpy as np import circorbphase as cop import spitztiming as st import caldat as cal if ecldur == None: ecldur = obsdur - 3600. ictrshift = 0 if ctrshift != 0: ictrshift = ctrshift s2d = 1. / 86400. # conversion factor for seconds to days for i in range(len(obswin)): if i == 0: ecl = cop.circorbphase(teph, period, obswin[i][0], obswin[i][1], \ toff, evphase, errphase=errphase) else: ecl = np.concatenate((ecl, cop.circorbphase(teph, \ period, obswin[i][0], \ obswin[i][1], toff, \ evphase, errphase=errphase)), axis=1) # event mid-times with errors dates = np.array(cal.caldat(ecl[0][:]), dtype=np.float64) dates = np.transpose(dates) mon = dates[0] day = dates[1] year = dates[2] hour = dates[3] min = dates[4] sec = dates[5] uncert = ecl[1][:] * 24. * 60. * 60. mid = np.transpose([year, mon, day, hour, min, sec, \ uncert]) midtimes = 'Times of %s %s, solar-system barycenter:\n' % (planet, event) # format the string of event midtimes and errors for i in range(len(mid)): midtimes += '%4.0f %2.0f %2.0f %4.0f %2.0f %6.3f +- %10.3f sec\n' % \ (mid[i][0], mid[i][1], mid[i][2], mid[i][3], mid[i][4], mid[i][5],\ mid[i][6]) # constraints for ingress dt = np.max((ecldur/2., 2*3600.)) # ecl offset FINDME jdstart = ecl[0][:] - (dt + ictrshift + ecldur/2. + startwin / 2.) * s2d # start evnt before baseline jdend = jdstart + startwin * s2d iconst = st.spitztiming(jdstart, jdend) # constraints for egress jdstart = ecl[0][:] - (ictrshift + startwin / 2.) * s2d jdend = jdstart + startwin * s2d econst = st.spitztiming(jdstart, jdend) if type == 'midtimes': return midtimes elif type == 'egress': return econst elif type == 'ingress': return iconst