コード例 #1
0
    def read_guide_stars_catalog(self, filename, max_sep_arcsec=2.):

        log = get_logger()
        log.info("reading guide stars in {}".format(filename))

        # here we could do some conversion of column names
        catalog = Table.read(filename)

        if (not "xcentroid" in catalog.dtype.names) or (
                not "ra_gaia" in catalog.dtype.names):
            log.error(
                "I can only deal with Aaron's catalogs with columns xcentroid,ycentroid,ra_gaia,dec_gaia, sorry"
            )
            raise RuntimeError(
                "I can only deal with Aaron's catalogs with columns xcentroid,ycentroid,ra_gaia,dec_gaia, sorry"
            )

        max_sep_arcsec = 2.
        log.info(
            "selection stars for which we have a good match (< {} arcsec)".
            format(max_sep_arcsec))

        dra = (catalog["ra"] - catalog["ra_gaia"]) * cosd(
            catalog["dec_gaia"]) * 3600.  # arcsec
        ddec = (catalog["dec"] - catalog["dec_gaia"]) * 3600.  # arcsec
        dr = np.hypot(dra, ddec)
        selection = (dr < 2)  # arcsec
        if np.sum(selection) == 0:
            log.error("no star is matched with sufficient precision!")
            raise RuntimeError("no star is matched with sufficient precision!")

        return catalog[:][selection]
コード例 #2
0
    def test_tancorr_fit(self):

        tcorr = TanCorr()

        tel_ha1 = 12.
        tel_dec1 = 80.

        npts = 24
        x1 = 0.1 * np.random.uniform(size=npts)
        y1 = 0.1 * np.random.uniform(size=npts)
        ha, dec = xy2hadec(x1, y1, tel_ha1, tel_dec1)

        true_dha_arcsec = 3.
        true_ddec_arcsec = 1.

        tel_ha2 = tel_ha1 + true_dha_arcsec / 3600.
        tel_dec2 = tel_dec1 + true_ddec_arcsec / 3600.
        x2, y2 = hadec2xy(ha, dec, tel_ha2, tel_dec2)

        tcorr.fit(x1, y1, x2, y2)
        meas_dha_arcsec = tcorr.dha / cosd(tel_dec1) * 3600.
        meas_ddec_arcsec = tcorr.ddec * 3600.

        assert (np.abs(true_dha_arcsec - meas_dha_arcsec) < 0.01)
        assert (np.abs(true_ddec_arcsec - meas_ddec_arcsec) < 0.01)
コード例 #3
0
    def test_it(self):
        print("Testing fiberassign_radec2xy_cs5")
        nrand = 500
        square_side_in_degrees = 1.5
        xtan = np.pi / 180. * square_side_in_degrees * (
            np.random.uniform(size=nrand) - 0.5)
        ytan = np.pi / 180. * square_side_in_degrees * (
            np.random.uniform(size=nrand) - 0.5)
        tile_ra = 12.
        tile_dec = 40.
        tile_ha = 1
        tile_mjd = 59344.4
        tile_fieldrot = -130 / 3600.  # deg
        lst = tile_ra + tile_ha

        ha, dec = xy2hadec(xtan, ytan, tile_ha, tile_dec)
        ra = lst - ha

        x, y = fiberassign_radec2xy_cs5(ra, dec, tile_ra, tile_dec, tile_mjd,
                                        tile_ha, tile_fieldrot)

        print("Testing fiberassign_cs5_xy2radec")
        ra2, dec2 = fiberassign_cs5_xy2radec(x, y, tile_ra, tile_dec, tile_mjd,
                                             tile_ha, tile_fieldrot)

        drad = cosd(dec) * (ra2 - ra)
        ddec = (dec2 - dec)
        distdeg = np.sqrt(drad**2 + ddec**2)
        rms = (np.sqrt(np.mean(distdeg**2)))
        print("rms={} arcsec".format(rms * 3600.))
        assert (rms * 3600. < 0.1)

        print("Testing fiberassign_radec2xy_flat")
        x, y = fiberassign_radec2xy_flat(ra, dec, tile_ra, tile_dec, tile_mjd,
                                         tile_ha, tile_fieldrot)

        print("Testing fiberassign_flat_xy2radec")
        ra2, dec2 = fiberassign_flat_xy2radec(x, y, tile_ra, tile_dec,
                                              tile_mjd, tile_ha, tile_fieldrot)

        drad = cosd(dec) * (ra2 - ra)
        ddec = (dec2 - dec)
        distdeg = np.sqrt(drad**2 + ddec**2)
        rms = (np.sqrt(np.mean(distdeg**2)))
        print("rms={} arcsec".format(rms * 3600.))
        assert (rms * 3600. < 0.1)
