Example #1
0
    def test_era_inverse(self):

        # Check a full forward/inverse cycle
        dt = datetime(2016, 4, 3, 2, 1, 0)
        t1 = ctime.datetime_to_unix(dt)
        era = ctime.unix_to_era(t1)
        t2 = ctime.era_to_unix(era, t1 - 3600.0)

        # Should be accurate at the 1 ms level
        self.assertAlmostEqual(t1, t2, 3)

        # Check a full forward/inverse cycle over a leap second boundary
        dt = datetime(2009, 1, 1, 3, 0, 0)
        t1 = ctime.datetime_to_unix(dt)
        era = ctime.unix_to_era(t1)
        t2 = ctime.era_to_unix(era, t1 - 6 * 3600.0)

        # Should be accurate at the 10 ms level
        self.assertAlmostEqual(t1, t2, 2)
Example #2
0
    def test_era_inverse(self):

        # Check a full forward/inverse cycle
        dt = datetime(2016, 4, 3, 2, 1, 0)
        t1 = ctime.datetime_to_unix(dt)
        era = ctime.unix_to_era(t1)
        t2 = ctime.era_to_unix(era, t1 - 3600.0)

        # Should be accurate at the 1 ms level
        self.assertAlmostEqual(t1, t2, 3)

        # Check a full forward/inverse cycle over a leap second boundary
        dt = datetime(2009, 1, 1, 3, 0, 0)
        t1 = ctime.datetime_to_unix(dt)
        era = ctime.unix_to_era(t1)
        t2 = ctime.era_to_unix(era, t1 - 6 * 3600.0)

        # Should be accurate at the 10 ms level
        self.assertAlmostEqual(t1, t2, 2)
Example #3
0
    def test_era_known(self):
        # Check an ERA calculated by caput.time against one calculated by
        # http://dc.zah.uni-heidelberg.de/apfs/times/q/form (note the latter
        # uses UT1, so we have maximum precision of 1s)

        dt = datetime(2016, 4, 3, 2, 1, 0)

        t1 = ctime.datetime_to_unix(dt)
        era1 = ctime.unix_to_era(t1)
        era2 = 221.0 + (52.0 + 50.828 / 60.0) / 60.0

        self.assertAlmostEqual(era1, era2, 3)

        # Test another one
        dt = datetime(2001, 2, 3, 4, 5, 6)

        t1 = ctime.datetime_to_unix(dt)
        era1 = ctime.unix_to_era(t1)
        era2 = 194.0 + (40.0 + 11.549 / 60.0) / 60.0

        self.assertAlmostEqual(era1, era2, 3)
Example #4
0
    def test_era_known(self):
        # Check an ERA calculated by caput.time against one calculated by
        # http://dc.zah.uni-heidelberg.de/apfs/times/q/form (note the latter
        # uses UT1, so we have maximum precision of 1s)

        dt = datetime(2016, 4, 3, 2, 1, 0)

        t1 = ctime.datetime_to_unix(dt)
        era1 = ctime.unix_to_era(t1)
        era2 = 221.0 + (52.0 + 50.828 / 60.0) / 60.0

        self.assertAlmostEqual(era1, era2, 3)

        # Test another one
        dt = datetime(2001, 2, 3, 4, 5, 6)

        t1 = ctime.datetime_to_unix(dt)
        era1 = ctime.unix_to_era(t1)
        era2 = 194.0 + (40.0 + 11.549 / 60.0) / 60.0

        self.assertAlmostEqual(era1, era2, 3)
Example #5
0
def sun_coord(unix_time, deg=True):

    date = ephemeris.ensure_unix(np.atleast_1d(unix_time))
    skyfield_time = ephemeris.unix_to_skyfield_time(date)
    ntime = date.size

    coord = np.zeros((ntime, 4), dtype=np.float32)

    planets = skyfield.api.load('de421.bsp')
    sun = planets['sun']

    observer = ephemeris._get_chime().skyfield_obs()

    apparent = observer.at(skyfield_time).observe(sun).apparent()
    radec = apparent.radec(epoch=skyfield_time)

    coord[:, 0] = radec[0].radians
    coord[:, 1] = radec[1].radians

    altaz = apparent.altaz()
    coord[:, 2] = altaz[0].radians
    coord[:, 3] = altaz[1].radians

    # Correct RA from equinox to CIRS coords using
    # the equation of the origins
    era = np.radians(ctime.unix_to_era(date))
    gast = 2 * np.pi * skyfield_time.gast / 24.0
    coord[:, 0] = coord[:, 0] + (era - gast)

    # Convert to hour angle
    coord[:, 0] = _correct_phase_wrap(coord[:, 0] -
                                      np.radians(ephemeris.lsa(date)))

    if deg:
        coord = np.degrees(coord)

    return coord
