def geoFromICRS(icrsP, icrsV, agData):
    """
    Converts ICRS coordinates to apparent geocentric coordinates.
    
    Inputs:
    - icrsP(3)      ICRS cartesian position (au)
    - icrsV(3)      ICRS cartesian velocity (au/year) (e.g. proper motion and radial velocity)
    - agData        an AppGeoData object containing star-independent apparent geocentric data
    
    Returns:
    - appGeoP(3)    apparent geocentric cartesian position (au), a numpy.array
    
    Warnings:
    - Uses the approximation ICRS = FK5 J2000.
    - Not fully accurate for solar system objects.
    
    Details:
    The following approximations have been used:
    - FK5 J2000 is the same as ICRS
    - The annual aberration correction is only appropriate for stellar objects;
      it introduces unacceptable errors for solar system objects.
    - No correction is applied for the bending of light by sun's gravity.
      This introduces errors on the order of 0.02"
      at a distance of 20 degrees from the sun (Wallace, 1986)
    
    References:
    ABERAT, from the APPLE (J2000) subroutine library, U.S. Naval Observatory
    P.T. Wallace's MAPQK routine
    P.T. Wallace, "Proposals for Keck Tel. Point. Algorithms", 1986 (unpub.)
    "The Astronomical Almanac" for 1978, U.S. Naval Observatory
    """
    # make sure inputs are floating-point numpy arrays
    icrsP = numpy.asarray(icrsP, dtype=float)
    icrsV = numpy.asarray(icrsV, dtype=float)

    # correct for velocity and Earth's offset from the barycenter
    p2 = icrsP + icrsV * agData.dtPM - agData.bPos

    # here is where the correction for sun's gravity belongs

    # correct for annual aberration
    p2Dir, p2Mag = llv.vn(p2)
    dot2 = numpy.dot(p2Dir, agData.bVelC)
    # i.e. dot2 = p2 dot bVelC / |p2|
    # but handles |p2|=0 gracefully (by setting dot2 to 0)
    vfac = p2Mag * (1.0 + dot2 / (1.0 + agData.bGamma))
    p3 = ((p2 * agData.bGamma) + (vfac * agData.bVelC)) / (1.0 + dot2)

    # correct position for precession and nutation
    return numpy.dot(agData.pnMat, p3)
def geoFromICRS(icrsP, icrsV, agData):
    """
    Converts ICRS coordinates to apparent geocentric coordinates.
    
    Inputs:
    - icrsP(3)      ICRS cartesian position (au)
    - icrsV(3)      ICRS cartesian velocity (au/year) (e.g. proper motion and radial velocity)
    - agData        an AppGeoData object containing star-independent apparent geocentric data
    
    Returns:
    - appGeoP(3)    apparent geocentric cartesian position (au), a numpy.array
    
    Warnings:
    - Uses the approximation ICRS = FK5 J2000.
    - Not fully accurate for solar system objects.
    
    Details:
    The following approximations have been used:
    - FK5 J2000 is the same as ICRS
    - The annual aberration correction is only appropriate for stellar objects;
      it introduces unacceptable errors for solar system objects.
    - No correction is applied for the bending of light by sun's gravity.
      This introduces errors on the order of 0.02"
      at a distance of 20 degrees from the sun (Wallace, 1986)
    
    References:
    ABERAT, from the APPLE (J2000) subroutine library, U.S. Naval Observatory
    P.T. Wallace's MAPQK routine
    P.T. Wallace, "Proposals for Keck Tel. Point. Algorithms", 1986 (unpub.)
    "The Astronomical Almanac" for 1978, U.S. Naval Observatory
    """
    # make sure inputs are floating-point numpy arrays    
    icrsP = numpy.asarray(icrsP, dtype = float)
    icrsV = numpy.asarray(icrsV, dtype = float)
    
    # correct for velocity and Earth's offset from the barycenter
    p2 = icrsP + icrsV * agData.dtPM - agData.bPos
    
    # here is where the correction for sun's gravity belongs
    
    # correct for annual aberration
    p2Dir, p2Mag = llv.vn(p2)
    dot2 = numpy.dot(p2Dir, agData.bVelC)
    # i.e. dot2 = p2 dot bVelC / |p2|
    # but handles |p2|=0 gracefully (by setting dot2 to 0)
    vfac = p2Mag * (1.0 + dot2 / (1.0 + agData.bGamma))
    p3 = ((p2 * agData.bGamma) + (vfac * agData.bVelC)) / (1.0 + dot2)
    
    # correct position for precession and nutation
    return numpy.dot(agData.pnMat, p3)
