class TestHelioBaryCentric(): """ Verify time offsets to the solar system barycentre and the heliocentre. Uses the WHT observing site. Tests are against values returned at time of initial creation of these routines. They agree to an independent SLALIB based implementation to 20 microseconds. """ def setup(self): wht = EarthLocation(342.12*u.deg, 28.758333333333333*u.deg, 2327*u.m) self.obstime = Time("2013-02-02T23:00", location=wht) self.obstime2 = Time("2013-08-02T23:00", location=wht) self.obstimeArr = Time(["2013-02-02T23:00", "2013-08-02T23:00"], location=wht) self.star = SkyCoord("08:08:08 +32:00:00", unit=(u.hour, u.degree), frame='icrs') def test_heliocentric(self): hval = self.obstime.light_travel_time(self.star, 'heliocentric') assert isinstance(hval, TimeDelta) assert hval.scale == 'tdb' assert abs(hval - 461.43037870502235 * u.s) < 1. * u.us def test_barycentric(self): bval = self.obstime.light_travel_time(self.star, 'barycentric') assert isinstance(bval, TimeDelta) assert bval.scale == 'tdb' assert abs(bval - 460.58538779827836 * u.s) < 1. * u.us def test_arrays(self): bval1 = self.obstime.light_travel_time(self.star, 'barycentric') bval2 = self.obstime2.light_travel_time(self.star, 'barycentric') bval_arr = self.obstimeArr.light_travel_time(self.star, 'barycentric') hval1 = self.obstime.light_travel_time(self.star, 'heliocentric') hval2 = self.obstime2.light_travel_time(self.star, 'heliocentric') hval_arr = self.obstimeArr.light_travel_time(self.star, 'heliocentric') assert hval_arr[0]-hval1 < 1. * u.us assert hval_arr[1]-hval2 < 1. * u.us assert bval_arr[0]-bval1 < 1. * u.us assert bval_arr[1]-bval2 < 1. * u.us @pytest.mark.remote_data @pytest.mark.skipif('not HAS_JPLEPHEM') def test_ephemerides(self): bval1 = self.obstime.light_travel_time(self.star, 'barycentric') with solar_system_ephemeris.set('jpl'): bval2 = self.obstime.light_travel_time(self.star, 'barycentric', ephemeris='jpl') # should differ by less than 0.1 ms, but not be the same assert abs(bval1 - bval2) < 1. * u.ms assert abs(bval1 - bval2) > 1. * u.us
def jd2bjd(jd, RA, Dec, obs_site="Kitt Peak"): """ Convert jd into bjd https://en.wikipedia.org/wiki/Barycentric_Julian_Date https://docs.astropy.org/en/stable/time/ """ times = Time(jd, format='jd', scale='utc') c = SkyCoord(RA, Dec, unit="deg") # defaults to ICRS frame observatory = EarthLocation.of_site(obs_site) ltt_bary = times.light_travel_time(c, kind='barycentric', location=observatory) time_barycentre = times.tdb + ltt_bary # tdb: # Barycentric Dynamical Time return time_barycentre
def JD2HJD(JD,ra,dec): # JD2HJD for Kittpeak! location = EarthLocation.from_geodetic(-111.5967*u.deg, 31.9583*u.deg, 2096*u.m) kp = Observer(location=location, name="Kitt Peak",timezone="US/Arizona") # convert JD to HJD target = coord.SkyCoord(ra*u.deg,dec*u.deg, frame='icrs') #tsite = coord.EarthLocation.of_site(site) times = Time(JD, format='jd', scale='utc', location=location) ltt_helio = times.light_travel_time(target, 'heliocentric') HJD = JD+ltt_helio return HJD
def get_vhelio(mjd, coords): #Returns the heliocentric correction for an observation. Uses the Time.light_travel_time #to compute the time barycentric correction for each observation. This time is converted to a distance, #and the velocity is measured by computing this distance over 30 mins ahead/behind the observation. c = 3.e5 * u.km / u.s keck = EarthLocation(-5464487.817598869 * u.m, -2492806.5910856915 * u.m, 2151240.1945184576 * u.m) # keck=EarthLocation.of_site('keck') dt = (1. * u.hour).to(u.day) # times_array=[self.mjd-(dt.value)/2.,self.mjd+(dt.value)/2.]*u.day times_array = [mjd - (dt.value) / 2., mjd + (dt.value) / 2.] * u.day times = Time(times_array.value, format='mjd', scale='utc', location=keck) # ltt=times.light_travel_time(self.coords, 'heliocentric') ltt = times.light_travel_time(coords, 'heliocentric') dist = (c * ltt) # pdb.set_trace() vhelio = -1. * (np.diff(dist) / np.diff(times_array)).to(u.km / u.s) return vhelio.value
def utc_to_bary(t_utc, psr_coords, dish_lat=52.91, dish_long=6.87): """ Adapted from function by Mark Kennedy. Convert UTC MJD pulse arrival times to barycentric. t_utc : float or astropy Time object UTC MJD(s). If floats are given, then these are converted to astropy. psr_coords : string "00h00m00s +00d00m00s" dish_lat : float, optional Latitude (deg) of telescope. Default = LOFAR Core dish_long : float, optional Longitude (deg) of telescope. Default = LOFAR Core """ psr_coords = SkyCoord(psr_coords) telescope = EarthLocation(lat=dish_lat * u.deg, lon=dish_long * u.deg) if type(t_utc) == float or type(t_utc) == np.ndarray: t_utc = Time(t_utc, format='mjd') ltt_bary = t_utc.light_travel_time(psr_coords, location=telescope) time_bary = t_utc.tdb + ltt_bary return time_bary.mjd
def find_bjd_mid_exposure(utc_times, exposure=0, coords=None, location=None): """ Returns a numpy array of barycentric Julian date times Parameters ---------- phot_column : `astropy.table.Column` of `astropy.times.Time` or numpy array numpy array or column of observation dates/times. exposure : float; optional exposure time in seconds coords : `astropy.coordinates.SkyCoord` Ra/Dec of the object to be used for the light travel time calculation. location: `astropy.coordinates.EarthLocation` Location of the observatory. Returns ------- new_time : numpy array array of barycentric times by Julian date """ location = EarthLocation(lat=latitude, lon=longitude) ip_peg = SkyCoord(ra=[ra], dec=[dec], unit='degree') if coords is None or observatory_location is None: raise ValueError times = Time(phot_column, scale='utc', format='isot', location=location) ltt_bary = times.light_travel_time(coords) times_tdb = times.tdb time_barycenter = times_tdb + ltt_bary # adjust to midpoint of exposure bary_time = time_barycenter + exposure * u.second / 2 return bary_time.jd
def MJD2BJD(mjd, target_coord, site_location=(-105.820417,32.780361)): """do the conversion mjd -- input mjd, scale is utc target_coord -- the coordinate of the target, in astropy.coord format, to caculate the light travel time site_location -- location of the telescope, to make accurate calcualtion of light travel time and tdb conversion. Not very important here. The default value is for Greenwich Observatory. """ t = Time(mjd, format='mjd', scale='utc', location=site_location) # calculate light travel time ltt = t.light_travel_time(target_coord) # print(t, ltt) # convert t to tdb, and add light travel time # You can use JD or MJD. It's different # Maybe MJD?---BMJD t_out = (t.tdb + ltt).jd return t_out
def jd_utc_to_bjd_tdb(jd_utc, ra, dec, location='lowell'): ''' AUTHORS Patrick Tamburo, BU, June 2021 PURPOSE Converts Julian Date in UTC timescale to Barycentric Julian Date in TDB timescale. INPUTS jd_utc (float): the julian date in utc ra (str): the ra of the target (e.g., '23:06:30.0') dec (str): the ded of the target (e.g, '-05:01:57') location (str, optional): the site of observations, must match a location in the astropy .of_site json file. OUTPUTS Time in BJD TDB. TODO: None. ''' site = coord.EarthLocation.of_site(location) input_jd_utc = Time(jd_utc, format='jd', scale='utc', location=site) target = coord.SkyCoord(ra, dec, unit=(u.hourangle, u.deg), frame='icrs') ltt_bary = input_jd_utc.light_travel_time(target) return (input_jd_utc.tdb + ltt_bary).value
def _convert_to_bjd_tdb(self): """convert jd to bjd format and tdb time scale """ mjds = {} bjds = {} for band in self.bands: radius = self.radii[band][0] #any radius will do d = self.data[band][radius] #because time per radius is identical jd = Time(list(d.keys()), format='jd', scale='utc', location=oao) #mjd time format mjds[band] = jd.mjd if self.use_barycorrpy: #https://arxiv.org/pdf/1801.01634.pdf try: from barycorrpy import utc_tdb except: raise ImportError("pip install barycorrpy") #convert jd to bjd_tdb result = utc_tdb.JDUTC_to_BJDTDB(jd, ra=self.objcoord.ra.deg, dec=self.objcoord.dec.deg, lat=oao.lat.deg, longi=oao.lon.deg, alt=oao.height.value) bjds[band] = result[0] else: #BJD time format in TDB time scale bjds[band] = (jd.tdb + jd.light_travel_time(self.objcoord)).value #check difference between two time scales (should be < 8 mins!) diff = bjds[band] - 2400000.5 - mjds[band] diff_in_minutes = np.median(diff) * 24 * 60 assert diff_in_minutes < 8.4, f'{band}: {diff_in_minutes:.2} min' self.mjds = mjds self.bjds = bjds
def barycorr(self, tm, star_coord): """ Barycentric time correction. Using Astropys way of doing it. Parameters: tm (ndarray): Timestamps in TDB Julian Date (JD). star_coord (SkyCoord object): Coordinates of star. Returns: ndarray: Corrected timestamps in BJD. ndarray: Time corrections used to convert time into barycentric time in days. .. codeauthor:: Rasmus Handberg <*****@*****.**> """ tess_position = self.EarthLocation(tm) times = Time(tm, format='jd', scale='tdb', location=tess_position) # TODO: Auto-advance the coordinates of the star to the given obstime, if possible # This is currently done in prepare/BasePhotometry to the reference-time for the sector #try: # star_coord = star_coord.apply_space_motion(new_obstime=times) #except ValueError: # pass #print(star_coord) # Calculate the light time travel correction for the stars coordinates: timecorr = times.light_travel_time(star_coord, kind='barycentric', ephemeris=self.planetary_ephemeris) # Calculate the corrected timestamps: time = times.tdb + timecorr return time.jd, timecorr.value
star_coord.pm_ra_cosdec.value, star_coord.pm_dec.value, times.jd) star_coord = coord.SkyCoord(ra=ras[0], dec=decs[0], unit=u.deg, frame='icrs') #print(star_coord) # Use Greenwich as location instead of TESS (similar to what is done in Elenor): greenwich = coord.EarthLocation.of_site('greenwich') times_greenwich = Time(time_nocorr + 2457000, format='jd', scale='utc', location=greenwich) timecorr_greenwich = times_greenwich.light_travel_time( star_coord, kind='barycentric', ephemeris='builtin').value time_greenwich = time_nocorr + timecorr_greenwich #print(time_greenwich) # Calculate barycentric correction using our method: time_astropy, timecorr_astropy = knl.barycorr( time_nocorr + 2457000, star_coord) time_astropy -= 2457000 #print(time_astropy) # Plot the new barycentric time correction and the old one: ax.scatter(time_nocorr, 86400 * (ffi_time - f2(time_nocorr)), marker='.', label='FFI centre', alpha=0.5)
def bjdbrv(jd_utc, ra, dec, obsname=None, lat=0., lon=0., elevation=None, pmra=0., pmdec=0., parallax=0., rv=0., zmeas=0., epoch=2451545.0, tbase=0., **kwargs): """ Wrapper to barycorrpy.py and utc2bjd. Computes the barycentric velocity correction and julian date in one call. Keyword obsname refers to observatory.pro in the IDL Astronomy User Library See also: http://astroutils.astronomy.ohio-state.edu/exofast/barycorr.html :param jd_utc: Julian date (UTC) :param ra: RA (J2000) [deg] :param dec: Dec (J2000) [deg] :param obsname: Observatory name (overrides coordinates if set) :param lat: Observatory latitude [deg] :param lon: Observatory longitude (E) [+/-360 deg] :param elevation: Observatory elevation [m] :param pmra: Proper motion (RA*cos(Dec)) [mas/yr] :param pmdec: Proper motion (Dec) [mas/yr] :param parallax: Parallax [mas] :param rv: Radial velocity (within 100 km/s) [m/s] :param zmeas: Measured redshift :param epoch: Epoch (default 2448348.56250, J2000) :param tbase: Baseline subtracted from times (default 0.0) :return: Barycentric correction for zmeas Example: -------- >>> from brv_we14py import bjdbrv >>> print bjdbrv(2457395.24563, 4.585590721, 44.02195596, 'ca') (2457395.247062386, -23684.54364462639) """ # translation obsname_idl obsname_py if obsname=='ca': lat = 37.2236 lon = -2.5463 elevation = 2168. if obsname=='eso': #obsname = 'lasilla' lat = -29.2584 lon = -70.7345 elevation = 2400. if obsname=='lapalma': lat = 28.754000 lon = -17.88905555 elevation = 2387.2 # Barycentric Julian Date # adapted from http://docs.astropy.org/en/stable/time/#barycentric-and-heliocentric-light-travel-time-corrections targ = coord.SkyCoord(ra, dec, unit=(u.deg, u.deg), frame='icrs') loc = coord.EarthLocation.from_geodetic(lon, lat, height=elevation) #times = time.Time(jd_utc, format='jd', scale='utc', location=loc) #ltt_bary = times.light_travel_time(targ) JDUTC = Time(jd_utc, format='jd', scale='utc') if JDUTC.isscalar: ltt_bary = JDUTC.light_travel_time(targ, location=loc) # Does not work vectorised with numpy 1.14 # *** TypeError: For this input type lists must contain either int or Ellipsis # https://github.com/astropy/astropy/issues/7051 bjd = JDUTC.tdb + ltt_bary else: bjd = [(jdutc.tdb + jdutc.light_travel_time(targ, location=loc)).value for jdutc in JDUTC] brv, warning_and_error, status = barycorrpy.get_BC_vel(JDUTC, ra=ra, dec=dec, epoch=epoch, pmra=pmra, pmdec=pmdec, px=parallax, lat=lat, longi=lon, alt=elevation, **kwargs) return (bjd.value, brv[0]) if JDUTC.isscalar else (bjd, brv)
obj = coord.SkyCoord(ra, dec, 1000 / parallax, unit=(u.hourangle, u.deg, u.pc), pm_ra_cosdec=pmra * u.mas / u.yr, pm_dec=pmdec * u.mas / u.yr, obstime=pmtime, frame='fk5') newcoords = obj.apply_space_motion(interesttime) #print(newcoords) #calc light travel time times = Time(mjd, format='mjd', location=coord.EarthLocation.of_site(telescope)) ltt_bary = times.light_travel_time(newcoords, ephemeris='jpl') #eclipses are in bjd so should subtract ltt to get them in mjd mjdeclipses = eclipses - ltt_bary #eclipse_times= Time(mjdeclipses, format='jd', scale='utc') #utc_eclipses = eclipse_times.to_datetime() print('obj coords = ' + ra + ' ' + dec) print('pm corrected coords = ' + newcoords.to_string('hmsdms')) print('location = ' + telescope) print('prev obs eclipse = ' + str(t_0) + ' UTC:' + str(t.to_datetime())) print('obj period = ' + str(p) + 'd' + ' = ' + str(p * 24 * 60) + ' mins') print('entered time = ' + str(times.to_datetime())) print('light travel time = ' + str(ltt_bary)) print('next eclipses (mjd) from location = ') print(mjdeclipses[-10:])
def make_lightcurve(target_dir, stepsize, wlim, plotall=True, detector='FUV'): """ """ print("") print("===============") print("stepsize: ", stepsize) print("plotall=", plotall) print("target_dir: ", target_dir) #wlim= [1130, 1900] #3200 is the default max from what I could gather as is 915. The geocoronal emission lines are automatically excluded from the lightcurve if detector == 'FUV': band = '_a' #should be '_a', '_b', '' for the combined band images, or '*' to get all bands available (the '*' option actually causes cos.py to double-count bands) elif detector == 'NUV': band = '' else: print( "Apparently there's not a detector header...or it didn't make it into make_lightcurve()..." ) mjd_array = np.array([]) gross_array = np.array([]) flux_table = np.array([]) bkg_array = np.array([]) count_array = np.array([]) error_array = np.array([]) ferror_array = np.array([]) negative_flux_files = [] negative_means = [] if plotall: fig = plt.figure(figsize=(20, 9)) ax = fig.add_subplot(1, 1, 1) print(os.getcwd()) assembled_files = glob(target_dir + '*corrtag' + band + '.fits') for item in assembled_files: astrotable, astrometa = lc.cos.extract(item, step=stepsize, wlim=wlim) #print('astrometa: ', astrometa) mjd_array = np.append(mjd_array, astrotable['mjd']) gross_array = np.append(gross_array, astrotable['gross']) flux_table = np.append( flux_table, astrotable["flux"]) #for complete dataset mean normalization bkg_array = np.append(bkg_array, astrotable['background']) count_array = np.append(count_array, astrotable['gross'] - astrotable['background']) error_array = np.append( error_array, np.sqrt(astrotable['gross'] + astrotable['background'])) ferror_array = np.append( ferror_array, np.sqrt(astrotable['gross'] + astrotable['background']) / (astrotable['gross'] - astrotable['background']) * astrotable['flux']) #flux_table= np.append(flux_table, (astrotable["flux"]/np.nanmedian(astrotable['flux'])-1)) #for individual fits file median normalization #flux_table= np.append(flux_table, (astrotable["flux"]/np.nanmean(astrotable['flux'])-1)) #for individual fits file mean normalization print("first mjd: ", astrotable['mjd'][0]) #print("astrotable['gross']: " , astrotable['gross']) #print("astrotable['background']: ", astrotable['background']) #count_diff= astrotable['gross']-astrotable['background'] #print("difference: ", count_diff) #print("normed counts: ", np.float_(count_diff)/np.nanmean(count_diff)) print("file: ", item) print("np.nanmean(flux):", np.nanmean(astrotable['flux'])) print('-------------') if np.nanmean(astrotable['flux'] < 0.): negative_flux_files.append(item) negative_means.append(np.nanmean(astrotable['flux'])) print('===========') print("Negative flux files and means detected: ") for filename, nanmean in zip(negative_flux_files, negative_means): print("File: ", filename, "| nanmean: ", nanmean) print('===========') pre_flux = np.copy(flux_table) ferror_array = np.copy( ferror_array / flux_table ) #normalizing the error to the flux values to whatever units flux happens to be in at a given time norm_ferror_array = np.copy( ferror_array * (flux_table / np.nanmean(flux_table)) ) #making the flux error array be in scaled units to the normalized flux that's about to be calculated #it had to be done without subtracting 1 because then you'd have negative values for the errors inexplicably #this is also why it couldn't be left in arbitrary units because it would later be multiplied by the negative flux values flux_array = np.copy( flux_table / np.nanmean(flux_table) - 1. ) #normalize flux array around zero #This was the mean all norming method #flux_array = np.copy(flux_table) #this should be uncommented for the individual fits normalization #flux_array= np.copy(flux_table/np.nanmedian(flux_table)-1.) #New version as of 2017-11-30 #print("np.nanmean(flux_array)" , np.nanmean(flux_array)) #print("np.nanmean(flux_table: " ,np.nanmean(flux_table)) #print("np.sum(flux_array-pre_flux): ", np.sum(flux_array- pre_flux)) #print("np.sum(flux_array + pre_flux): ", np.sum(flux_array + pre_flux)) #print("") #print("np.nanmax(flux_array): ", np.nanmax(flux_array)) #print("mjd value for that: ", mjd_array[np.argmax(flux_array)]) #print("top 5 flux values: ", np.sort(flux_array)[-5:]) #print('mjd_array.shape: ', mjd_array.shape) #print('gross_array.shape: ', gross_array.shape) #print('flux_array.shape: ', flux_array.shape) #print("mjd_diff: ", mjd_array - np.roll(mjd_array,1)) if plotall: fig = plt.figure(figsize=(20, 9)) ax = fig.add_subplot(1, 1, 1) ax.scatter(mjd_array, gross_array) ax.set_xlabel('mjd') ax.set_ylabel('gross') ax.set_title(target_dir[:-1] + ' step= ' + str(stepsize)) fig.savefig(target_dir[:-1] + '_gross_step' + str(stepsize) + '_wlim' + str(wlim[0]) + ',' + str(wlim[1]) + '.pdf') plt.show() #plt.clf() #fig2 = plt.figure(figsize= (20,9)) #ax = fig2.add_subplot(1,1,1) #ax.axhline(y= 1, linestyle= '-', color = 'm', xmin = 0, xmax = 100000, linewidth = 1, alpha = 0.2) #ax.axhline(y= 0,linestyle = '-', color = 'g' , xmin = 0, xmax = 100000, linewidth = 1, alpha = 0.2) #ax.scatter(mjd_array, flux_array) #ax.scatter(mjd_array, pre_flux, color = 'r', alpha = 0.5) #ax.set_xlabel('mjd') #ax.set_ylabel('flux') ##plt.xlim(56921.256, 56921.258) ##ax.set_ylim(0,0.005) #plt.legend(['y=1','y = 0','normalized flux', 'not normed']) #ax.set_title(target_dir[:-1] + ' step= ' + str(stepsize)) #fig2.savefig(target_dir[:-1]+ '_flux_step' + str(stepsize)+ '_wlim'+ str(wlim[0])+',' + str(wlim[1])+ '.pdf') #plt.show() plt.title('normed') plt.hist(flux_array, bins=200) plt.show() plt.title('not normed') plt.hist(gross_array, bins=20) plt.show() else: pass #see if this is being run exernally to see if we should be gathering the lightcurves somewhere #time_sec= (mjd_array- mjd_array[0])*second_per_mjd #This needs to be changed for the times in seconds to be in terms of bmjd_tdb sub_dir, sub_file = assembled_files[0].split('/') os.chdir( sub_dir + '/' ) #change into the directory that contains the files so we can look at the header hdu = fits.open(sub_file) #look at the header os.chdir('../') #change back to the original directory we were in target_ra = hdu[0].header['RA_TARG'] #header in degrees target_dec = hdu[0].header['DEC_TARG'] #headers in degrees print("starting time corrections") target_coord = coord.SkyCoord(target_ra, target_dec, unit=(u.deg, u.deg), frame='icrs') time_mjd = Time( mjd_array, format='mjd', scale='utc', location=( 0. * u.deg, 0. * u.deg)) #assumes location at lon = 0 , lat =0, elev= sea level ltt_bary = time_mjd.light_travel_time( target_coord ) #light travel time for the target for the barycentric correction print("light travel time calculated") print("max time correction: ", np.max(np.abs(ltt_bary))) bmjd_array = (time_mjd.tdb + ltt_bary).tdb.mjd #barycentric correction time_sec = ( bmjd_array - bmjd_array[0] ) * second_per_mjd #This should correctly output the seconds times in the BMJD_tdb version #textheader= 'mjd\tgross\tflux\ttime(s)(bmjd_tdb)\tbmjd_tdb' textheader = 'mjd\tgross\tflux\ttime(s)(bmjd_tdb)\tbmjd_tdb\tbackground\tcounts\terror\tflux_error' comment_string = 'mask_deg=' + str(config.mask_deg) #20190610 textheader = comment_string + '\n' + textheader #20190610 #textcomment= 'step = ' + str(stepsize) if __name__ != "__main__": dest_dir = target_dir[:-1] + "_grid_lightcurves/" if not os.path.exists(dest_dir): os.makedirs(dest_dir) os.chdir(dest_dir) print(os.getcwd()) out_array = np.append([mjd_array], [gross_array], axis=0) out_array = np.append(out_array, [flux_array], axis=0) out_array = np.append(out_array, [time_sec], axis=0) out_array = np.append(out_array, [bmjd_array], axis=0) out_array = np.append(out_array, [bkg_array], axis=0) out_array = np.append(out_array, [count_array], axis=0) out_array = np.append(out_array, [error_array], axis=0) out_array = np.append(out_array, [norm_ferror_array], axis=0) print(out_array.shape) out_array = out_array.T print(out_array.shape) print("writing textfile") #np.savetxt(target_dir[:-1]+'_lightcurve_step' + str(stepsize)+'_wlim'+ str(wlim[0])+',' + str(wlim[1])+'.txt', out_array, delimiter = '\t', header = textheader) np.savetxt(target_dir[:-1] + '_lightcurve_step' + str(stepsize) + '_wlim' + str(wlim[0]) + ',' + str(wlim[1]) + '.txt', out_array, delimiter='\t', header=textheader) #20190610 if __name__ != '__main__': os.chdir('../') print(os.getcwd()) return "done"
frame='icrs') #star location n_start = int((tnow.jd[0] - t.jd[i]) / per[i] + 1) #Get transit number n_finish = int((tnow.jd[1] - t.jd[i]) / per[i] + 1) tmid = [] tstart = [] tend = [] for j in range(n_start, n_finish): tmid.append(t0[i] + j * per[i]) #mid transit time (BJD) tstart.append(t0[i] + j * per[i] - tdur[i] / 24.0 / 2.0) #ingress start tend.append(t0[i] + j * per[i] + tdur[i] / 24.0 / 2.0) #egress end tmid_times = Time(tmid, format='jd', scale='tdb', location=loc) tstart_times = Time(tstart, format='jd', scale='tdb', location=loc) tend_times = Time(tend, format='jd', scale='tdb', location=loc) if len(tmid_times) > 0: ltt_bary = tmid_times.light_travel_time( skycoo) #calculate light correction time. tmid_times = tmid_times + ltt_bary #apply light correction time ltt_bary = tstart_times.light_travel_time(skycoo) tstart_times = tstart_times + ltt_bary ltt_bary = tend_times.light_travel_time(skycoo) tend_times = tend_times + ltt_bary #write out table of transit times. for j in range(len(tmid_times.iso)): print(str(toiid[i]).zfill(7),"|",tmid_times.utc.iso[j],"|",tstart_times.utc.iso[j],"|",\ tend_times.utc.iso[j]) except ValueError: #index is not found. print("not found: ", toi)
class Observation: def __init__(self, celest=None, t=None, site=None, default_site='mdm', use_local_time=True, ra_unit=u.hourangle, dec_unit=u.deg): # set up the site. self.setsite(site, default_site=default_site) # set up the time. if t == None: # set to system clock if no time specified. self.t = Time(ttime.time(), format='unix') else: self.settime(t, use_local_time=use_local_time) # set up the celestial coordinates. if celest != None and celest != 'ZENITH': self.setcelest(celest) # many legal formats -- see below. else: # default to zenith self.lst = lpsidereal(self.t, self.site.location) # sidereal self.nowfr = currentFK5frame(self.t) self.celest = SkyCoord(self.lst, self.site.location.lat, frame=self.nowfr) # zenith self.cel_J2000 = self.celest.transform_to('icrs') # print("after xform, self.celest is",self.celest) self.constel = self.celest.get_constellation(short_name=True) self.previouslstmid = None self.moonpos = None # SkyCoord of moon self.moonobjang = None self.moonphasedescr = None self.moonillumfrac = None self.moonaltit = None self.moonaz = None self.lunskybright = None # approximate lunar contrib to sky # brightness at this location self.sunpos = None # SkyCoord of sun self.sunobjang = None self.sunaltit = None self.sunaz = None self.twi = None # rough magnitude difference between dark # night sky and present blue twilight contrib in zenith. self.lstmid = None self.tsunset = None self.tevetwi = None self.tnightcenter = None self.tmorntwi = None self.tsunrise = None # self.moonrise = None # self.sunrise = None self.barytcorr = None self.baryvcorr = None self.planetdict = {} # dictionary of planet SkyCoords by name. self.planetmags = {} # dictionary of planet visual mags by name. def setsite(self, site, default_site='mdm'): if isinstance(site, obs_site): self.site = site else: # sitedict = get_sites() # print "got sites; ",sitedict.keys() if site == None: if default_site != None: self.site = sitedict[default_site] # 'backup default' is mdm else: self.site = sitedict['mdm'] else: self.site = sitedict[site] def settime(self, t, use_local_time=True): # set the time self.t using the input 't'; self.t will always be # in utc. If use_local_time, then the input is assumed to be local # zone time (though if t is already a Time instance this is ignored). # Input t can be an ISO string, or a lisr tuple of at least yr, month, # day, hour, and minute. if isinstance(t, Time): self.t = t elif isinstance( t, str): # generally an ISO string like '2018-07-22 14:13:22' if use_local_time: localt = self.site.localtz.localize(dateutil.parser.parse((t))) self.t = Time(localt) else: self.t = Time(dateutil.parser.parse(t)) elif isinstance(t, tuple) or isinstance(t, list): if len(t) == 5: dtin = datetime(t[0], t[1], t[2], t[3], t[4]) else: dtin = datetime(t[0], t[1], t[2], t[3], t[4], t[5]) if use_local_time: # print "using local" localt = self.site.localtz.localize(dtin) self.t = Time(localt) else: # print "not using local" self.t = Time(dtin) elif isinstance(t, float): self.t = Time(t, format='jd') # Keep a 'pure number' version of the julian epoch. self.julyear = 2000. + (self.t - thorconsts.J2000_Time).jd / 365.25 def advancetime(self, delta, forward=True): if isinstance(delta, TimeDelta): if forward: self.t = self.t + delta else: self.t = self.t - delta elif isinstance(delta, str): # e.g., "123. or 2. d" # codes for time delta intervals, and their values in seconds. # non-obvious: 't' for 'transit' is 1 sidereal day, # 'w' is a week, 'l' is exactly 30 days -- a very rough 'lunation' that # will land on the same time of night about one month later -- and # 'y' is a 365-day 'year', again because it's more likely you want to # land on the same time of night next year than keep track over many years. t_unit_dict = { 's': 1., 'm': 60., 'h': 3600., 't': 86164.0905352, 'd': 86400, 'w': 604800., 'l': 2592000., 'y': 31536000. } x = delta.split() try: deltafloat = float(x[0]) if len(x) > 1: deltafloat = deltafloat * t_unit_dict[x[1][0]] dt = TimeDelta(deltafloat, format='sec') if forward: self.t = self.t + dt else: self.t = self.t - dt except: print("Bad time step string.") elif isinstance(delta, float): # float defaults to seconds. dt = TimeDelta(delta, format='sec') if forward: self.t = self.t + dt else: self.t = self.t - dt else: print( "Time step must be a float, an astropy TimeDelta or a string.") self.julyear = 2000. + (self.t - thorconsts.J2000_Time).jd / 365.25 def setcelest(self, celestin, ra_unit=u.hourangle, dec_unit=u.deg): """Sets the celestial coords. Input can be a SkyCoord instance, a list or tuple of (ra,dec) or (ra,dec,equinox), or a character string. If it's a character string it has to be e.g. 18:22:22.3 -0:18:33 18:22:22.3 -0:18:33 2015 18 22 22.3 -0 18 33 18 22 22.3 -0 18 33 2015 specifying "ra_unit = u.deg" will accept ras. """ if isinstance(celestin, SkyCoord): # if it's a SkyCoord, just copy it. self.celest = celestin elif isinstance(celestin, tuple) or isinstance(celestin, list): # if len(celestin) == 2: self.celest = SkyCoord(celestin[0], celestin[1], unit=(ra_unit, dec_unit)) # parse a tuple elif len(celestin) == 3: # print("celestin[2] = ",celestin[2]) eq = float(celestin[2]) if eq == 2000.: self.celest = SkyCoord(celestin[0], celestin[1], unit=(ra_unit, dec_unit)) else: eq = "J%7.2f" % (eq) self.celest = SkyCoord(celestin[0], celestin[1], unit=(ra_unit, dec_unit), frame=FK5(equinox=eq)) elif isinstance(celestin, str): # str includes unicode in python3. pieces = celest.splitin() if len(pieces ) >= 6: # space-separated fields - glue back together. rastr = pieces[0] + ":" + pieces[1] + ":" + pieces[2] decstr = pieces[3] + ":" + pieces[4] + ":" + pieces[5] if len(pieces) == 7: # if there's an equinox ... eqstr = pieces[6] else: eqstr = '2000.' else: # e.g. 21:29:36.2 so split gets ra and dec separately rastr = pieces[0] decstr = pieces[1] if len(pieces) > 2: eqstr = pieces[2] # if there's an equinox ... else: eqstr = '2000.' # print "rastr decstr eqstr",rastr,decstr,eqstr if float(eqstr) == 2000.: # default to ICRS if 2000. self.celest = SkyCoord(rastr, decstr, unit=(ra_unit, dec_unit)) else: # or set in FK5 frame of date if not 2000. eq = "J" + eqstr self.celest = SkyCoord(rastr, decstr, unit=(ra_unit, dec_unit), frame=FK5(equinox=eq)) # print(" ************ IN SETCELEST ************ ") # print( "self.celest:",self.celest) # print( "frame.name:",self.celest.frame.name) if self.celest.frame.name == 'icrs' or self.celest.frame.name == 'gcrs': self.cel_J2000 = self.celest elif self.celest.frame.name == 'precessedgeocentric': self.cel_J2000 = self.celest.transform_to('gcrs') else: self.cel_J2000 = self.celest.transform_to('icrs') # print "self.cel_J2000:",self.cel_J2000 def computesky(self, redo_coords=True): # computes lst, current-equinox coords, hour angle, alt, az, and # parang; turning off redo_coords suppresses transformation to # current equinox etc., useful for repeat calls tracing out a single # night # Also, if redo_coords is on, computes rotation matrices to # take celestial cartesian coords in ICRS directly into the # observer's topocentric frame. This speeds up such things # as the star display by a large factor. # print("entering computesksy: self.celest = ", self.celest) self.lst = lpsidereal(self.t, self.site.location) # sidereal # use these to test for 'this is the same night.' self.midnight = local_midnight_Time(self.t, self.site.localtz) self.lstmid = lpsidereal(self.midnight, self.site.location) if redo_coords: if self.celest.frame.name == 'gcrs' or self.celest.frame.name == 'precessedgeocentric': self.nowfr = currentgeocentframe(self.t) else: self.nowfr = currentFK5frame(self.t) # print("self.nowfr = ",self.nowfr) self.celnow = self.celest.transform_to(self.nowfr) self.hanow = (self.lst - self.celnow.ra).wrap_at(12. * u.hour) # hour angle (self.altit, self.az, self.parang) = altazparang(self.celnow.dec, self.hanow, self.site.location.lat) self.airmass = true_airmass(self.altit) # polynomial expansion. if redo_coords: self.constel = self.celest.get_constellation(short_name=True) # compute some convenient rotation matrices: # compute matrix for precession from J2000 (i.e., icrs almost exactly) # to now, for later use. self.icrs2now = precessmatrix(thorconsts.J2000_Time, self.t) # and matrix to rotate a current-equinox celestial xyz into topocentric self.current2topoxyz = cel2localmatrix(self.lst, self.site.location.lat) # and matrix product to rotate icrs into topocentric xyz. self.icrs2topoxyz = self.current2topoxyz.dot( self.icrs2now) # matrix product # If we're in the south, rotate by 180 degrees around vertical axis # to invert display. Simply negate top two rows of the matrix. if self.site.location.lat < 0. * u.deg: self.icrs2topoxyz = np.array([[-1], [-1], [1] ]) * self.icrs2topoxyz # print("leaving computesksy: self.celest = ", self.celest) def computebary(self): # this is a bit expensive so split off. self.baryvcorr = self.celest.radial_velocity_correction( obstime=self.t, location=self.site.location).to(u.km / u.second) # print "baryvcorr: ", self.baryvcorr.to(u.km/u.s) # print type(self.baryvcorr.to(u.km/u.s)) self.barytcorr = self.t.light_travel_time(self.celnow, kind='barycentric', location=self.site.location, ephemeris='builtin') self.tbary = self.t + self.barytcorr # print "barytcorr: ", self.barytcorr.to(u.s) # print type(self.barytcorr.to(u.s)) def computesunmoon(self): self.lst = lpsidereal(self.t, self.site.location) self.moonpos, self.moondist = accumoon(self.t, self.site.location) self.moonha = self.lst - self.moonpos.ra (self.moonaltit, self.moonaz, parang) = altazparang(self.moonpos.dec, self.moonha, self.site.location.lat) self.sunpos = lpsun(self.t) self.sunha = self.lst - self.sunpos.ra (self.sunaltit, self.sunaz, parang) = altazparang(self.sunpos.dec, self.sunha, self.site.location.lat) self.twi = ztwilight(self.sunaltit) self.sunmoonang = self.sunpos.separation(self.moonpos) self.moonillumfrac = 0.5 * (1. - np.cos(self.sunmoonang)) self.moonobjang = self.celnow.separation(self.moonpos) (self.moonphasedescr, self.lunage, self.lunation) = phase_descr(self.t.jd) # print "age %f lunation %d" % (self.lunage, self.lunation) # print "moon illum frac:",self.moonillumfrac # print "moon-obj ang:", self.moonobjang # print "moon altit",self.moonaltit,"obj altit",self.altit self.lunsky = lunskybright(self.sunmoonang, self.moonobjang, thorconsts.KZEN, self.moonaltit, self.altit, self.moondist, self.sunaltit) # print "lunsky: ",self.lunsky # print "lst",self.lst # print "moon",self.moonpos # print "moon ha, alt, az", self.moonha, self.moonaltit, self.moonaz # print "sun",self.sunpos # print "sun ha, alt, az", self.sunha, self.sunaltit, self.sunaz # print "twilight diff: " , self.twi def computeplanets(self): # print "starting planets" planetlist = [ 'mercury', 'venus', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune' ] # to get magnitudes need to get sun and earth positions too sunbary = get_body_barycentric('sun', self.t) # print 'sunbary:' # print sunbary earthbary = get_body_barycentric('earth', self.t) # print 'earthbary:' # print earthbary for p in planetlist: # get celestial position of planet self.planetdict[p] = get_body(p, self.t) # print "get_body gives",p, self.planetdict[p] # This returns a position in "GCRS: which is earth-centered. # now get sun-centered location (slightly different from bary) to get # magnitude. pbary = get_body_barycentric(p, self.t) psun = sunbary - pbary # vector from sun to planet psundist = np.sqrt(psun.x**2 + psun.y**2 + psun.z**2) # modulus pearth = earthbary - pbary # vector from planet to earth pearthdist = np.sqrt(pearth.x**2 + pearth.y**2 + pearth.z**2) # for inner planets, use polynomials for the phase angle dependence, # which is not at all trivial. if p == 'mercury' or p == 'venus' or p == 'mars': # angle between sun and earth as viewed from planet phaseang = angle_between(psun, pearth) # print "phaseang:",phaseang phasefac = np.polyval(thorconsts.PLANETPHASECOEFS[p], phaseang) # print "phasefac:",phasefac self.planetmags[p] = phasefac + 5. * np.log10( psundist.to(u.AU).value * pearthdist.to(u.AU).value) # print "mag:",self.planetmags[p] # outer planets are close enough to phase zero all the time to ignore the phase angle. else: phasefac = thorconsts.PLANETPHASECOEFS[p] self.planetmags[p] = phasefac + 5. * np.log10( psundist.to(u.AU).value * pearthdist.to(u.AU).value) # print "mag:",self.planetmags[p] # saturn will not be good because there's no ring-tilt dependence factored in. fr = currentgeocentframe(self.t) #print "frame attributes:",fr.get_frame_attr_names() # print """ #after transformation: # """ # we want these in equinox of date for plotting. They'll be # converted back to J2000 for the table when the coordinates are loaded # into the observation instance. for p in planetlist: self.planetdict[p] = self.planetdict[p].transform_to(fr) # print p, self.planetdict[p].to_string('hmsdms') # print "ending planets" def setnightevents(self, do_hours_up=True): """Compute the events (sunset etc) for a single night. Optionally compute the number of hours an object is up. """ # self.midnight also computed in computesky, but it's cheap. self.midnight = local_midnight_Time(self.t, self.site.localtz) self.lstmid = lpsidereal(self.midnight, self.site.location) # if you're looking at the same night, from the same site, # lst mid will be the same. Don't bother with the calculation if self.previouslstmid != None: if abs(self.previouslstmid - self.lstmid) < 0.001 * u.deg: # print "no night event calc'n -- same." return sunmid = lpsun(self.midnight) # sunrise and sunset altitudes are complicated and initialized # with the site for efficiency's sake. Twilight altitude is # fixed at -18 degrees, so not costly to set it here. twialt = Angle(-18., unit=u.deg) twialt12 = Angle(-12., unit=u.deg) # Compute sunset, sunrise, and twilight times. # Start by computing the approximate hour angles at which these # occur, for the dec that the sun has at midnight. # for this purpose, wrap hour angles at noon so that all for a given night # are positive # Find hour angle at which the dec of the sun (evaluated at # local midnight) rises or sets sunsetha = ha_alt(sunmid.dec, self.site.location.lat, self.site.setalt) # If the dec of the sun never rises or sets -- possible in the arctic -- set # flags for later use; "0" is normal, it rises and sets, "1" is it's always # up (midnight sun) and "-1" is it never rises. if sunsetha > (500. * u.rad): self.sunsetflag = 1 # sun always up elif sunsetha < (-500. * u.rad): self.sunsetflag = -1 # sun never rises or sets else: self.sunsetflag = 0 sunriseha = Angle(2. * np.pi, unit=u.rad) - ha_alt( sunmid.dec, self.site.location.lat, self.site.risealt) twilightha = ha_alt(sunmid.dec, self.site.location.lat, twialt) # positive, correct for evening # print "sunsetha, sunriseha, twilightha",sunsetha,sunriseha,twilightha # Again, set flag in case twilight never ends (high-latitude summer) or the sun doesn't get # higher than -18 degrees if twilightha > (500. * u.rad): self.twilightflag = 1 # never gets dark elif twilightha < (-500. * u.rad): self.twilightflag = -1 # fully dark all night (only happens near pole and solstice) else: self.twilightflag = 0 # do the same for 12-degree twilight; with the sun between 12 and 18 degrees below the horizon the # sky is fairly dark and one can work on brighter object, standard stars and so on. twilight12ha = ha_alt(sunmid.dec, self.site.location.lat, twialt12) # positive, correct for evening if twilight12ha > (500. * u.rad): self.twilight12flag = 1 # never gets dark elif twilight12ha < (-500. * u.rad): self.twilight12flag = -1 # fully dark all night (only happens near pole and solstice) else: self.twilight12flag = 0 hasunmid = (self.lstmid - sunmid.ra).wrap_at(24. * u.hour) #print "hasunmid:",hasunmid #print "midnight",self.midnight self.tnightcenter = self.midnight - TimeDelta( hasunmid.hour / 24. - 0.5, format='jd') #self.lstnightcenter = lpsidereal(self.tnightcenter,self.site.location) #print 'night center',self.nightcenter if self.sunsetflag == 0: # if dec of sun is such that sunset and sunrise occur sunsetguess = hasunmid - sunsetha # hour angle difference from sun's posn at midnight sunriseguess = sunriseha - hasunmid if self.twilightflag == 0: evetwiguess = hasunmid - twilightha morntwiguess = Angle(2. * np.pi, unit=u.rad) - twilightha - hasunmid if self.twilight12flag == 0: evetwi12guess = hasunmid - twilight12ha morntwi12guess = Angle(2. * np.pi, unit=u.rad) - twilight12ha - hasunmid #print "sunsetguess, sunriseguess",sunsetguess,sunriseguess.hour #print "eve, morn",evetwiguess,morntwiguess.hour # convert to time differences if self.sunsetflag == 0: TDsunset = TimeDelta(sunsetguess.hour / 24., format='jd') TDsunrise = TimeDelta(sunriseguess.hour / 24., format='jd') #print "tdsunset, tdsunrise",TDsunset,TDsunrise if self.twilightflag == 0: TDevetwi = TimeDelta(evetwiguess.hour / 24., format='jd') TDmorntwi = TimeDelta(morntwiguess.hour / 24., format='jd') #print "TDeve, TDmorn",TDevetwi,TDmorntwi if self.twilight12flag == 0: TDevetwi12 = TimeDelta(evetwi12guess.hour / 24., format='jd') TDmorntwi12 = TimeDelta(morntwi12guess.hour / 24., format='jd') # form into times and iterate to accurate answers. if self.sunsetflag == 0: self.tsunset = self.midnight - TDsunset # first approx #print "first approx",self.tsunset self.tsunset = jd_sun_alt(self.site.setalt, self.tsunset, self.site.location) self.tsunrise = self.midnight + TDsunrise # first approx #print "first approx",self.tsunrise self.tsunrise = jd_sun_alt(self.site.risealt, self.tsunrise, self.site.location) if self.twilightflag == 0: self.tevetwi = self.midnight - TDevetwi self.tevetwi = jd_sun_alt(twialt, self.tevetwi, self.site.location) self.tmorntwi = self.midnight + TDmorntwi self.tmorntwi = jd_sun_alt(twialt, self.tmorntwi, self.site.location) if self.twilight12flag == 0: self.tevetwi12 = self.midnight - TDevetwi12 self.tevetwi12 = jd_sun_alt(twialt12, self.tevetwi12, self.site.location) #self.lsteve12 = lpsidereal(self.tevetwi12,self.site.location) self.tmorntwi12 = self.midnight + TDmorntwi12 self.tmorntwi12 = jd_sun_alt(twialt12, self.tmorntwi12, self.site.location) #self.lstmorn12 = lpsidereal(self.tmorntwi12,self.site.location) # and, moonrise and set times for that night. moonmid = lpmoon(self.midnight, self.site.location) hamoonmid = self.lstmid - moonmid.ra hamoonmid.wrap_at(12. * u.hour, inplace=True) #print "moon at midnight",moonmid #print "hamoonmid: ",hamoonmid.hour, 'hr' roughlunarday = TimeDelta(1.0366, format='jd') moonsetha = ha_alt(moonmid.dec, self.site.location.lat, self.site.setalt) # Using the midnight position of the moon to assess whether it actually # rises or sets in a 12-hour window around that time is problematic, # since the moon's dec can move pretty quickly. This is a rare 'corner # case' that only matters at very high latitudes so I'm not going to worry # about it too much. if moonsetha > (500. * u.rad): self.moonsetflag = 1 # moon always up elif moonsetha < (-500. * u.rad): self.moonsetflag = -1 # moon always below horizon else: self.moonsetflag = 0 moonsetdiff = moonsetha - hamoonmid # how far from setting at midnight # find nearest setting point if moonsetdiff.hour >= 12.: moonsetdiff = moonsetdiff - Angle(24. * u.hour) if moonsetdiff.hour < -12.: moonsetdiff = moonsetdiff + Angle(24. * u.hour) TDmoonset = TimeDelta(moonsetdiff.hour / 24., format='jd') self.tmoonset = self.midnight + TDmoonset #print "moonset first approx:",self.tmoonset #print "aiming for set alt = ",self.site.setalt self.tmoonset = jd_moon_alt(self.site.setalt, self.tmoonset, self.site.location) #print "moonset: ",self.tmoonset # .to_datetime(timezone = localtzone) moonriseha = -1. * ha_alt(moonmid.dec, self.site.location.lat, self.site.risealt) # signed moonrisediff = moonriseha - hamoonmid # how far from riseting point at midn. # find nearest riseing point if moonrisediff.hour >= 12.: moonrisediff = moonrisediff - Angle(24. * u.hour) if moonrisediff.hour < -12.: moonrisediff = moonrisediff + Angle(24. * u.hour) TDmoonrise = TimeDelta(moonrisediff.hour / 24., format='jd') self.tmoonrise = self.midnight + TDmoonrise #print "moonrise first approx:",self.tmoonrise #print "aiming for rise alt = ",self.site.risealt self.tmoonrise = jd_moon_alt(self.site.risealt, self.tmoonrise, self.site.location) #print "moonrise: ",self.tmoonrise # .to_datetime(timezone = localtzone) # Save this to avoid re-doing unnecessarily. If lstmid is exactly the same, # then the night and location are almost certainly unchanged. self.previouslstmid = self.lstmid def compute_hours_up( self): # involves night events but is specific to this object. # this requires setnightevents to have been run for the same night. minalt, maxalt = min_max_alt(self.site.location.lat, self.celnow.dec) if self.twilight12flag == 0: self.ha_mid = (self.lstmid - self.celnow.ra).wrap_at(12. * u.hour) #print("self.ha_mid.value",self.ha_mid.value) #print("self.ha_mid.hourangle",self.ha_mid.hourangle) deltattran = TimeDelta(self.ha_mid.hourangle / 24., format='jd') / 1.0027379093 self.ttransit = self.midnight - deltattran #print("self.midnight = ",self.midnight) #print("self.ttransit = ",self.ttransit) if minalt < thorconsts.ALT30 and maxalt > thorconsts.ALT30: # if this dec passes through 3 airmasses ha30 = ha_alt(self.celnow.dec, self.site.location.lat, thorconsts.ALT30) dt30 = TimeDelta(ha30.hourangle / 24., format='jd') / 1.0027379093 jd30_1 = self.ttransit - dt30 # Time of rise through 3 airmasses jd30_2 = self.ttransit + dt30 # Time of set past 3 airmasses # print("jd30_1 = ",jd30_1) # print("jd30_2 = ",jd30_2) self.uptime30 = hrs_up(jd30_1, jd30_2, self.tevetwi12, self.tmorntwi12) elif minalt > thorconsts.ALT30: self.uptime30 = (self.tmorntwi12 - self.tevetwi12) elif maxalt < thorconsts.ALT30: self.uptime30 = thorconsts.ZERO_TIMEDELTA #print("time above 3 airm", self.uptime30) if minalt < thorconsts.ALT20 and maxalt > thorconsts.ALT20: # if it passes through 2 airmass ha20 = ha_alt(self.celnow.dec, self.site.location.lat, thorconsts.ALT20) dt20 = TimeDelta(ha20.hourangle / 24., format='jd') / 1.0027379093 jd20_1 = self.ttransit - dt20 jd20_2 = self.ttransit + dt20 self.uptime20 = hrs_up(jd20_1, jd20_2, self.tevetwi12, self.tmorntwi12) elif minalt > thorconsts.ALT20: self.uptime20 = (self.tmorntwi12 - self.tevetwi12) elif maxalt < thorconsts.ALT20: self.uptime20 = thorconsts.ZERO_TIMEDELTA #print("time above 2 airm", self.uptime20) if minalt < thorconsts.ALT15 and maxalt > thorconsts.ALT15: # if it passes through 1.5 airmasses ha15 = ha_alt(self.celnow.dec, self.site.location.lat, thorconsts.ALT15) dt15 = TimeDelta(ha15.hourangle / 24., format='jd') / 1.0027379093 jd15_1 = self.ttransit - dt15 jd15_2 = self.ttransit + dt15 self.uptime15 = hrs_up(jd15_1, jd15_2, self.tevetwi12, self.tmorntwi12) elif minalt > thorconsts.ALT15: self.uptime15 = (self.tmorntwi12 - self.tevetwi12) elif maxalt < thorconsts.ALT15: self.uptime15 = thorconsts.ZERO_TIMEDELTA #print("time above 1.5 airm", self.uptime15) def printnow(self): # prints a nicely formatted display of the instantaneous circumstances. # first ensure that they're up to date ... self.computesky() self.computesunmoon() self.computeplanets() self.computebary() print(" ") print("Site : %s; E longit = %s, lat = %s" % (self.site.name, self.site.location.lon.to_string(unit=u.deg, sep=' '), self.site.location.lat.to_string(unit=u.deg, sep=' '))) print(" ") print(" J2000: %s %s (in %s)" % (self.cel_J2000.ra.to_string( unit=u.hourangle, sep=' ', precision=2, pad=True), self.cel_J2000.dec.to_string( sep=' ', precision=1, pad=True, alwayssign=True), self.constel)) eqout = self.t eqout.format = "jyear_str" print("%s : %s %s" % (eqout.value, self.celnow.ra.to_string( unit=u.hourangle, sep=' ', precision=2, pad=True), self.celnow.dec.to_string( sep=' ', precision=1, pad=True, alwayssign=True))) print(" ") ut = self.t.to_datetime() local = self.t.to_datetime(timezone=self.site.localtz) # localdow = dows[datetime.weekday()] print("UT date and time : %s JD %s " % (ut.strftime("%a %Y-%m-%d %H:%M:%S"), self.t.jd)) print("local date and time : %s" % (local.strftime("%a %Y-%m-%d %H:%M:%S"))) print(" ") print("Local mean sidereal time: %s " % (self.lst.to_string(unit=u.hourangle, sep=' ', precision=0))) print(" ") parang_opposite = self.parang + Angle(180 * u.deg) parang_opposite.wrap_at(180. * u.deg) print("Hour angle: %s AltAz: %5.1f, %6.1f Parallactic: %4.1f [%4.1f]" % \ (self.hanow.to_string(unit = u.hourangle, sep = ' ', precision = 0, pad = True, alwayssign = True), self.altit.deg, self.az.deg, self.parang.deg, parang_opposite.deg)) if self.altit < 0.: print("Below horizon.") elif self.airmass > 10.: print("Airmass > 10.") else: print("Airmass: %6.3f" % (self.airmass)) print(" ") print("Moon: %s Alt,Az %4.1f, %4.1f" % (self.moonphasedescr, self.moonaltit.deg, self.moonaz.deg)) if self.moonaltit > 0.: # give more detail on the moon if it's up. print("Moon ra and dec: %s %s (%s)" % (self.moonpos.ra.to_string( unit=u.hourangle, sep=' ', precision=0, pad=True), self.moonpos.dec.to_string( sep=' ', fields=2, pad=True, alwayssign=True), eqout.value)) print("Illum. fract : %5.3f Moon-obj ang: %5.1f deg" % (self.moonillumfrac, self.moonobjang.deg)) if self.lunsky != 99.: print("Lunar sky brightness %4.1f mag/sq arcsec" % (self.lunsky)) else: print("The moon is down. ") print(" ") if self.sunaltit.deg < -18.: print("The sun is down; there is no twilight.") elif self.sunaltit.deg < 0.: print("In twilight; sky %4.1f mag brighter than dark sky." % self.twi) else: print("THE SUN IS UP.") print("Sun RA and dec: %s %s (%s); AltAz %4.1f, %5.1f" % (self.sunpos.ra.to_string( unit=u.hourangle, sep=' ', precision=1, pad=True), self.sunpos.dec.to_string( sep=' ', precision=0, pad=True, alwayssign=True), eqout.value, self.sunaltit.deg, self.sunaz.deg)) print(" ") print("Barycentric corrns: add %7.2f sec and %6.2f km/s to observed." % \ (self.barytcorr.to(u.s).value,self.baryvcorr.to(u.km/u.s).value)) print("Barycentric JD (UTC system): %14.5f." % (self.tbary.jd)) def printnight(self, use_local_time=True): # Prints a nicely formatted display of the rise/set times. self.setnightevents() if use_local_time: tz = self.site.localtz print("Night events; times listed are local.\n") else: tz = None print("Night events; times listed are UT.\n") sunset = self.tsunset.to_datetime(timezone=tz) print(" Sunset: %s" % (time_rounded_to_minute(sunset, incl_date=True, incl_day=True))) endtwi = self.tevetwi.to_datetime(timezone=tz) print(" Twilight Ends: %s" % (time_rounded_to_minute(endtwi, incl_date=True, incl_day=True))) nghtctr = self.tnightcenter.to_datetime(timezone=tz) print("Center of Night: %s" % (time_rounded_to_minute(nghtctr, incl_date=True, incl_day=True))) begtwi = self.tmorntwi.to_datetime(timezone=tz) print("Twilight Begins: %s" % (time_rounded_to_minute(begtwi, incl_date=True, incl_day=True))) sunrise = self.tsunrise.to_datetime(timezone=tz) print(" Sunrise: %s" % (time_rounded_to_minute(sunrise, incl_date=True, incl_day=True))) print(" ") moonrise = self.tmoonrise.to_datetime(timezone=tz) moonset = self.tmoonset.to_datetime(timezone=tz) if self.tmoonrise < self.tmoonset: print(" Moonrise: %s" % (time_rounded_to_minute( moonrise, incl_date=True, incl_day=True))) print(" Moonset: %s" % (time_rounded_to_minute( moonset, incl_date=True, incl_day=True))) else: print(" Moonset: %s" % (time_rounded_to_minute( moonset, incl_date=True, incl_day=True))) print(" Moonrise: %s" % (time_rounded_to_minute( moonrise, incl_date=True, incl_day=True)))
class TestHelioBaryCentric: """ Verify time offsets to the solar system barycentre and the heliocentre. Uses the WHT observing site. Tests are against values returned at time of initial creation of these routines. They agree to an independent SLALIB based implementation to 20 microseconds. """ @classmethod def setup_class(cls): cls.orig_auto_download = iers.conf.auto_download iers.conf.auto_download = False @classmethod def teardown_class(cls): iers.conf.auto_download = cls.orig_auto_download def setup(self): wht = EarthLocation(342.12 * u.deg, 28.758333333333333 * u.deg, 2327 * u.m) self.obstime = Time("2013-02-02T23:00", location=wht) self.obstime2 = Time("2013-08-02T23:00", location=wht) self.obstimeArr = Time(["2013-02-02T23:00", "2013-08-02T23:00"], location=wht) self.star = SkyCoord("08:08:08 +32:00:00", unit=(u.hour, u.degree), frame='icrs') def test_heliocentric(self): hval = self.obstime.light_travel_time(self.star, 'heliocentric') assert isinstance(hval, TimeDelta) assert hval.scale == 'tdb' assert abs(hval - 461.43037870502235 * u.s) < 1. * u.us def test_barycentric(self): bval = self.obstime.light_travel_time(self.star, 'barycentric') assert isinstance(bval, TimeDelta) assert bval.scale == 'tdb' assert abs(bval - 460.58538779827836 * u.s) < 1. * u.us def test_arrays(self): bval1 = self.obstime.light_travel_time(self.star, 'barycentric') bval2 = self.obstime2.light_travel_time(self.star, 'barycentric') bval_arr = self.obstimeArr.light_travel_time(self.star, 'barycentric') hval1 = self.obstime.light_travel_time(self.star, 'heliocentric') hval2 = self.obstime2.light_travel_time(self.star, 'heliocentric') hval_arr = self.obstimeArr.light_travel_time(self.star, 'heliocentric') assert hval_arr[0] - hval1 < 1. * u.us assert hval_arr[1] - hval2 < 1. * u.us assert bval_arr[0] - bval1 < 1. * u.us assert bval_arr[1] - bval2 < 1. * u.us @pytest.mark.remote_data @pytest.mark.skipif('not HAS_JPLEPHEM') def test_ephemerides(self): bval1 = self.obstime.light_travel_time(self.star, 'barycentric') with solar_system_ephemeris.set('jpl'): bval2 = self.obstime.light_travel_time(self.star, 'barycentric', ephemeris='jpl') # should differ by less than 0.1 ms, but not be the same assert abs(bval1 - bval2) < 1. * u.ms assert abs(bval1 - bval2) > 1. * u.us
def plan_when_transits_will_occur( filename='targets.txt', observatory='Southern African Large Telescope', start='2017-06-22', end='2017-06-28', airmass_limit=2.5, moon_distance=10, do_secondary=True, method='by_night'): ''' Plan when targets will be visibile and transiting from a site. Inputs ------ filename : str A plain text file with the following columns: target : The name of the target (e.g. J0555-57). RA : The right ascension of the target (e.g. 05h55m32.62s). DEC : The declination of the target (e.g. -57d17m26.1s). epoch* : The epoch of the transit. Youc can either use: epoch_HJD-2400000 : HJD - 24500000 epoch_BJD-2455000 : MJD Period : The period of the system (days). Secondary : can be True or False depending on whether you want to see when the secondary transits will be. observatory : str The observatory you are observing from. See later for list of available observatories (accepted by astropy). start : str The first night of observation (e.g. 2017-08-31). end : str The last night of observation (e.g. 2017-09-10). airmass_limit : float The maximum airmass you want to observe through. moon_distance : float The closest the target can be t the moon in arcmins. do_secondary = True: Look for secondary eclipses assuming circularised orbits. Available observator names are: 'ALMA', 'Anglo-Australian Observatory', 'Apache Point', 'Apache Point Observatory', 'Atacama Large Millimeter Array', 'BAO', 'Beijing XingLong Observatory', 'Black Moshannon Observatory', 'CHARA', 'Canada-France-Hawaii Telescope', 'Catalina Observatory', 'Cerro Pachon', 'Cerro Paranal', 'Cerro Tololo', 'Cerro Tololo Interamerican Observatory', 'DCT', 'Discovery Channel Telescope', 'Dominion Astrophysical Observatory', 'Gemini South', 'Hale Telescope', 'Haleakala Observatories', 'Happy Jack', 'Jansky Very Large Array', 'Keck Observatory', 'Kitt Peak', 'Kitt Peak National Observatory', 'La Silla Observatory', 'Large Binocular Telescope', 'Las Campanas Observatory', 'Lick Observatory', 'Lowell Observatory', 'Manastash Ridge Observatory', 'McDonald Observatory', 'Medicina', 'Medicina Dish', 'Michigan-Dartmouth-MIT Observatory', 'Mount Graham International Observatory', 'Mt Graham', 'Mt. Ekar 182 cm. Telescope', 'Mt. Stromlo Observatory', 'Multiple Mirror Telescope', 'NOV', 'National Observatory of Venezuela', 'Noto', 'Observatorio Astronomico Nacional, San Pedro Martir', 'Observatorio Astronomico Nacional, Tonantzintla', 'Palomar', 'Paranal Observatory', 'Roque de los Muchachos', 'SAAO', 'SALT', 'SRT', 'Siding Spring Observatory', 'Southern African Large Telescope', 'Subaru', 'Subaru Telescope', 'Sutherland', 'Vainu Bappu Observatory', 'Very Large Array', 'W. M. Keck Observatory', 'Whipple', 'Whipple Observatory', 'aao', 'alma', 'apo', 'bmo', 'cfht', 'ctio', 'dao', 'dct', 'ekar', 'example_site', 'flwo', 'gemini_north', 'gemini_south', 'gemn', 'gems', 'greenwich', 'haleakala', 'irtf', 'keck', 'kpno', 'lapalma', 'lasilla', 'lbt', 'lco', 'lick', 'lowell', 'mcdonald', 'mdm', 'medicina', 'mmt', 'mro', 'mso', 'mtbigelow', 'mwo', 'noto', 'ohp', 'paranal', 'salt', 'sirene', 'spm', 'srt', 'sso', 'tona', 'vbo', 'vla'. ''' ################### # Try reading table ################### try: target_table = Table.read(filename, format='ascii') except: raise ValueError( 'I cant open the target file (make sure its ascii with the following first line:\ntarget RA DEC epoch_HJD-2400000 Period Secondary' ) ############################## # try reading observation site ############################## try: observation_site = coord.EarthLocation.of_site(observatory) observation_handle = Observer(location=observation_site) observation_handle1 = Observer.at_site(observatory) except: print(coord.EarthLocation.get_site_names()) raise ValueError('The site is not understood') ################################### # Try reading start and end times ################################### try: start_time = Time(start + ' 12:01:00', location=observation_site) end_time = Time(end + ' 12:01:00', location=observation_site) number_of_nights = int(end_time.jd - start_time.jd) time_range = Time([start + ' 12:01:00', end + ' 12:01:00']) print('Number of nights: {}'.format(number_of_nights)) except: raise ValueError('Start and end times not understood') ##################### # Now do constraints ##################### #try: constraints = [ AltitudeConstraint(0 * u.deg, 90 * u.deg), AirmassConstraint(3), AtNightConstraint.twilight_civil() ] #except: # raise ValueError('Unable to get set constraints') if method == 'by_night': for i in range(number_of_nights): start_time_tmp = start_time + TimeDelta( i, format='jd') # get start time (doesent need to be accurate) end_time_tmp = start_time + TimeDelta( i + 1, format='jd') # get start time (doesent need to be accurate) print('#' * 80) start_time_tmpss = start_time_tmp.datetime.ctime().split( ) # ['Fri', 'Dec', '24', '12:00:00', '2010'] print('Night {} - {} {} {} {}'.format(i + 1, start_time_tmpss[0], start_time_tmpss[2], start_time_tmpss[1], start_time_tmpss[-1])) print('#' * 80) # Now print Almnac information (sunset and end of evening twilight print('Almnac:') sun_set = observation_handle.sun_set_time(start_time_tmp, which='next') print('Sunset:\t\t\t\t\t\t\t' + sun_set.utc.datetime.ctime()) twilight_evening_astronomical = observation_handle.twilight_evening_astronomical( start_time_tmp, which='next') # -18 twilight_evening_nautical = observation_handle.twilight_evening_nautical( start_time_tmp, which='next') # -12 twilight_evening_civil = observation_handle.twilight_evening_civil( start_time_tmp, which='next') # -6 deg print('Civil evening twilight (-6 deg) (U.T.C):\t\t' + twilight_evening_civil.utc.datetime.ctime()) print('Nautical evening twilight (-12 deg) (U.T.C):\t\t' + twilight_evening_nautical.utc.datetime.ctime()) print('Astronomical evening twilight (-18 deg) (U.T.C):\t' + twilight_evening_astronomical.utc.datetime.ctime()) print('\n') twilight_morning_astronomical = observation_handle.twilight_morning_astronomical( start_time_tmp, which='next') # -18 twilight_morning_nautical = observation_handle.twilight_morning_nautical( start_time_tmp, which='next') # -12 twilight_morning_civil = observation_handle.twilight_morning_civil( start_time_tmp, which='next') # -6 deg print('Astronomical morning twilight (-18 deg) (U.T.C):\t' + twilight_morning_astronomical.utc.datetime.ctime()) print('Nautical morning twilight (-12 deg) (U.T.C):\t\t' + twilight_morning_nautical.utc.datetime.ctime()) print('Civil morning twilight (-6 deg) (U.T.C):\t\t' + twilight_morning_civil.utc.datetime.ctime()) sun_rise = observation_handle.sun_rise_time(start_time_tmp, which='next') print('Sunrise:\t\t\t\t\t\t' + sun_rise.utc.datetime.ctime()) print('\n') # stuff for creating plot plot_mids = [] plot_names = [] plot_widths = [] for j in range(len(target_table)): # Extract information star_coordinates = coord.SkyCoord('{} {}'.format( target_table['RA'][j], target_table['DEC'][j]), unit=(u.hourangle, u.deg), frame='icrs') star_fixed_coord = FixedTarget(coord=star_coordinates, name=target_table['target'][j]) #################### # Get finder image #################### ''' plt.close() try: finder_image = plot_finder_image(star_fixed_coord,reticle=True,fov_radius=10*u.arcmin) except: pass plt.savefig(target_table['target'][j]+'_finder_chart.eps') ''' P = target_table['Period'][j] Secondary_transit = target_table['Secondary'][j] transit_half_width = TimeDelta( target_table['width'][j] * 60 * 60 / 2, format='sec') # in seconds for a TimeDelta # now convert T0 to HJD -> JD -> BJD so we can cout period if 'epoch_HJD-2400000' in target_table.colnames: #print('Using HJD-2400000') T0 = target_table['epoch_HJD-2400000'][j] T0 = Time(T0 + 2400000, format='jd') # HJD given by WASP ltt_helio = T0.light_travel_time(star_coordinates, 'heliocentric', location=observation_site) T0 = T0 - ltt_helio # HJD -> JD ltt_bary = T0.light_travel_time(star_coordinates, 'barycentric', location=observation_site) T0 = T0 + ltt_bary # JD -> BJD elif 'epoch_BJD-2455000' in target_table.colnames: #print('Using BJD-2455000') T0 = target_table['epoch_BJD-2455000'][j] + 2455000 T0 = Time(T0, format='jd') # BJD else: print('\n\n\n\n FAILE\n\n\n\n') continue ########################################################## # Now start from T0 and count in periods to find transits ########################################################## # convert star and end time to BJD ltt_bary_start_time = start_time_tmp.light_travel_time( star_coordinates, 'barycentric', location=observation_site) # + TimeDelta(i,format='jd') start_time_bary = start_time_tmp + ltt_bary_start_time # + TimeDelta(i,format='jd') # convert start time to BJD ltt_bary_end_time_tmp = end_time_tmp.light_travel_time( star_coordinates, 'barycentric', location=observation_site) # + TimeDelta(i,format='jd') end_time_bary = end_time_tmp + ltt_bary_start_time #+ TimeDelta(i+1,format='jd') # convert end time to BJD and add 1 day 12pm -> 12pm the next day elapsed = end_time_bary - start_time_bary # now this is 24 hours from the start day 12:00 pm # now count transits time = Time(T0.jd, format='jd') # make a temporary copy transits = [] primary_count, secondary_count = 0, 0 while time.jd < end_time_bary.jd: if (time.jd > start_time_bary.jd) and (time.jd < end_time_bary.jd): if is_observable(constraints, observation_handle, [star_fixed_coord], times=[time])[0] == True: transits.append(time) primary_count += 1 if Secondary_transit == 'yes': timesecondary = time + TimeDelta(P / 2, format='jd') if (timesecondary.jd > start_time_bary.jd) and ( timesecondary.jd < end_time_bary.jd): if is_observable(constraints, observation_handle, [star_fixed_coord], times=[timesecondary])[0] == True: transits.append(timesecondary) secondary_count += 1 time = time + TimeDelta(P, format='jd') # add another P to T0 # Now find visible transits transits = [ i for i in transits if is_observable(constraints, observation_handle, [star_fixed_coord], times=[i])[0] == True ] if len(transits) == 0: message = '{} has no transits.'.format( target_table['target'][j]) print('-' * len(message)) print(message) print('-' * len(message)) print('\n') plt.close() continue else: message = '{} has {} primary transits and {} secondary transits.'.format( target_table['target'][j], primary_count, secondary_count) print('-' * len(message)) print(message) print('RA: {}'.format(target_table['RA'][j])) print('DEC: {}'.format(target_table['DEC'][j])) print('Epoch: 2000') print('T0 (BJD): {}'.format(T0.jd)) print('Period: {}'.format(P)) print('Transit width (hr): {}'.format( target_table['width'][j])) print('-' * len(message)) print('\n') for i in transits: # currently transit times are in BJD (need to convert to HJD to check ltt_helio = i.light_travel_time(star_coordinates, 'barycentric', location=observation_site) ii = i - ltt_helio ltt_helio = ii.light_travel_time(star_coordinates, 'heliocentric', location=observation_site) ii = ii + ltt_helio transit_1 = i - transit_half_width - TimeDelta( 7200, format='sec') # ingress - 2 hr transit_2 = i - transit_half_width - TimeDelta( 3600, format='sec') # ingress - 2 hr transit_3 = i - transit_half_width # ingress transit_4 = i + transit_half_width # egress transit_5 = i + transit_half_width + TimeDelta( 3600, format='sec') # ingress - 2 hr transit_6 = i + transit_half_width + TimeDelta( 7200, format='sec') # ingress - 2 hr if (((i.jd - time.jd) / P) - np.floor( (i.jd - time.jd) / P) < 0.1) or (( (i.jd - time.jd) / P) - np.floor( (i.jd - time.jd) / P) > 0.9): print('Primary Transit:') print('-' * len('Primary Transit')) if 0.4 < ((i.jd - time.jd) / P) - np.floor( (i.jd - time.jd) / P) < 0.6: print('Secondary Transit') print('-' * len('Secondary Transit')) ################## # now get sirmass ################## altaz = star_coordinates.transform_to( AltAz(obstime=transit_1, location=observation_site)) hourangle = observation_handle1.target_hour_angle( transit_1, star_coordinates) hourangle = 24 * hourangle.degree / 360 if hourangle > 12: hourangle -= 24 print('Ingress - 2hr (U.T.C):\t\t\t\t\t' + transit_1.utc.datetime.ctime() + '\tAirmass: {:.2f}\tHA:{:.2f}'.format( altaz.secz, hourangle)) altaz = star_coordinates.transform_to( AltAz(obstime=transit_2, location=observation_site)) hourangle = observation_handle1.target_hour_angle( transit_2, star_coordinates) hourangle = 24 * hourangle.degree / 360 if hourangle > 12: hourangle -= 24 print('Ingress - 1hr (U.T.C):\t\t\t\t\t' + transit_2.utc.datetime.ctime() + '\tAirmass: {:.2f}\tHA:{:.2f}'.format( altaz.secz, hourangle)) altaz = star_coordinates.transform_to( AltAz(obstime=transit_3, location=observation_site)) hourangle = observation_handle1.target_hour_angle( transit_3, star_coordinates) hourangle = 24 * hourangle.degree / 360 if hourangle > 12: hourangle -= 24 print('Ingress (U.T.C):\t\t\t\t\t' + transit_3.utc.datetime.ctime() + '\tAirmass: {:.2f}\tHA:{:.2f}'.format( altaz.secz, hourangle)) altaz = star_coordinates.transform_to( AltAz(obstime=i, location=observation_site)) hourangle = observation_handle1.target_hour_angle( i, star_coordinates) hourangle = 24 * hourangle.degree / 360 if hourangle > 12: hourangle -= 24 print('Mid transit (U.T.C):\t\t\t\t\t' + i.utc.datetime.ctime() + '\tAirmass: {:.2f}\tHA:{:.2f}'.format( altaz.secz, hourangle)) altaz = star_coordinates.transform_to( AltAz(obstime=transit_4, location=observation_site)) hourangle = observation_handle1.target_hour_angle( transit_4, star_coordinates) hourangle = 24 * hourangle.degree / 360 if hourangle > 12: hourangle -= 24 print('Egress (U.T.C):\t\t\t\t\t\t' + transit_4.utc.datetime.ctime() + '\tAirmass: {:.2f}\tHA:{:.2f}'.format( altaz.secz, hourangle)) altaz = star_coordinates.transform_to( AltAz(obstime=transit_5, location=observation_site)) hourangle = observation_handle1.target_hour_angle( transit_5, star_coordinates) hourangle = 24 * hourangle.degree / 360 if hourangle > 12: hourangle -= 24 print('Egress + 1hr (U.T.C):\t\t\t\t\t' + transit_5.utc.datetime.ctime() + '\tAirmass: {:.2f}\tHA:{:.2f}'.format( altaz.secz, hourangle)) altaz = star_coordinates.transform_to( AltAz(obstime=transit_6, location=observation_site)) hourangle = observation_handle1.target_hour_angle( transit_6, star_coordinates) hourangle = 24 * hourangle.degree / 360 if hourangle > 12: hourangle -= 24 print('Egress + 2hr (U.T.C):\t\t\t\t\t' + transit_6.utc.datetime.ctime() + '\tAirmass: {:.2f}\tHA:{:.2f}'.format( altaz.secz, hourangle)) print('HJD {} (to check with http://var2.astro.cz/)\n'. format(ii.jd)) # append stuff for plots plot_mids.append(i) # astropy Time plot_names.append(target_table['target'][j]) plot_widths.append(target_table['width'][j]) # Now plot plt.close() if len(plot_mids) == 0: continue date_formatter = dates.DateFormatter('%H:%M') #ax.xaxis.set_major_formatter(date_formatter) # now load dummy transit lightcurves xp, yp = np.load('lc.npy') xs, ys = np.load('lcs.npy') # x = np.linspace(0, 2*np.pi, 400) # y = np.sin(x**2) subplots_adjust(hspace=0.000) number_of_subplots = len( plot_names) # number of targets transiting that night time = sun_set + np.linspace(-1, 14, 100) * u.hour # take us to sunset for i, v in enumerate(xrange(number_of_subplots)): # exctract params width = plot_widths[v] name = plot_names[v] mid = plot_mids[v] # now set up dummy lc plot x_tmp = mid + xp * (width / 2) * u.hour # get right width in hours # now set up axis v = v + 1 ax1 = subplot(number_of_subplots, 1, v) ax1.xaxis.set_major_formatter(date_formatter) if v == 1: ax1.set_title(start) # plot transit model ax1.plot_date(x_tmp.plot_date, ys, 'k-') # plot continuum #xx =time.plot_date #xx = [uu for uu in xx if (uu<min(x_tmp.plot_date)) or (uu>max(x_tmp.plot_date))] #ax1.plot_date(xx, np.ones(len(xx)),'k--', alpha=0.3) ax1.set_xlim(min(time.plot_date), max(time.plot_date)) #ax1.plot_date(mid.plot_date, 0.5, 'ro') plt.setp(ax1.get_xticklabels(), rotation=30, ha='right') ax1.set_ylabel(name, rotation=45, labelpad=20) twilights = [ (sun_set.datetime, 0.0), (twilight_evening_civil.datetime, 0.1), (twilight_evening_nautical.datetime, 0.2), (twilight_evening_astronomical.datetime, 0.3), (twilight_morning_astronomical.datetime, 0.4), (twilight_morning_nautical.datetime, 0.3), (twilight_morning_civil.datetime, 0.2), (sun_rise.datetime, 0.1), ] for ii, twii in enumerate(twilights[1:], 1): ax1.axvspan(twilights[ii - 1][0], twilights[ii][0], ymin=0, ymax=1, color='grey', alpha=twii[1]) ax1.grid(alpha=0.5) ax1.get_yaxis().set_ticks([]) if v != number_of_subplots: ax1.get_xaxis().set_ticks([]) plt.xlabel('Time [U.T.C]') #plt.tight_layout() #plt.savefig('test.eps',format='eps') plt.show()
def test_spice(keep_figures=False): # Initialize our home-made TESS Kernel object: with TESS_SPICE() as knl: for starid in (260795451, 267211065): print("=" * 72) print("TIC %d" % starid) tpf_file = find_tpf_files(INPUT_DIR, starid=starid)[0] with fits.open(tpf_file, mode='readonly', memmap=True) as hdu: time_tpf = hdu[1].data['TIME'] timecorr_tpf = hdu[1].data['TIMECORR'] camera = hdu[0].header['CAMERA'] ccd = hdu[0].header['CCD'] # Coordinates of the target as astropy SkyCoord object: star_coord = coord.SkyCoord( ra=hdu[0].header['RA_OBJ'], dec=hdu[0].header['DEC_OBJ'], unit=u.deg, frame='icrs', obstime=Time('J2000'), pm_ra_cosdec=hdu[0].header['PMRA'] * u.mas / u.yr, pm_dec=hdu[0].header['PMDEC'] * u.mas / u.yr, radial_velocity=0 * u.km / u.s) # Load the original timestamps from FFIs: hdf_file = find_hdf5_files(INPUT_DIR, camera=camera, ccd=ccd)[0] with h5py.File(hdf_file, 'r') as hdf: ffi_time = np.asarray(hdf['time']) ffi_timecorr = np.asarray(hdf['timecorr']) f = interp1d(time_tpf - timecorr_tpf, timecorr_tpf, kind='linear') # Change the timestamps bach to JD: time_nocorr = ffi_time - ffi_timecorr times = Time(time_nocorr, 2457000, format='jd', scale='tdb') ras, decs = add_proper_motion(star_coord.ra.value, star_coord.dec.value, star_coord.pm_ra_cosdec.value, star_coord.pm_dec.value, times.jd) star_coord = coord.SkyCoord(ra=ras[0], dec=decs[0], unit=u.deg, frame='icrs') print(star_coord) # Use Greenwich as location instead of TESS (similar to what is done in Elenor): greenwich = coord.EarthLocation.of_site('greenwich') times_greenwich = Time(time_nocorr + 2457000, format='jd', scale='utc', location=greenwich) timecorr_greenwich = times_greenwich.light_travel_time( star_coord, kind='barycentric', ephemeris='builtin').value #time_greenwich = time_nocorr + timecorr_greenwich # Calculate barycentric correction using our method: time_astropy, timecorr_astropy = knl.barycorr( time_nocorr + 2457000, star_coord) # Caluclate barycentric correction uning second method: timecorr_knl = knl.barycorr2(time_nocorr + 2457000, star_coord) print(timecorr_knl) # Plot the new barycentric time correction and the old one: fig1 = plt.figure() ax = fig1.add_subplot(111) ax.scatter(time_nocorr, ffi_timecorr * 86400, alpha=0.3, s=4, label='FFI timecorr') ax.scatter(time_tpf - timecorr_tpf, timecorr_tpf * 86400, alpha=0.3, s=4, label='TPF timecorr') ax.scatter(time_nocorr, timecorr_greenwich * 86400, alpha=0.3, s=4, label='Elenor timecorr') ax.scatter(time_nocorr, timecorr_astropy * 86400, alpha=0.3, s=4, label='Our timecorr') ax.set_xlabel('Uncorrected Time (JD - 2457000)') ax.set_ylabel('Barycentric Time Correction (s)') ax.set_title('TIC %d' % starid) plt.legend() # Plot the new barycentric time correction and the old one: fig2 = plt.figure(figsize=(8, 10)) ax1 = fig2.add_subplot(311) ax1.axhline(0, color='k', ls=':', lw=0.5) ax1.plot(time_nocorr, (ffi_timecorr - f(time_nocorr)) * 86400, '.') ax1.set_ylabel('FFI - TPF (seconds)') ax1.set_title('TIC %d' % starid) ax2 = fig2.add_subplot(312) ax2.axhline(0, color='k', ls=':', lw=0.5) ax2.plot(time_nocorr, (timecorr_greenwich - f(time_nocorr)) * 86400 * 1000, '.') ax2.set_ylabel('Elenor - TPF (ms)') ax3 = plt.subplot(313) ax3.axhline(0, color='k', ls=':', lw=0.5) ax3.plot(time_nocorr, (timecorr_astropy - f(time_nocorr)) * 86400 * 1000, '.', label='Astropy') ax3.plot(time_nocorr, (timecorr_knl - f(time_nocorr)) * 86400 * 1000, '.', label='Kernel') ax3.set_ylabel('Our - TPF (ms)') ax3.set_xlabel('Uncorrected Time (TJD)') ax3.legend() ax1.set_xticks([]) ax2.set_xticks([]) plt.tight_layout() if not keep_figures: plt.close(fig1) plt.close(fig2) print("=" * 72)
#enter target in qoutes below #target="ip_peg" #obj=coord.SkyCoord.from_name(target) ra = hdu_list[0].header['RA'] dec = hdu_list[0].header['DEC'] obj = coord.SkyCoord(ra, dec, unit=(u.hourangle, u.deg), frame='fk5') #l=coord.EarthLocation.get_site_names() telescopedict = { "Gemini-North": "gemini_north", "Gemini-South": "gemini_south", "WIYN": "kitt peak" } telescope = telescopedict[hdu_list[0].header['OBSERVAT']] times = Time(mjdtime, format='mjd', scale='utc', location=coord.EarthLocation.of_site(telescope)) ltt_bary = times.light_travel_time(obj) np.savetxt(path+str(file["filename"])+'_ltt_barytiming.txt', ltt_bary, delimiter=" ", fmt='%s') bjdtime=mjdtime+ltt_bary np.savetxt(path+str(file["filename"])+'bjdtiming.txt', bjdtime, delimiter=" ", fmt='%s') #read the data in using pandas dat_file = path+file["lc_filename"] df = pd.read_csv(dat_file, index_col=None, delim_whitespace=True, names=['frame','mag']) #select region of interest (optional) framestart=0 #starting from 0 frameend=frames numframes=frameend-framestart frames=df['frame'].values[framestart:frameend] mag=df['mag'].values[framestart:frameend]
format='jd', scale='utc') #obsDayTimeofEphemerisEndPoint = Time(linearEphemeris + epochNumber * 1.0914203, format='jd', scale='utc')+(transitFWHM/2)*u.day obsDayTimeofEphemerisMidPoint.format = 'iso' print('obsDayTimeofEphemerisMidPoint=') print(obsDayTimeofEphemerisMidPoint) offsetFromMidnight = ( (obsDayTimeofEphemerisMidPoint - observingNightMidnightUTC)).sec / 3600 #this is to align the plots deltaFromObservingNightMidnightUTC = np.linspace( -6, 6, 100 ) * u.hour #to create x.axis values for the 6 hours either side of midnight lttObservingNight = Time.light_travel_time(observingNightMidnightUTC + deltaFromObservingNightMidnightUTC, wasp12b, location=alston) bjdhoursObservingNight = lttObservingNight.to(u.hour) deltaFromEphemerisMidPoint = np.linspace( -(transitFWHM / 2), (transitFWHM / 2), 20 ) * u.hour #to create x.axis values for half the FHWM period either side of the transit midpoint lttEphemeris = Time.light_travel_time(obsDayTimeofEphemerisMidPoint + deltaFromEphemerisMidPoint, wasp12b, location=alston) bjdhoursEphemeris = lttEphemeris.to(u.hour) print('transitFWHM/2= ' + str(transitFWHM / 2)) frameOfObservingNight = AltAz(obstime=observingNightMidnightUTC + deltaFromObservingNightMidnightUTC,
def bjdbrv(jd_utc, ra=None, dec=None, obsname=None, lat=0., lon=0., elevation=None, pmra=0., pmdec=0., parallax=0., rv=0., zmeas=0., epoch=2451545.0, tbase=0., leap_update=False, **kwargs): """ Wrapper to barycorrpy.py and utc2bjd. Computes the barycentric velocity correction and julian date in one call. Keyword obsname refers to observatory.pro in the IDL Astronomy User Library See also: http://astroutils.astronomy.ohio-state.edu/exofast/barycorr.html :param jd_utc: Julian date (UTC) :param ra: RA (J2000) [deg] :param dec: Dec (J2000) [deg] :param obsname: Observatory name (overrides coordinates if set) :param lat: Observatory latitude [deg] :param lon: Observatory longitude (E) [+/-360 deg] :param elevation: Observatory elevation [m] :param pmra: Proper motion (RA*cos(Dec)) [mas/yr] :param pmdec: Proper motion (Dec) [mas/yr] :param parallax: Parallax [mas] :param rv: Radial velocity (within 100 km/s) [m/s] :param zmeas: Measured redshift :param epoch: Epoch (default 2448348.56250, J2000) :param tbase: Baseline subtracted from times (default 0.0) :return: Barycentric correction for zmeas Example: -------- >>> from brv_we14py import bjdbrv >>> print bjdbrv(2457395.24563, 4.585590721, 44.02195596, 'ca') (2457395.247062386, -23684.54364462639) """ if obsname == "McDonald Observatory": # Same as used in SERVAL lat = 30.6814 lon = -104.0147 elevation = 2025. # Barycentric Julian Date # adapted from http://docs.astropy.org/en/stable/time/#barycentric-and-heliocentric-light-travel-time-corrections targ = coord.SkyCoord(ra, dec, unit=(u.deg, u.deg), frame='icrs') loc = coord.EarthLocation.from_geodetic(lon, lat, height=elevation) #times = time.Time(jd_utc, format='jd', scale='utc', location=loc) #ltt_bary = times.light_travel_time(targ) JDUTC = Time(jd_utc, format='jd', scale='utc') ltt_bary = JDUTC.light_travel_time(targ, location=loc) bjd = JDUTC.tdb + ltt_bary # we should be JDUTC if leap_update is False: print('WARNING: LEAP UPDATE=FALSE') brv, warning, status = barycorrpy.get_BC_vel(JDUTC, ra=ra, dec=dec, epoch=epoch, pmra=pmra, pmdec=pmdec, px=parallax, lat=lat, longi=lon, alt=elevation, leap_update=leap_update, **kwargs) return bjd.value, brv[0]
plt.ylabel('MJD (s)') plt.savefig(path+'timing'+name+'.png',dpi=200) #work out the bjd #https://mail.python.org/pipermail/astropy/2014-April/002844.html #https://docs.astropy.org/en/stable/time/ #http://astroutils.astronomy.ohio-state.edu/time/ #time to barycenter correction -needs target ra, dec, and observatory location. it pulls these from the fits header #enter target in qoutes below if you don't want to pull the object from the header #target="ip_peg" #obj=coord.SkyCoord.from_name(target) ra = hdu_list[0].header['RA'] dec = hdu_list[0].header['DEC'] obj = coord.SkyCoord(ra, dec, unit=(u.hourangle, u.deg), frame='fk5') #l=coord.EarthLocation.get_site_names() telescopedict = { "Gemini-North": "gemini_north", "Gemini-South": "gemini_south", "WIYN": "kitt peak" } telescope = telescopedict[hdu_list[0].header['OBSERVAT']] times = Time(mjdtime, format='mjd', scale='utc', location=coord.EarthLocation.of_site(telescope)) ltt_bary = times.light_travel_time(obj, ephemeris='jpl') np.savetxt(path+name+'_ltt_barytiming.txt', ltt_bary, delimiter=" ", fmt='%s') bjdtime=times.tdb+ltt_bary np.savetxt(path+name+'bjdtiming.txt', bjdtime, delimiter=" ", fmt='%s') #bjd_tdb plt.show()
def test_spice(SHARED_INPUT_DIR, starid): # Initialize our home-made TESS Kernel object: with TESS_SPICE() as knl: print("="*72) print("TIC %d" % starid) tpf_file = find_tpf_files(SHARED_INPUT_DIR, starid=starid)[0] with fits.open(tpf_file, mode='readonly', memmap=True) as hdu: time_tpf = hdu[1].data['TIME'] timecorr_tpf = hdu[1].data['TIMECORR'] camera = hdu[0].header['CAMERA'] ccd = hdu[0].header['CCD'] # Coordinates of the target as astropy SkyCoord object: star_coord = coord.SkyCoord( ra=hdu[0].header['RA_OBJ'], dec=hdu[0].header['DEC_OBJ'], unit=u.deg, frame='icrs', obstime=Time('J2000'), pm_ra_cosdec=hdu[0].header['PMRA']*u.mas/u.yr, pm_dec=hdu[0].header['PMDEC']*u.mas/u.yr, radial_velocity=0*u.km/u.s ) # Load the original timestamps from FFIs: hdf_file = find_hdf5_files(SHARED_INPUT_DIR, camera=camera, ccd=ccd)[0] with h5py.File(hdf_file, 'r') as hdf: ffi_time = np.asarray(hdf['time']) ffi_timecorr = np.asarray(hdf['timecorr']) f = interp1d(time_tpf-timecorr_tpf, timecorr_tpf, kind='linear') # Change the timestamps bach to JD: time_nocorr = ffi_time - ffi_timecorr times = Time(time_nocorr, 2457000, format='jd', scale='tdb') ras, decs = add_proper_motion( star_coord.ra.value, star_coord.dec.value, star_coord.pm_ra_cosdec.value, star_coord.pm_dec.value, times.jd ) star_coord = coord.SkyCoord( ra=ras[0], dec=decs[0], unit=u.deg, frame='icrs' ) print(star_coord) # Use Greenwich as location instead of TESS (similar to what is done in Elenor): greenwich = coord.EarthLocation.of_site('greenwich') times_greenwich = Time(time_nocorr+2457000, format='jd', scale='utc', location=greenwich) timecorr_greenwich = times_greenwich.light_travel_time(star_coord, kind='barycentric', ephemeris='builtin').value #time_greenwich = time_nocorr + timecorr_greenwich # Calculate barycentric correction using our method: time_astropy, timecorr_astropy = knl.barycorr(time_nocorr + 2457000, star_coord) # Calculate barycentric correction using second method: timecorr_knl = knl.barycorr2(time_nocorr + 2457000, star_coord) print(timecorr_knl) # Plot the new barycentric time correction and the old one: fig1 = plt.figure() ax = fig1.add_subplot(111) ax.plot(time_tpf - timecorr_tpf, timecorr_tpf*86400, 'g.-', label='TPF timecorr') ax.plot(time_nocorr, ffi_timecorr*86400, 'b.-', label='FFI centre') ax.scatter(time_nocorr, timecorr_greenwich*86400, marker='x', label='Elenor timecorr') ax.scatter(time_nocorr, timecorr_astropy*86400, marker='x', c='r', label='Our timecorr') ax.set_xlabel('Uncorrected Time [TJD]') ax.set_ylabel('Barycentric Time Correction [s]') ax.set_title('TIC %d' % starid) ax.set_yscale('log') plt.legend() # Plot the new barycentric time correction and the old one: fig2 = plt.figure(figsize=(8,10)) ax3 = fig2.add_subplot(111) ax3.axhline(1.0, color='k', ls='--', lw=1) ax3.plot(time_nocorr, np.abs(ffi_timecorr - f(time_nocorr))*86400, '.-', label='FFI centre') ax3.plot(time_nocorr, np.abs(timecorr_greenwich - f(time_nocorr))*86400*1000, '.-', label='Elenor') ax3.plot(time_nocorr, np.abs(timecorr_astropy - f(time_nocorr))*86400*1000, '.-', label='Astropy') ax3.plot(time_nocorr, np.abs(timecorr_knl - f(time_nocorr))*86400*1000, '.-', label='Kernel') ax3.set_ylabel('abs(TimeCorr - TPF TimeCorr) [ms]') ax3.set_xlabel('Uncorrected Time [TJD]') ax3.set_yscale('log') ax3.set_ylim(bottom=0.1) ax3.legend() ax3.grid(axis='y', which='both', color='0.7', ls=':', lw=0.5) ax3.set_title('TIC %d' % starid) plt.tight_layout() assert np.all(86400000*np.abs(timecorr_astropy - f(time_nocorr)) < 1), "AstroPy method: More than 1 ms away" assert np.all(86400000*np.abs(timecorr_knl - f(time_nocorr)) < 1), "HomeMade method: More than 1 ms away" print("="*72)
def hmjd_to_earth(hmjd, coord): t = Time(hmjd, format='mjd') return t - t.light_travel_time( coord, kind='heliocentric', location=PALOMAR)