Example #6
0
    def parse_ant_logs(cls, logs, return_post_report_params=False):
        """
        Unzip and parse .ANT log file output by nsched for John Galt Telescope
        observations

        Parameters
        ----------
        logs : list of strings
            .ZIP filenames. Each .ZIP archive should include a .ANT file and
            a .POST_REPORT file. This method unzips the archive, uses
            `parse_post_report` to read the .POST_REPORT file and extract
            the CHIME sidereal day corresponding to the DRAO sidereal day,
            and then reads the lines in the .ANT file to obtain the pointing
            history of the Galt Telescope during this observation.

            (The DRAO sidereal day is days since the clock in Ev Sheehan's
            office at DRAO was reset. This clock is typically only reset every
            few years, but it does not correspond to any defined date, so the
            date must be figured out from the .POST_REPORT file, which reports
            both the DRAO sidereal day and the UTC date and time.

            Known reset dates: 2017-11-21, 2019-3-10)

        Returns
        -------

        if output_params == False:
            ant_data: A dictionary consisting of lists containing the LST,
                hour angle, RA, and dec (all as Skyfield Angle objects),
                CHIME sidereal day, and DRAO sidereal day.

        if output_params == True
            output_params: dictionary returned by `parse_post_report`
            and
            ant_data: described above

        Files
        -----
        the .ANT and .POST_REPORT files in the input .zip archive are
        extracted into /tmp/26mlog/<loginname>/
        """

        from skyfield.positionlib import Angle
        from caput import time as ctime

        DRAO_lon = ephemeris.CHIMELONGITUDE * 24.0 / 360.0

        def sidlst_to_csd(sid, lst, sid_ref, t_ref):
            """
            Convert an integer DRAO sidereal day and LST to a float
            CHIME sidereal day

            Parameters
            ----------
            sid : int
                DRAO sidereal day
            lst : float, in hours
                local sidereal time
            sid_ref : int
                DRAO sidereal day at the reference time t_ref
            t_ref : skyfield time object, Julian days
                Reference time

            Returns
            -------
            output : float
                CHIME sidereal day
            """
            csd_ref = int(
                ephemeris.csd(ephemeris.datetime_to_unix(
                    t_ref.utc_datetime())))
            csd = sid - sid_ref + csd_ref
            return csd + lst / ephemeris.SIDEREAL_S / 24.0

        ant_data_list = []
        post_report_list = []

        for log in logs:
            doobs = True

            filename = log.split("/")[-1]
            basedir = "/tmp/26mlog/{}/".format(os.getlogin())
            basename, extension = filename.split(".")
            post_report_file = basename + ".POST_REPORT"
            ant_file = basename + ".ANT"

            if extension == "zip":
                try:
                    zipfile.ZipFile(log).extract(post_report_file,
                                                 path=basedir)
                except:
                    print(
                        "Failed to extract {} into {}. Moving right along...".
                        format(post_report_file, basedir))
                    doobs = False
                try:
                    zipfile.ZipFile(log).extract(ant_file, path=basedir)
                except:
                    print(
                        "Failed to extract {} into {}. Moving right along...".
                        format(ant_file, basedir))
                    doobs = False

            if doobs:
                try:
                    post_report_params = cls.parse_post_report(
                        basedir + post_report_file)

                    with open(os.path.join(basedir, ant_file), "r") as f:
                        lines = [line for line in f]
                        ant_data = {"sid": np.array([])}
                        lsth = []
                        lstm = []
                        lsts = []

                        hah = []
                        ham = []
                        has = []

                        decd = []
                        decm = []
                        decs = []

                        for l in lines:
                            arr = l.split()

                            try:
                                lst_hms = [float(x) for x in arr[2].split(":")]

                                # do last element first: if this is going to
                                # crash because a line in the log is incomplete,
                                # we don't want it to append to any of the lists

                                decs.append(float(arr[8].replace('"', "")))
                                decm.append(float(arr[7].replace("'", "")))
                                decd.append(float(arr[6].replace("D", "")))

                                has.append(float(arr[5].replace("S", "")))
                                ham.append(float(arr[4].replace("M", "")))
                                hah.append(float(arr[3].replace("H", "")))

                                lsts.append(float(lst_hms[2]))
                                lstm.append(float(lst_hms[1]))
                                lsth.append(float(lst_hms[0]))

                                ant_data["sid"] = np.append(
                                    ant_data["sid"], int(arr[1]))
                            except:
                                print("Failed in file {} for line \n{}".format(
                                    ant_file, l))
                                if len(ant_data["sid"]) != len(decs):
                                    print("WARNING: mismatch in list lengths.")

                        ant_data["lst"] = Angle(hours=(lsth, lstm, lsts))

                        ha = Angle(hours=(hah, ham, has))
                        dec = Angle(degrees=(decd, decm, decs))

                        ant_data["ha"] = Angle(
                            radians=ha.radians -
                            ephemeris.galt_pointing_model_ha(ha, dec).radians,
                            preference="hours",
                        )

                        ant_data["dec_cirs"] = Angle(
                            radians=dec.radians -
                            ephemeris.galt_pointing_model_dec(ha, dec).radians,
                            preference="degrees",
                        )

                        ant_data["csd"] = sidlst_to_csd(
                            np.array(ant_data["sid"]),
                            ant_data["lst"].hours,
                            post_report_params["SID"],
                            post_report_params["start_time"],
                        )

                    ant_data["t"] = ephemeris.unix_to_skyfield_time(
                        ephemeris.csd_to_unix(ant_data["csd"]))

                    # Correct RA from equinox to CIRS coords (both in radians)
                    era = np.radians(
                        ctime.unix_to_era(ephemeris.ensure_unix(
                            ant_data["t"])))
                    gast = ant_data["t"].gast * 2 * np.pi / 24.0

                    ant_data["ra_cirs"] = Angle(
                        radians=ant_data["lst"].radians -
                        ant_data["ha"].radians + (era - gast),
                        preference="hours",
                    )

                    obs = ephemeris.Star_cirs(
                        ra=ant_data["ra_cirs"],
                        dec=ant_data["dec_cirs"],
                        epoch=ant_data["t"],
                    )

                    ant_data["ra"] = obs.ra
                    ant_data["dec"] = obs.dec

                    ant_data_list.append(ant_data)
                    post_report_list.append(post_report_params)
                except:
                    print("Parsing {} failed".format(post_report_file))

        if return_post_report_params:
            return post_report_list, ant_data_list
        return ant_data