Beispiel #3
0
def geoFromTopo(appTopoP, last, obsData):
    """
    Converts apparent topocentric coordinates to apparent geocentric coordinates.
    
    Inputs:
    - appTopoP(3)   apparent topocentric cartesian position (au) (az/alt)
    - last          local apparent sidereal time, as an angle (deg)
    - obsData       an ObserverData object
    
    Returns:
    - appGeoP(3)    apparent geocentric cartesian position (au) (RA/Dec), a numpy.array
    
    Warnings:
    Computation of diurnal aberration is slightly approximate (see notes below),
    but not enough to make a difference on the sky.
    
    References:
    see topoFromGeo (note: the variables are identical)
    """
    #  compute useful quantities
    sinLAST = RO.MathUtil.sind(last)
    cosLAST = RO.MathUtil.cosd(last)

    #  rotate apparent topocentric position to HA/Dec;
    posC = haDecFromAzAlt(appTopoP, obsData.latitude)

    #  remove correction for diurnal aberration
    #  following Pat Wallace's sla_OAPQK, the same equation is used
    #  as applying the correction, but the sign of obsData.diurAbVecMag is reversed
    cDir, cMag = llv.vn(posC)
    diurAbScaleCorr = 1.0 + (obsData.diurAbVecMag * cDir[1])
    posB = numpy.array((
        posC[0] * diurAbScaleCorr,
        (posC[1] - (obsData.diurAbVecMag * cMag)) * diurAbScaleCorr,
        posC[2] * diurAbScaleCorr,
    ))

    #  correct position for diurnal parallax (needed for planets, not stars)
    posA = posB + obsData.p

    #  rotate position from (-HA)/Dec to RA/Dec (but cartesian)
    return numpy.array((
        cosLAST * posA[0] - sinLAST * posA[1],
        sinLAST * posA[0] + cosLAST * posA[1],
        posA[2],
    ))
def geoFromTopo(appTopoP, last, obsData):
    """
    Converts apparent topocentric coordinates to apparent geocentric coordinates.
    
    Inputs:
    - appTopoP(3)   apparent topocentric cartesian position (au) (az/alt)
    - last          local apparent sidereal time, as an angle (deg)
    - obsData       an ObserverData object
    
    Returns:
    - appGeoP(3)    apparent geocentric cartesian position (au) (RA/Dec), a numpy.array
    
    Warnings:
    Computation of diurnal aberration is slightly approximate (see notes below),
    but not enough to make a difference on the sky.
    
    References:
    see topoFromGeo (note: the variables are identical)
    """
    #  compute useful quantities
    sinLAST = RO.MathUtil.sind (last)
    cosLAST = RO.MathUtil.cosd (last)

    #  rotate apparent topocentric position to HA/Dec;
    posC = haDecFromAzAlt (appTopoP, obsData.latitude)

    #  remove correction for diurnal aberration
    #  following Pat Wallace's sla_OAPQK, the same equation is used
    #  as applying the correction, but the sign of obsData.diurAbVecMag is reversed
    cDir, cMag = llv.vn(posC)
    diurAbScaleCorr = 1.0 + (obsData.diurAbVecMag * cDir[1])
    posB = numpy.array ((
         posC[0] * diurAbScaleCorr,
        (posC[1] - (obsData.diurAbVecMag * cMag)) * diurAbScaleCorr,
         posC[2] * diurAbScaleCorr,
    ))

    #  correct position for diurnal parallax (needed for planets, not stars)
    posA = posB + obsData.p

    #  rotate position from (-HA)/Dec to RA/Dec (but cartesian)
    return numpy.array((
        cosLAST * posA[0] - sinLAST * posA[1],
        sinLAST * posA[0] + cosLAST * posA[1],
        posA[2],
    ))
