Beispiel #1
0
def altaz2hadec(alt,az) :
    """
     Convert Altitude, Azimuth to HA, Dec at Kitt Peak elevation

    Args:
        alt: float or 1D np.array altitude in degrees
        az: float or 1D np.array azimuth in degrees

    Returns: ha, dec
        ha: float or 1D np.array Hour Angle in degrees
        dec: float or 1D np.array Hour Angle in degrees
    """
    salt,calt = sincosd(alt)
    saz,caz   = sincosd(az)
    slat,clat = sincosd(LATITUDE)
    ha  = arctan2d( -saz*calt, -caz*slat*calt+salt*clat)
    dec = arcsind(slat*salt+clat*calt*caz)
    return ha,dec
Beispiel #2
0
def xy2hadec(x,y,tel_ha,tel_dec) :
    """
    Convert tangent plane x,y to HA,Dec given a telescope pointing tel_ha, tel_dec

    Args:
        x: float or 1D np.array with tangent plane coord.
        y: float or 1D np.array with tangent plane coord.
        tel_ha: float; telescope pointing Hour Angle in degrees
        tel_dec: float; telescope pointing Dec in degrees

    Returns: HA, Dec  float or 1D np.array in degrees
    """
    sh,ch = sincosd(tel_ha)
    sd,cd = sincosd(tel_dec)
    rh=np.array([[ch,-sh,0],[sh,ch,0],[0,0,1]])
    rd=np.array([[sd,0,cd],[0,1,0],[-cd,0,sd]])
    z = np.sqrt(1-x**2-y**2)
    xyz = rh.dot(rd.dot(np.array([-y,x,z])))
    return getLONLAT(xyz)
Beispiel #3
0
def hadec2xy(ha,dec,tel_ha,tel_dec) :
    """
     Convert HA,Dec to tangent plane x,y given a telescope pointing tel_ha, tel_dec

    Args:
        ha: float or 1D np.array Hour Angle in degrees
        dec: float or 1D np.array Hour Angle in degrees (same size as ha)
        tel_ha: float; telescope pointing Hour Angle in degrees
        tel_dec: float; telescope pointing Dec in degrees

    Returns: x y float or 1D np.array
    """
    xyz = getXYZ(ha,dec)
    sh,ch = sincosd(tel_ha)
    sd,cd = sincosd(tel_dec)
    rh=np.array([[ch,sh,0],[-sh,ch,0],[0,0,1]]) # rotation about HA axis
    rd=np.array([[sd,0,-cd],[0,1,0],[+cd,0,sd]]) # rotation about Dec axis
    tmp = rd.dot(rh.dot(xyz))
    x=tmp[1]
    y=-tmp[0]
    return x,y
Beispiel #4
0
def hadec2altaz(ha,dec) :
    """
     Convert HA,Dec to Altitude , Azimuth at Kitt Peak elevation

    Args:
        ha: float or 1D np.array hour angle in degrees
        dec: float or 1D np.array declination in degrees

    Returns: alt, az
        alt: float or 1D np.array altitude in degrees
        az: float or 1D np.array azimuth in degrees
    """
    sha,cha   = sincosd(ha)
    sdec,cdec = sincosd(dec)
    slat,clat = sincosd(LATITUDE)
    x = - cha * cdec * slat + sdec * clat
    y = - sha * cdec
    z = cha * cdec * clat + sdec * slat
    r = np.hypot(x, y)
    az  = arctan2d(y,x)
    alt = arctan2d(z,r)
    return alt,az