コード例 #4
0
def qs2xy(q, s):
    '''angular q,s on curved focal surface -> focal tangent plane x,y

    Args:
        q: angle in degrees
        s: focal surface radial distance in mm

    Returns (x, y) cartesian location on focal tangent plane in mm

    Notes: (x,y) are in the "CS5" DESI coordinate system tangent plane to
    the curved focal surface.  q is the radial angle measured counter-clockwise
    from the x-axis; s is the radial distance along the curved focal surface;
    it is *not* sqrt(x**2 + y**2).  (q,s) are the preferred coordinates for
    the DESI focal plane hardware engineering team.
    '''
    r = s2r(s)
    x = r * cosd(q)
    y = r * sind(q)
    return x, y
コード例 #5
0
    def fit_tancorr(self, catalog, mjd=None, hexrot_deg=None, lst=None):
        log = get_logger()

        x_gfa = catalog["xcentroid"]
        y_gfa = catalog["ycentroid"]
        ra_gaia = catalog["ra_gaia"]
        dec_gaia = catalog["dec_gaia"]

        # mjd,hexprot_deg,lst could have been set before
        if mjd is not None:
            self.mjd = mjd
            log.info("Use argument MJD={}".format(self.mjd))
        elif "mjd_obs" in catalog.keys():
            self.mjd = np.mean(catalog["mjd_obs"])
            log.info("Use 'mjd_obs' in catalog, MJD={}".format(self.mjd))
        elif self.mjd is None:
            log.error("mjd is None")
            raise RuntimeError("mjd is None")
        else:
            log.info("Use MJD={}".format(self.mjd))

        if hexrot_deg is not None:
            self.hexrot_deg = hexrot_deg
        elif self.hexrot_deg is None:
            log.error("hexrot_deg is None")
            raise RuntimeError("hexrot_deg is None")

        if lst is not None:
            self.lst = lst
        elif self.lst is None:
            from desimeter.time import mjd2lst
            log.warning("Compute LST from MJD={}".format(self.mjd))
            self.lst = mjd2lst(self.mjd)
        log.info("Use LST={}".format(self.lst))

        # first transfo: gfa2fp
        x_fp, y_fp = self.all_gfa2fp(x_gfa,
                                     y_gfa,
                                     petal_loc=catalog["petal_loc"])

        # keep only petal data for which we have the metrology
        selection = (x_fp != 0)
        x_gfa = x_gfa[selection]
        y_gfa = y_gfa[selection]
        x_fp = x_fp[selection]
        y_fp = y_fp[selection]
        ra_gaia = ra_gaia[selection]
        dec_gaia = dec_gaia[selection]

        # transform focal plane to tangent plane
        x_tan_meas, y_tan_meas = fp2tan(x_fp, y_fp, self.adc1, self.adc2)

        correction = TanCorr()

        for _ in range(
                3
        ):  # loop because change of pointing induces a rotation of the field

            # we transform GAIA coordinates to the tangent plane
            x_tan_gaia, y_tan_gaia = radec2tan(
                ra_gaia,
                dec_gaia,
                self.ra,
                self.dec,
                mjd=self.mjd,
                lst_deg=self.lst,
                hexrot_deg=self.hexrot_deg,
                precession=self.precession,
                aberration=self.aberration,
                polar_misalignment=self.polar_misalignment)

            # now that we have both sets of coordinates, we fit a transformation from one to the other
            correction.fit(x_tan_meas, y_tan_meas, x_tan_gaia, y_tan_gaia)

            # opposite sign for the telescope offset because I have converted GAIA RA Dec to tangent plane ...
            self.dec -= correction.ddec
            self.ra += correction.dha / cosd(self.dec)  # HA = LST-RA

        # save params to this
        log.info("RMS coord. residual = {:3.2f} arcsec".format(
            correction.rms_arcsec))
        log.info("Rotation angle (field rot ZP) ={:4.3f} deg".format(
            correction.rot_deg))
        log.info("Pointing correction dHA={:3.2f} arcsec, dDec={:3.2f} arcsec".
                 format(correction.dha * 3600., correction.ddec * 3600.))
        log.info("Scales sxx={:5.4f} syy={:5.4f} sxy={:5.4f}".format(
            correction.sxx, correction.syy, correction.sxy))

        # now I just copy the correction parameters in this class
        self.sxx = correction.sxx
        self.syy = correction.syy
        self.sxy = correction.sxy
        self.fieldrot_zp_deg = correction.rot_deg
        self.nstars = correction.nstars
        self.rms_arcsec = correction.rms_arcsec

        # I now derive the field rotation
        self.fieldrot_deg = self.compute_fieldrot()
