def compute_local_st(hdrs,debug=False): '''Compute the Local Apparent Sidereal Time. A TDB (ideally) or TT midtime must be provided as part of the <hdrs> dictionary otherwise an exception is raised.''' # Compute the Greenwich mean sidereal time. This requires the full UT1 date # as a MJD, not just the fraction. gmst = S.sla_gmst(hdrs['MJD_UTC_mid'] + (hdrs['UT1-UTC']/86400.0)) # Now local apparent sidereal time by adding longitude and the equation of the # equinoxes (which needs the TDB date) if hdrs.has_key('MJD_TDB_mid'): date = hdrs['MJD_TDB_mid'] if debug: print "Using TDB time:", date elif hdrs.has_key('MJD_TT_mid'): date = hdrs['MJD_TT_mid'] if debug: print "Using TT time:", date else: raise TimeError('Need a TDB or TT time available') last = gmst + hdrs['OBS_ELONG'] + S.sla_eqeqx(date) new_dict = { 'LST_App_mid' : last } hdrs.update(new_dict) return hdrs
def compute_hourangle(date, obsvr_long, obsvr_lat, obsvr_hgt, mean_ra, mean_dec, dbg=False): mjd_tdb = datetime2mjd_tdb(date, obsvr_long, obsvr_lat, obsvr_hgt, False) # Compute MJD_UTC mjd_utc = datetime2mjd_utc(date) # Compute UT1-UTC dut = ut1_minus_utc(mjd_utc) # Compute local apparent sidereal time # Do GMST first which takes UT1 and then add East longitude and the equation of the equinoxes # (which takes TDB) # gmst = S.sla_gmst(mjd_utc+(dut/86400.0)) stl = gmst + obsvr_long + S.sla_eqeqx(mjd_tdb) logger.debug('GMST, LAST, EQEQX, GAST, long= %.17f %.17f %E %.17f %.17f' % (gmst, stl, S.sla_eqeqx(mjd_tdb), gmst+S.sla_eqeqx(mjd_tdb), obsvr_long)) (app_ra, app_dec) = S.sla_map(mean_ra, mean_dec, 0.0, 0.0, 0.0, 0.0, 2000.0, mjd_tdb) (ra_str, dec_str) = radec2strings(app_ra, app_dec) logger.debug("%f %f %s %s" % (app_ra, app_dec, ra_str, dec_str)) hour_angle = stl - app_ra logger.debug(hour_angle) hour_angle = S.sla_drange(hour_angle) logger.debug(hour_angle) return hour_angle
def hlst(self,mjd) : global tellat, tellong, telelev # test 0.2 sec UT1 correction # dut1 = (0.2 /3600.0) * math.pi/12.0 dut1 = 0.0 last = s.sla_gmst(mjd) - tellong + s.sla_eqeqx(mjd) + dut1 # lmst = s.sla_gmst(mjd) - tellong if last < 0.0 : last = last + 2.0*math.pi return last
def compute_ephem(d, orbelems, sitecode, dbg=False, perturb=True, display=False): '''Routine to compute the geocentric or topocentric position, magnitude, motion and altitude of an asteroid or comet for a specific date and time from a dictionary of orbital elements. <orbelems> can be in one of two forms, so called "Eric format" as produced by rise_set.moving_objects.read_neocp_orbit and used in the scheduler/RequestDB or the format used by NEO exchange. Selection is automatically handled based on whether the epoch of the elements dictionary key is 'epoch' (Eric format) or 'epochofel' (NEO exchange format) ''' # Light travel time for 1 AU (in sec) tau = 499.004783806 # Compute MJD for UTC mjd_utc = datetime2mjd_utc(d) # Compute epoch of the elements as a MJD try: epochofel = datetime.strptime(orbelems['epochofel'], '%Y-%m-%d %H:%M:%S') except TypeError: epochofel = orbelems['epochofel'] epoch_mjd = datetime2mjd_utc(epochofel) logger.debug('Element Epoch= %.1f' % (epoch_mjd)) logger.debug('MJD(UTC) = %.15f' % (mjd_utc)) logger.debug(' JD(UTC) = %.8f' % (mjd_utc + 2400000.5)) # Convert MJD(UTC) to MJD(TT) mjd_tt = mjd_utc2mjd_tt(mjd_utc) logger.debug('MJD(TT) = %.15f' % (mjd_tt)) # Compute UT1-UTC dut = ut1_minus_utc(mjd_utc) logger.debug("UT1-UTC = %.15f" % (dut)) # Obtain precession-nutation 3x3 rotation matrix # Should really be TDB but "TT will do" says The Wallace... rmat = S.sla_prenut(2000.0, mjd_tt) logger.debug(rmat) # Obtain latitude, longitude of the observing site. # Reverse longitude to get the more normal East-positive convention # (site_num, site_name, site_long, site_lat, site_hgt) = S.sla_obs(0, 'SAAO74') # site_long = -site_long (site_name, site_long, site_lat, site_hgt) = get_sitepos(sitecode) logger.debug("Site code/name, lat/long/height=%s %s %f %f %.1f" % (sitecode, site_name, site_long, site_lat, site_hgt)) if site_name == '?': logger.debug("WARN: No site co-ordinates found, computing for geocenter") pvobs = zeros(6) else: # Compute local apparent sidereal time # Do GMST first which takes UT1 and then add East longitiude and the equation of the equinoxes # (which takes TDB; but we use TT here) # gmst = S.sla_gmst(mjd_utc+(dut/86400.0)) stl = gmst + site_long + S.sla_eqeqx(mjd_tt) logger.debug('GMST, LAST, EQEQX, GAST, long= %.17f %.17f %E %.17f %.17f' % (gmst, stl, S.sla_eqeqx(mjd_tt), gmst+S.sla_eqeqx(mjd_tt), site_long)) pvobs = S.sla_pvobs(site_lat, site_hgt, stl) logger.debug("PVobs(orig)=%s\n %s" % (pvobs[0:3],pvobs[3:6]*86400.0)) # Apply transpose of precession/nutation matrix to pv vector to go from # true equator and equinox of date to J2000.0 mean equator and equinox (to # match the reference system of sla_epv) # pos_new = S.sla_dimxv(rmat, pvobs[0:3]) vel_new = S.sla_dimxv(rmat, pvobs[3:6]) pvobs_new = concatenate([pos_new, vel_new]) logger.debug("PVobs(new)=%s\n %s" % (pvobs_new[0:3],pvobs_new[3:6]*86400.0)) # Earth position and velocity # Moderate precision/speed version. N.B different order of bary vs. heliocentric! #(vel_bar, pos_bar, e_vel_hel, e_pos_hel) = S.sla_evp(mjd_tt, 2000.0) # High precision/slowest version. N.B different order of bary vs. heliocentric sets # and position vs velocity! # N.B. velocities are AU/day not AU/sec ! # Also N.B. ! Must use heliocentric positions, not barycentric as normal as # asteroid position from sla_planel is also heliocentric. (e_pos_hel, e_vel_hel, e_pos_bar, e_vel_bar) = S.sla_epv(mjd_tt) e_vel_hel = e_vel_hel/86400.0 logger.debug("Sun->Earth [X, Y, Z]=%s" % e_pos_hel) logger.debug("Sun->Earth [X, Y, Z]= %20.15E %20.15E %20.15E" % (e_pos_hel[0], e_pos_hel[1], e_pos_hel[2])) logger.debug("Sun->Earth [Xdot, Ydot, Zdot]=%s" % e_vel_hel) logger.debug("Sun->Earth [Xdot, Ydot, Zdot]= %20.15E %20.15E %20.15E" % (e_vel_hel[0]*86400.0, e_vel_hel[1]*86400.0, e_vel_hel[2]*86400.0)) # Add topocentric offset in position and velocity e_pos_hel = e_pos_hel + pvobs_new[0:3] e_vel_hel = e_vel_hel + pvobs_new[3:6] logger.debug("Sun->Obsvr [X, Y, Z]=%s" % e_pos_hel) logger.debug("Sun->Obsvr [Xdot, Ydot, Zdot]=%s" % e_vel_hel) # Asteroid position (and velocity) comet = False jform = 2 if 'elements_type' in orbelems and str(orbelems['elements_type']).upper() == 'MPC_COMET': comet = True jform = 3 # Perturb elements # NEO exchange format if comet == True: p_orbelems = {'LongNode' : radians(orbelems['longascnode']), 'Inc' : radians(orbelems['orbinc']), 'ArgPeri' : radians(orbelems['argofperih']), 'SemiAxisOrQ' : orbelems['perihdist'], 'Ecc' : orbelems['eccentricity'], } orbelems['meananom'] = 0.0 epoch_mjd = datetime2mjd_utc(orbelems['epochofperih']) else: p_orbelems = {'LongNode' : radians(orbelems['longascnode']), 'Inc' : radians(orbelems['orbinc']), 'ArgPeri' : radians(orbelems['argofperih']), 'MeanAnom' : radians(orbelems['meananom']), 'SemiAxis' : orbelems['meandist'], 'Ecc' : orbelems['eccentricity'] } p_orbelems['H'] = orbelems['abs_mag'] p_orbelems['G'] = orbelems['slope'] if perturb == True: (p_epoch_mjd, p_orbelems['Inc'], p_orbelems['LongNode'], p_orbelems['ArgPeri'], p_orbelems['SemiAxis'], p_orbelems['Ecc'], p_orbelems['MeanAnom'], j) = S.sla_pertel( jform, epoch_mjd, mjd_tt, epoch_mjd, radians(orbelems['orbinc']), radians(orbelems['longascnode']), radians(orbelems['argofperih']), orbelems['meandist'], orbelems['eccentricity'], radians(orbelems['meananom'])) else: p_epoch_mjd = epoch_mjd j = 0 if j != 0: logger.error("Perturbing error=%s" % j) r3 = -100. delta = 0.0 ltt = 0.0 pos = zeros(3) vel = zeros(3) #rel_pos= [0.0, 0.0, 0.0] while (fabs(delta - r3) > .01): r3 = delta if comet == True: (pv, status) = S.sla_planel(mjd_tt - (ltt/86400.0), jform, p_epoch_mjd, p_orbelems['Inc'], p_orbelems['LongNode'], p_orbelems['ArgPeri'], p_orbelems['SemiAxisOrQ'], p_orbelems['Ecc'], 0.0, 0.0) else: (pv, status) = S.sla_planel(mjd_tt - (ltt/86400.0), jform, p_epoch_mjd, p_orbelems['Inc'], p_orbelems['LongNode'], p_orbelems['ArgPeri'], p_orbelems['SemiAxis'], p_orbelems['Ecc'], p_orbelems['MeanAnom'], 0.0) logger.debug("Sun->Asteroid [x,y,z]=%s %s" % (pv[0:3], status)) logger.debug("Sun->Asteroid [xdot,ydot,zdot]=%s %s" % (pv[3:6], status)) for i, e_pos in enumerate(e_pos_hel): pos[i] = pv[i] - e_pos for i, e_vel in enumerate(e_vel_hel): vel[i] = pv[i+3] - e_vel logger.debug("Earth->Asteroid [x,y,z]=%s" % pos) logger.debug("Earth->Asteroid [xdot,ydot,zdot]=%s" % vel) # geometric distance, delta (AU) delta = sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2]) logger.debug("Geometric distance, delta (AU)=%s" % delta) # Light travel time to asteroid ltt = tau * delta logger.debug("Light travel time (sec, min, days)=%s %s %s" % (ltt, ltt/60.0, ltt/86400.0)) # Correct position for planetary aberration for i, a_pos in enumerate(pos): pos[i] = a_pos - (ltt * vel[i]) logger.debug("Earth->Asteroid [x,y,z]=%s" % pos) logger.debug("Earth->Asteroid [x,y,z]= %20.15E %20.15E %20.15E" % (pos[0], pos[1], pos[2])) logger.debug("Earth->Asteroid [xdot,ydot,zdot]=%s %s %s" % (vel[0]*86400.0,vel[1]*86400.0,vel[2]*86400.0)) # Convert Cartesian to RA, Dec (ra, dec) = S.sla_dcc2s(pos) logger.debug("ra,dec=%s %s" % (ra, dec)) ra = S.sla_dranrm(ra) logger.debug("ra,dec=%s %s" % (ra, dec)) (rsign, ra_geo_deg) = S.sla_dr2tf(2, ra) (dsign, dec_geo_deg) = S.sla_dr2af(1, dec) # Compute r, the Sun-Target distance. Correct for light travel time first cposx = pv[0] - (ltt * pv[3]) cposy = pv[1] - (ltt * pv[4]) cposz = pv[2] - (ltt * pv[5]) r = sqrt(cposx*cposx + cposy*cposy + cposz*cposz) logger.debug("r (AU) =%s" % r) # Compute R, the Earth-Sun distance. (Only actually need R^2 for the mag. formula) es_Rsq = (e_pos_hel[0]*e_pos_hel[0] + e_pos_hel[1]*e_pos_hel[1] + e_pos_hel[2]*e_pos_hel[2]) logger.debug("R (AU) =%s" % sqrt(es_Rsq)) logger.debug("delta (AU)=%s" % delta) # Compute sky motion sky_vel = compute_relative_velocity_vectors(e_pos_hel, e_vel_hel, pos, vel, delta, dbg) logger.debug("vel1, vel2, r= %15.10lf %15.10lf %15.10lf" % (sky_vel[1], sky_vel[2], delta)) logger.debug("vel1, vel2, r= %15.10e %15.10e %15.10lf\n" % (sky_vel[1], sky_vel[2], delta)) total_motion, sky_pa, ra_motion, dec_motion = compute_sky_motion(sky_vel, delta, dbg) mag = -99 # Compute phase angle, beta (Sun-Target-Earth angle) beta = compute_phase_angle(r, delta, es_Rsq) if comet == True: # Calculate magnitude of comet # Here 'H' is the absolute magnitude, 'kappa' the slope parameter defined in Meeus # _Astronomical Algorithms_ p. 231, is equal to 2.5 times the 'G' read from the elements if p_orbelems['H'] and p_orbelems['G']: mag = p_orbelems['H'] + 5.0 * log10(delta) + 2.5 * p_orbelems['G'] * log10(r) else: phi1 = exp(-3.33 * (tan(beta/2.0))**0.63) phi2 = exp(-1.87 * (tan(beta/2.0))**1.22) # logger.debug("Phi1, phi2=%s" % phi1,phi2) # Calculate magnitude of object if p_orbelems['H'] and p_orbelems['G']: mag = p_orbelems['H'] + 5.0 * log10(r * delta) - \ (2.5 * log10((1.0 - p_orbelems['G'])*phi1 + p_orbelems['G']*phi2)) az_rad, alt_rad = moon_alt_az(d, ra, dec, site_long, site_lat, site_hgt) airmass = S.sla_airmas((pi/2.0)-alt_rad) alt_deg = degrees(alt_rad) phaseang_deg = degrees(beta) # if display: print " %02.2dh %02.2dm %02.2d.%02.2ds %s%02.2dd %02.2d\' %02.2d.%01.1d\" V=%.1f %5.2f %.1f % 7.3f %8.4f" % ( ra_geo_deg[0], if display: print " %02.2d %02.2d %02.2d.%02.2d %s%02.2d %02.2d %02.2d.%01.1d %02.1f V=%.1f %5.2f %.1f % 7.3f %8.4f" % ( ra_geo_deg[0], ra_geo_deg[1], ra_geo_deg[2], ra_geo_deg[3], dsign, dec_geo_deg[0], dec_geo_deg[1], dec_geo_deg[2], dec_geo_deg[3], phaseang_deg, mag, total_motion, sky_pa, alt_deg, airmass ) # Compute South Polar Distance from Dec dec_arcsec_decimal = dec_geo_deg[2] + dec_geo_deg[3] dec_arcmin_decimal = dec_geo_deg[1] + (dec_arcsec_decimal/60.) dec_deg_decimal = dec_geo_deg[0] + (dec_arcmin_decimal/60.) if '+' in dsign: spd = 90. + dec_deg_decimal elif '-' in dsign: spd = 90. - dec_deg_decimal else: spd = None emp_line = (d, ra, dec, mag, total_motion, alt_deg, spd, beta) return emp_line