Beispiel #5
0
def fiberassign_radec2xy_cs5(ra,
                             dec,
                             tile_ra,
                             tile_dec,
                             tile_mjd,
                             tile_ha,
                             tile_fieldrot,
                             adc1=None,
                             adc2=None,
                             to_platemaker=True):
    """Computes X Y focal plane coordinates of targets in CS5 coordinate system.
    Args:
      ra  : 1D numpy.array with target RA in degrees (need an array of points to compute the field rotation)
      dec : 1D numpy.array with target Dec in degrees, same size as ra
      tile_ra : float, RA of tile center in degrees, such that after pointing and ADC shift corrections, this corresponds to X=0,Y=0
      tile_dec : float, Dec of tile center in degrees, such that after pointing and ADC shift corrections, this corresponds to X=0,Y=0
      tile_mjd : float, days, used for precession (does not need to be super accurate)
      tile_ha :  float, hour angle of observation, in degrees
      tile_fieldrot :  float, design/requested field rotation, in degrees
      adc1 : optional, float, ADC1 angle in degrees: by default it is computed based on the HA and Dec.
      adc2 : optional, float, ADC2 angle in degrees: by default it is computed based on the HA and Dec.
      to_platemaker : assume output coordinates are in platemaker system and use dm2pm transform
    Returns xfp,yfp, focal plane coordinates in mm in CS5, 1D numpy arrays of same size as ra,dec
    """

    assert (ra.size == dec.size)

    # LST from HA
    lst = tile_ha + tile_ra

    if ((adc1 is None) and (adc2 is not None)) or ((adc1 is not None) and
                                                   (adc2 is None)):
        raise ValueError("either set both adc angles or none")

    if adc1 is None:
        adc1, adc2 = pm_get_adc_angles(tile_ha, tile_dec)

    # start with pointing = tile center
    tel_ra = tile_ra + 0.
    tel_dec = tile_dec + 0.

    # tune telescope pointing given ADC angle
    # in order to fp coordinates of tile RA and DEC, it's not zero because of the ADC angles
    for _ in range(2):

        xtan, ytan = radec2tan(np.array([tile_ra]),
                               np.array([tile_dec]),
                               tel_ra,
                               tel_dec,
                               tile_mjd,
                               lst,
                               hexrot_deg=0)
        xfp_0, yfp_0 = tan2fp(xtan, ytan, adc1, adc2)  #mm
        #print("Temp tile center in FP coordinates = {},{} mm".format(xfp_0[0],yfp_0[0]))

        # numeric derivative
        eps = 1. / 3600.  #
        xtan, ytan = radec2tan(np.array([tile_ra + eps]),
                               np.array([tile_dec]),
                               tel_ra,
                               tel_dec,
                               tile_mjd,
                               lst,
                               hexrot_deg=0)
        xfp_dra, yfp_dra = tan2fp(xtan, ytan, adc1, adc2)  #mm
        xtan, ytan = radec2tan(np.array([tile_ra]),
                               np.array([tile_dec + eps]),
                               tel_ra,
                               tel_dec,
                               tile_mjd,
                               lst,
                               hexrot_deg=0)
        xfp_ddec, yfp_ddec = tan2fp(xtan, ytan, adc1, adc2)  #mm
        dxdra = (xfp_dra[0] - xfp_0[0]) / eps
        dydra = (yfp_dra[0] - yfp_0[0]) / eps
        dxddec = (xfp_ddec[0] - xfp_0[0]) / eps
        dyddec = (yfp_ddec[0] - yfp_0[0]) / eps
        J = [[dxdra, dxddec], [dydra, dyddec]]

        # solve linear system to get tile RA Dec at center of fov
        Jinv = np.linalg.inv(J)
        X = Jinv.dot([xfp_0[0], yfp_0[0]])
        dra = X[0]
        ddec = X[1]

        # apply offset to telescope pointing
        tel_ra += dra
        tel_dec += ddec

    # verify
    xtan, ytan = radec2tan(np.array([tile_ra]),
                           np.array([tile_dec]),
                           tel_ra,
                           tel_dec,
                           tile_mjd,
                           lst,
                           hexrot_deg=0)
    xfp_0, yfp_0 = tan2fp(xtan, ytan, adc1, adc2)  #mm
    print("Tile center in FP coordinates = {},{} mm".format(
        xfp_0[0], yfp_0[0]))

    # now compute coordinates of all targets
    xtan, ytan = radec2tan(ra,
                           dec,
                           tel_ra,
                           tel_dec,
                           tile_mjd,
                           lst,
                           hexrot_deg=0)
    tmp_xfp, tmp_yfp = tan2fp(xtan, ytan, adc1, adc2)

    if to_platemaker:
        # apply tranformation from desimeter to platemater
        dm2pm = DM2PM.read(dm2pm_filename())
        tmp_xfp, tmp_yfp = dm2pm.dm2pm(tmp_xfp, tmp_yfp)

    # measure field rotation
    tmp_fieldrot = _measure_fieldrot_deg(-ra, dec, -tile_ra, tile_dec, tmp_xfp,
                                         tmp_yfp)

    # apply field rotation to match request
    drot = tile_fieldrot - tmp_fieldrot
    s, c = sincosd(drot)
    xfp = c * tmp_xfp - s * tmp_yfp
    yfp = s * tmp_xfp + c * tmp_yfp

    # verify
    realised_fieldrot = _measure_fieldrot_deg(-ra, dec, -tile_ra, tile_dec,
                                              xfp, yfp)
    print("Requested fieldrot={:3.1f} arcsec delta={:3.1f} arcsec".format(
        tile_fieldrot * 3600., (tile_fieldrot - realised_fieldrot) * 3600.))

    return xfp, yfp