コード例 #6
0
ファイル: fieldmodel.py プロジェクト: desihub/desimeter
    def read_guide_stars_catalog(self, filename, max_sep_arcsec=2.):

        log = get_logger()
        log.info("reading guide stars in {}".format(filename))

        # here we could do some conversion of column names
        catalog = Table.read(filename)

        if "mjd_obs" in catalog.dtype.names:
            self.mjd = np.mean(catalog["mjd_obs"])
            log.info("use mjd={} from catalog['mjd_obs']".format(self.mjd))

        if (not "xcentroid" in catalog.dtype.names) or (
                not "ra_gaia" in catalog.dtype.names):
            log.error(
                "I can only deal with Aaron's catalogs with columns xcentroid,ycentroid,ra_gaia,dec_gaia, sorry"
            )
            raise RuntimeError(
                "I can only deal with Aaron's catalogs with columns xcentroid,ycentroid,ra_gaia,dec_gaia, sorry"
            )

        log.info(
            "selection stars for which we have a good match (< {} arcsec)".
            format(max_sep_arcsec))

        if all([_ in catalog.columns for _ in ['pmra', 'pmdec', 'ref_epoch']]):

            if self.mjd is None:
                log.error(
                    "Cannot compute proper motion correction because mjd=None")
                raise RuntimeError(
                    "Cannot compute proper motion correction because mjd=None")

            # if proper motions and reference epochs are there
            pmra = catalog['pmra']
            pmdec = catalog['pmdec']
            # if unknown, zero out the pms
            pmra[~np.isfinite(pmra)] = 0
            pmdec[~np.isfinite(pmdec)] = 0

            cur_year = Time(self.mjd, format='mjd').to_value(format='jyear')
            # observation time in decimal years (like 2020.3)
            ref_epoch = catalog['ref_epoch']
            dra = (cur_year - ref_epoch) * pmra / 3600e3 / cosd(
                catalog['dec_gaia'])
            ddec = (cur_year - ref_epoch) * pmdec / 3600e3

            # add pm and rename columns
            catalog['ra_gaia'] += dra
            catalog['dec_gaia'] += ddec
            catalog.rename_column('ra_gaia', 'ra_gaia_with_pm')
            catalog.rename_column('dec_gaia', 'dec_gaia_with_pm')
            ra_column = 'ra_gaia_with_pm'
            dec_column = 'dec_gaia_with_pm'

        else:
            ra_column = 'ra_gaia'
            dec_column = 'dec_gaia'
            log.warning("No proper motion info in catalog")

        match_dra = (catalog["ra"] - catalog[ra_column]) * cosd(
            catalog[dec_column]) * 3600.  # arcsec
        match_ddec = (catalog["dec"] - catalog[dec_column]) * 3600.  # arcsec

        dr = np.hypot(match_dra, match_ddec)
        selection = (dr < max_sep_arcsec)  # arcsec
        if np.sum(selection) == 0:
            log.error("no star is matched with sufficient precision!")
            raise RuntimeError("no star is matched with sufficient precision!")

        return catalog[:][selection]