Beispiel #5
0
def topoFromGeo(appGeoP, last, obsData):
    """
    Converts apparent geocentric coordinates to apparent topocentric coordinates
    (not corrected for refraction).
    
    Inputs:
    - appGeoP(3)    current app. geocentric cartesian position (au) (RA/Dec)
    - last          local apparent sidereal time, as an angle (deg)
    - obsData       an ObserverData object
    
    Returns:
    - appTopo(3)    apparent topocentric cartesian position (au) (az/alt), a numpy.array
    
    Details:
    The following approximation is used:
    - pole wander is ignored
    
    References:
    P.T. Wallace, "Proposals for Keck Tel. Pointing Algorithms", 1986 (unpub)
    """
    sinLAST = RO.MathUtil.sind(last)
    cosLAST = RO.MathUtil.cosd(last)

    #  rotate position and offset to (-ha)/Dec (still cartesian, of course)
    posA = numpy.array((
        cosLAST * appGeoP[0] + sinLAST * appGeoP[1],
        -sinLAST * appGeoP[0] + cosLAST * appGeoP[1],
        appGeoP[2],
    ))

    #  correct position for diurnal parallax
    posB = posA - obsData.p

    #  correct position for diurnal aberration
    #  follows Pat Wallace's AOPQK
    bDir, bMag = llv.vn(posB)
    diurAbScaleCorr = 1.0 - (obsData.diurAbVecMag * bDir[1])
    posC = numpy.array((
        posB[0] * diurAbScaleCorr,
        (posB[1] + (obsData.diurAbVecMag * bMag)) * diurAbScaleCorr,
        posB[2] * diurAbScaleCorr,
    ))

    #  rotate position (posC) to alt/az;
    return azAltFromHADec(posC, obsData.latitude)
Beispiel #6
0
def topoFromGeo(appGeoP, last, obsData):
    """
    Converts apparent geocentric coordinates to apparent topocentric coordinates
    (not corrected for refraction).
    
    Inputs:
    - appGeoP(3)    current app. geocentric cartesian position (au) (RA/Dec)
    - last          local apparent sidereal time, as an angle (deg)
    - obsData       an ObserverData object
    
    Returns:
    - appTopo(3)    apparent topocentric cartesian position (au) (az/alt), a numpy.array
    
    Details:
    The following approximation is used:
    - pole wander is ignored
    
    References:
    P.T. Wallace, "Proposals for Keck Tel. Pointing Algorithms", 1986 (unpub)
    """
    sinLAST = RO.MathUtil.sind (last)
    cosLAST = RO.MathUtil.cosd (last)

    #  rotate position and offset to (-ha)/Dec (still cartesian, of course)
    posA = numpy.array((
         cosLAST * appGeoP[0] + sinLAST * appGeoP[1],
        -sinLAST * appGeoP[0] + cosLAST * appGeoP[1],
         appGeoP[2],
    ))

    #  correct position for diurnal parallax
    posB = posA - obsData.p

    #  correct position for diurnal aberration
    #  follows Pat Wallace's AOPQK
    bDir, bMag = llv.vn(posB)
    diurAbScaleCorr = 1.0 - (obsData.diurAbVecMag * bDir[1])
    posC = numpy.array ((
         posB[0] * diurAbScaleCorr,
        (posB[1] + (obsData.diurAbVecMag * bMag)) * diurAbScaleCorr,
         posB[2] * diurAbScaleCorr,
    ))

    #  rotate position (posC) to alt/az;
    return azAltFromHADec (posC, obsData.latitude)
Beispiel #7
0
def icrsFromGeo (appGeoP, agData):
    """
    Converts apparent geocentric coordinates to ICRS.
    
    Inputs:
    - appGeoP(3)    apparent geocentric cartesian position (au)
    - agData        an AppGeoData object containing star-independent
                    apparent geocentric data
    
    Returns
    - icrsP         ICRS cartesian position (au), a numpy.array
    
    Warnings:
    - Uses the approximation ICRS = FK5 J2000.0
    - Not fully accurate for solar system objects.
    - Requires iteration, so it will be slower than GeoFromICRS
    
    Error Conditions:
    Raises RuntimeError if iteration fails to converge.
    
    Details:
    The following approximations have been used:
    - The annual aberration correction is only appropriate for stellar objects;
      it introduces unacceptable errors for solar system objects.
    - No correction is applied for the bending of light by sun's gravity.
      This introduces errors on the order of 0.02"
      at a distance of 20 degrees from the sun (Wallace, 1986)
    
    icrsFromGeo performs the inverse transform of geoFromICRS.
    Unfortunately, some of the equations (e.g. annual aberration)
    are not invertable, so they have been solved by iteration.
    To make the code easier to follow, the symbols used here are identical
    to those used in GeoFromICRS.
    
    The convergence criterion is set by the magic numbers _MaxIter and _Accuracy.
    
    References:
    GeoFromICRS
    aberat, an APPLE (J2000) subroutine; U.S. Naval Observatory
    P.T. Wallace's MAPQK routine
    P.T. Wallace, "Proposals for Keck Tel. Point. Algorithms," 1986 (unpub.)
    "The Astronomical Almanac" for 1978, U.S. Naval Observatory
    """
    # compute constants needed to check iteration
    approxMagP = RO.MathUtil.vecMag(appGeoP)
    allowedErr = _Accuracy * approxMagP

    # correct position for nutation and precession
    p3 = numpy.dot(numpy.transpose(agData.pnMat), appGeoP)

    # iterively correct for annual aberration
    itNum = 1
    maxErr = approxMagP
    p2 = p3.copy()
    while (maxErr > allowedErr) and (itNum <= _MaxIter):
        itNum += 1
        p2Dir, p2Mag = llv.vn (p2)
        dot2 = numpy.dot(p2Dir, agData.bVelC)
        vfac = p2Mag * (1.0 + dot2 / (1.0 + agData.bGamma))
        oldP2 = p2.copy()
        p2 = (((1.0 + dot2) * p3) - (vfac * agData.bVelC)) / agData.bGamma
        maxErr = max (abs (p2 - oldP2))
    # if no convergence, complain and exit
    if (itNum > _MaxIter):
        raise RuntimeError('aberration correction failed to converge;' + \
            'after %s iterations; fractional error = %s, max allowed = %s' \
            % (_MaxIter, maxErr, allowedErr))

    # here is where the (iterative) correction for sun's gravity belongs

    # correct for Earth's offset from the barycenter
    return p2 + agData.bPos