Beispiel #6
0
def vecZ(zdeg):  # For positive zdeg=+az: +x=>+y; +y=>-x.
    s,c = sincosd(zdeg)
    return np.array([[c,-s,0], [+s,c,0], [0,0,1]])
Beispiel #7
0
def vecY(ydeg):  # For positive ydeg=-elev: +z=>+x; +x=>-z.
    # do not overlook this minus sign: positive ydeg pitches downward.
    s,c = sincosd(ydeg)
    return np.array([[c,0,+s], [0,1,0], [-s,0,c]])
Beispiel #8
0
def vecX(xdeg):  # For positive xdeg=cwRoll: +y=>+z; +z=>-y.
    s,c = sincosd(xdeg)
    return np.array([[1,0,0], [0,c,-s], [0,+s,c]])
Beispiel #9
0
def tan2radec(x_tan,y_tan,tel_ra,tel_dec,mjd,lst_deg,hexrot_deg, precession = True, aberration = True, polar_misalignment = True, use_astropy = False) :
    """
    Convert ICRS coordinates to tangent plane coordinates

    Args:
        xtan: float or 1D np.array with tangent plane coordinates
        ytan: float or 1D np.array with tangent plane coordinates
        tel_ra: float, in degrees, telescope pointing RA
        tel_dec: float, in degrees, telescope pointing Dec
        mjd: float, Modified Julian Date of observation, in days
        lst_deg: float, local sidereal time, in degrees
        hexrot_deg: float, hexapod rotation angle, in degrees

    Returns RA,Dec in ICRS system (hopefully)

    Optional arguments:
        aberration: boolean; compute aberration if True
        polar_misalignment: boolean; compute polar misalignment if True
        use_astropy: boolean; use astropy coordinates for precession and aberration if True
    """

    # undo hexapod rotation
    shex,chex = sincosd(hexrot_deg)
    x =  chex*x_tan+shex*y_tan
    y = -shex*x_tan+chex*y_tan

    # need to apply precession ... etc to telescope pointing to interpret the x,y
    if precession :
        tel_ra,tel_dec = apply_precession_from_icrs(tel_ra, tel_dec, mjd, use_astropy)
    if aberration :
        tel_ra,tel_dec = apply_aberration(tel_ra,tel_dec,mjd, use_astropy)

    tel_ha = lst_deg - tel_ra

    if polar_misalignment :
        polar_misalignment_matrix = compute_polar_misalignment_rotation_matrix(me_arcsec=ME_ARCSEC,ma_arcsec=MA_ARCSEC)
        tel_ha,tel_dec = getLONLAT(polar_misalignment_matrix.dot(getXYZ(tel_ha,tel_dec)))

    # we need to apply refraction for the telescope pointing to interpret the x,y
    tel_alt,tel_az = hadec2altaz(tel_ha,tel_dec)
    # apply refraction
    refracted_tel_alt = apply_refraction(tel_alt)
    # back to ha,dec
    refracted_tel_ha,refracted_tel_dec  = altaz2hadec(refracted_tel_alt,tel_az)
    # now convert x,y to ha,dec
    refracted_ha,refracted_dec = xy2hadec(x,y,refracted_tel_ha,refracted_tel_dec)

    # alt,az
    alt,az = hadec2altaz(refracted_ha,refracted_dec)

    # undo refraction
    alt = undo_refraction(alt)

    # back to ha,dec
    ha,dec  = altaz2hadec(alt,az)

    # now polar mis-alignment
    if polar_misalignment :
        # inverse matrix
        polar_misalignment_matrix = compute_polar_misalignment_rotation_matrix(me_arcsec=-ME_ARCSEC,ma_arcsec=-MA_ARCSEC)
        ha,dec  = getLONLAT(polar_misalignment_matrix.dot(getXYZ(ha,dec)))

    # ra
    ra = lst_deg - ha

    if aberration :
        ra,dec = undo_aberration(ra,dec,mjd, use_astropy)

    if precession :
        ra,dec = undo_precession_from_icrs(ra, dec, mjd, use_astropy)

    return ra,dec
