Example #1
0
def moon_alt_az(date, moon_app_ra, moon_app_dec, obsvr_long, obsvr_lat,\
    obsvr_hgt, dbg=False):
    '''Calculate Moon's Azimuth, Altitude (returned in radians).
    No refraction or polar motion is assumed.'''

# No atmospheric refraction...
    airless = True
    (temp_k, pres_mb, rel_humid, wavel, tlr) = atmos_params(airless)

# Assume no polar motion
    xp = yp = 0.0

# Compute MJD_UTC
    mjd_utc = datetime2mjd_utc(date)
    logger.debug(mjd_utc)
# Compute UT1-UTC

    dut = ut1_minus_utc(mjd_utc)
    logger.debug(dut)
# Perform apparent->observed place transformation
    (obs_az, obs_zd, obs_ha, obs_dec, obs_ra) = S.sla_aop(moon_app_ra, moon_app_dec,\
        mjd_utc, dut, obsvr_long, obsvr_lat, obsvr_hgt, xp, yp, \
        temp_k, pres_mb, rel_humid, wavel, tlr)

# Normalize azimuth into range 0..2PI
    obs_az = S.sla_ranorm(obs_az)
# Convert zenith distance to altitude (assumes no depression of the horizon
# due to observers' elevation above sea level)

    obs_alt = (pi/2.0)-obs_zd
    logger.debug("Az, ZD, Alt=%f %f %f" % (obs_az, obs_zd, obs_alt))
    return (obs_az, obs_alt)
Example #2
0
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
Example #3
0
def accurate_astro_darkness(sitecode, utc_date, debug=False):

# Convert passed UTC date to MJD and then Julian centuries

    mjd_utc = datetime2mjd_utc(utc_date)
    T = (mjd_utc - 51544.5)/36525.0

# Mean longitude of the Sun
    sun_mean_long = (280.46645 + T * (36000.76983 + T * 0.0003032) ) % 360

# Mean anomaly of the Sun
    sun_mean_anom = (357.52910 + T * (35999.05030 - T * (0.0001559 - 0.00000048 * T ) ) ) % 360

# Earth's eccentricity
    earth_e = 0.016708617 - T * (0.000042037 - T * 0.0000001236)

# Sun's equation of the center
    sun_eqcent = (1.914600 - T * (0.004817 - 0.000014 * T)) * sin(radians(sun_mean_anom)) +\
                 (0.019993 - T * 0.000101) * sin(2.0 *radians(sun_mean_anom)) +\
                 0.000290 * sin(3.0 *radians(sun_mean_anom))
# Sun's true longitude
    sun_true_long = sun_mean_long + sun_eqcent

# Obliquity of the ecliptic
    (dpsi, deps, eps0) = S.sla_nutc80(mjd_utc)

# Omega (Longitude of the ascending node of the Moon's orbit)
    omega = radians(125.04-1934.136*T)
    eps = degrees(eps0) + 0.00256*cos(omega)

    sun_app_long = sun_true_long - 0.00569-0.00478*sin(omega)
    sun_app_ra = atan2(cos(radians(eps)) * sin(radians(sun_app_long)), cos(radians(sun_app_long)))
    sun_app_ra = S.sla_dranrm(sun_app_ra)
    sun_app_dec = asin(sin(radians(eps)) * sin(radians(sun_app_long)))

    (site_name, site_long, site_lat, site_hgt) = get_sitepos(sitecode)

# Zenith distance of the Sun in degrees, normally 102 (nautical twilight as used
# in the scheduler) but could be 108 (astronomical twilight) or 90.5 (sunset)
# Here we use 105 (-15 degrees Sun altitude) to keep windows away from the
# brighter twilight which could be a problem for our faint targets.

    sun_zd = 105
    hourangle = degrees(acos(cos(radians(sun_zd))/(cos(site_lat)*cos(sun_app_dec))-tan(site_lat)*tan(sun_app_dec)))

    eqtime = 4.0 * (sun_mean_long - 0.0057183 - degrees(sun_app_ra) + degrees(dpsi) * cos(radians(eps)))
    solarnoon = (720-4*degrees(site_long)-eqtime)/1440
    sunrise = (solarnoon - hourangle*4/1440) % 1
    sunset = (solarnoon + hourangle*4/1440) % 1
    if debug: print solarnoon + hourangle*4/1440, solarnoon - hourangle*4/1440
    if debug: print sunset, sunrise

    if sunrise < sunset:
        sunrise = sunrise + 1
    if debug:
        to_return = [T, sun_mean_long, sun_mean_anom, earth_e, sun_eqcent, \
            sun_true_long, degrees(omega), sun_app_long, degrees(eps0), eps, \
            degrees(sun_app_ra), degrees(sun_app_dec), eqtime, hourangle]
        print to_return

    else:
        to_return = (utc_date+timedelta(days=sunset), utc_date+timedelta(days=sunrise))

    return to_return
Example #4
0
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