Beispiel #8
0
def icrsFromGeo(appGeoP, agData):
    """
    Converts apparent geocentric coordinates to ICRS.
    
    Inputs:
    - appGeoP(3)    apparent geocentric cartesian position (au)
    - agData        an AppGeoData object containing star-independent
                    apparent geocentric data
    
    Returns
    - icrsP         ICRS cartesian position (au), a numpy.array
    
    Warnings:
    - Uses the approximation ICRS = FK5 J2000.0
    - Not fully accurate for solar system objects.
    - Requires iteration, so it will be slower than GeoFromICRS
    
    Error Conditions:
    Raises RuntimeError if iteration fails to converge.
    
    Details:
    The following approximations have been used:
    - The annual aberration correction is only appropriate for stellar objects;
      it introduces unacceptable errors for solar system objects.
    - No correction is applied for the bending of light by sun's gravity.
      This introduces errors on the order of 0.02"
      at a distance of 20 degrees from the sun (Wallace, 1986)
    
    icrsFromGeo performs the inverse transform of geoFromICRS.
    Unfortunately, some of the equations (e.g. annual aberration)
    are not invertable, so they have been solved by iteration.
    To make the code easier to follow, the symbols used here are identical
    to those used in GeoFromICRS.
    
    The convergence criterion is set by the magic numbers _MaxIter and _Accuracy.
    
    References:
    GeoFromICRS
    aberat, an APPLE (J2000) subroutine; U.S. Naval Observatory
    P.T. Wallace's MAPQK routine
    P.T. Wallace, "Proposals for Keck Tel. Point. Algorithms," 1986 (unpub.)
    "The Astronomical Almanac" for 1978, U.S. Naval Observatory
    """
    # compute constants needed to check iteration
    approxMagP = RO.MathUtil.vecMag(appGeoP)
    allowedErr = _Accuracy * approxMagP

    # correct position for nutation and precession
    p3 = numpy.dot(numpy.transpose(agData.pnMat), appGeoP)

    # iterively correct for annual aberration
    itNum = 1
    maxErr = approxMagP
    p2 = p3.copy()
    while (maxErr > allowedErr) and (itNum <= _MaxIter):
        itNum += 1
        p2Dir, p2Mag = llv.vn(p2)
        dot2 = numpy.dot(p2Dir, agData.bVelC)
        vfac = p2Mag * (1.0 + dot2 / (1.0 + agData.bGamma))
        oldP2 = p2.copy()
        p2 = (((1.0 + dot2) * p3) - (vfac * agData.bVelC)) / agData.bGamma
        maxErr = max(abs(p2 - oldP2))
    # if no convergence, complain and exit
    if (itNum > _MaxIter):
        raise RuntimeError('aberration correction failed to converge;' + \
            'after %s iterations; fractional error = %s, max allowed = %s' \
            % (_MaxIter, maxErr, allowedErr))

    # here is where the (iterative) correction for sun's gravity belongs

    # correct for Earth's offset from the barycenter
    return p2 + agData.bPos