Beispiel #10
0
def radec2tan(ra,dec,tel_ra,tel_dec,mjd,lst_deg,hexrot_deg, precession = True, aberration = True, polar_misalignment = True, use_astropy = False) :
    """
    Convert ICRS coordinates to tangent plane coordinates

    Args:
        ra: float or 1D np.array with RA in degrees
        dec: float or 1D np.array with RA in degrees
        tel_ra: float, in degrees, telescope pointing RA
        tel_dec: float, in degrees, telescope pointing Dec
        mjd: float, Modified Julian Date of observation, in days
        lst_deg: float, local sidereal time, in degrees
        hexrot_deg: float, hexapod rotation angle, in degrees

    Returns x_tan,y_tan , tangent plane coordinates:
        x_tan = sin(theta)*cos(phi) : float on np.array (same shape as input ra,dec)
        y_tan = sin(theta)*sin(phi) : float on np.array (same shape as input ra,dec)

        where theta,phi are polar coordinates. theta=0 for along the telescope
        pointing. phi=0 for a star with the same Dec as the telescope
        pointing but a larger HA (or smaller RA).

    Optional arguments:
        aberration: boolean; compute aberration if True
        polar_misalignment: boolean; compute polar misalignment if True
        use_astropy: boolean; use astropy coordinates for precession and aberration if True
    """
    if precession :
        ra,dec = apply_precession_from_icrs(ra, dec, mjd, use_astropy)
        tel_ra,tel_dec = apply_precession_from_icrs(tel_ra, tel_dec, mjd, use_astropy)


    if aberration :
        ra,dec = apply_aberration(ra,dec,mjd, use_astropy)
        tel_ra,tel_dec = apply_aberration(tel_ra,tel_dec,mjd, use_astropy)

    # ha,dec
    ha     = lst_deg - ra
    tel_ha = lst_deg - tel_ra

    if polar_misalignment :
        # rotate
        polar_misalignment_matrix = compute_polar_misalignment_rotation_matrix(me_arcsec=ME_ARCSEC,ma_arcsec=MA_ARCSEC)
        ha,dec = getLONLAT(polar_misalignment_matrix.dot(getXYZ(ha,dec)))
        tel_ha,tel_dec = getLONLAT(polar_misalignment_matrix.dot(getXYZ(tel_ha,tel_dec)))

    # alt,az
    alt,az = hadec2altaz(ha,dec)
    tel_alt,tel_az = hadec2altaz(tel_ha,tel_dec)

    # apply refraction
    alt = apply_refraction(alt)
    tel_alt = apply_refraction(tel_alt)

    # convert back to ha,dec
    ha,dec  = altaz2hadec(alt,az)
    tel_ha,tel_dec  = altaz2hadec(tel_alt,tel_az)

    # tangent plane
    x,y = hadec2xy(ha,dec,tel_ha,tel_dec)

    # hexapod rotation
    shex,chex = sincosd(hexrot_deg)

    return chex*x-shex*y , +shex*x+chex*y