Ejemplo n.º 1
0
    def test_configure(self):
        temp_model = ObservatoryModel(self.location)
        temp_model.configure_from_module()

        self.assertEqual(temp_model.location.longitude_rad,
                         math.radians(-70.7494))
        self.assertEqual(temp_model.location.longitude, -70.7494)
        self.assertEqual(temp_model.current_state.telalt_rad,
                         math.radians(86.5))
Ejemplo n.º 2
0
class ObservatoryStateMock:
    def __init__(self):
        self.ptg = salobj.Controller("MTPtg")

        self.location = ObservatoryLocation()
        self.location.for_lsst()

        self.model = ObservatoryModel(self.location)
        self.model.configure_from_module()

        self.telemetry_sleep_time = 0.02
        self.run_current_target_status_loop = True
        self.current_target_status_task = None

        self._started = False
        self.start_task = asyncio.create_task(self.start())

    async def current_target_status(self):
        while self.run_current_target_status_loop:
            time = utils.current_tai()
            self.model.update_state(time)
            await self.ptg.tel_currentTargetStatus.set_write(
                timestamp=time,
                demandAz=self.model.current_state.telaz,
                demandEl=self.model.current_state.telalt,
                demandRot=self.model.current_state.telrot,
                demandRa=self.model.current_state.ra,
                demandDec=self.model.current_state.dec,
                parAngle=self.model.current_state.pa,
            )
            await asyncio.sleep(self.telemetry_sleep_time)

    async def start(self):
        if not self._started:
            self._started = True
            await self.ptg.start_task

            self.run_current_target_status_loop = True
            self.current_target_status_task = asyncio.create_task(
                self.current_target_status())

    async def close(self):
        self.run_current_target_status_loop = False
        try:
            await asyncio.wait_for(self.current_target_status_task,
                                   timeout=self.telemetry_sleep_time * 5)
        finally:
            await self.ptg.close()

    async def __aenter__(self):
        await self.start_task
        return self

    async def __aexit__(self, type, value, traceback):
        await self.close()
Ejemplo n.º 3
0
class SlewTimeSource(object):
    """Callable object to calculate slew times."""

    pre_position = ObservatoryPosition()
    post_position = ObservatoryPosition()

    def __init__(self, survey_start_time=DEFAULT_START_TIME):
        """Initialize slew time calculator.
        """
        self.start_time = survey_start_time
        self.observatory = ObservatoryModel()
        self.observatory.configure_from_module()
        self.observatory.params.rotator_followsky = True

    def __call__(self, seconds_into_survey, pre_alt, pre_az, pre_band,
                 post_alt, post_az, post_band):
        """Calculate the slew time.

        Args:
           - seconds_into_survey :: the time into the survey (in seconds)
           - pre_alt :: the alt of the starting pointing, in degrees
           - pre_az :: the az of the starting pointing, in degrees
           - pre_band :: the filter at the starting pointing
           - post_alt :: the alt of the ending pointing, in degrees
           - post_az :: the az of the ending pointing, in degrees
           - post_band :: the filter at the starting pointing
        """
        current_time = self.start_time + TimeDelta(seconds_into_survey,
                                                   format='sec')
        self.pre_position.time = current_time
        self.pre_position.tracking = True
        self.pre_position.alt_rad = np.radians(pre_alt)
        self.pre_position.az_rad = np.radians(pre_az)
        self.pre_position.rot_rad = self.observatory.current_state.rot_rad
        self.pre_position.filter = pre_band
        pre_state = self.observatory.get_closest_state(self.pre_position)

        self.post_position.time = current_time
        self.post_position.tracking = True
        self.post_position.alt_rad = np.radians(post_alt)
        self.post_position.az_rad = np.radians(post_az)
        self.post_position.rot_rad = self.observatory.current_state.rot_rad
        self.post_position.filter = post_band
        post_state = self.observatory.get_closest_state(self.post_position)

        slew_time = self.observatory.get_slew_delay_for_state(
            pre_state, post_state, False)

        return slew_time
Ejemplo n.º 4
0
class TestFeatureSchedulerTarget(unittest.TestCase):
    def setUp(self) -> None:

        self.observatory_model = ObservatoryModel()
        self.observatory_model.configure_from_module()

        start_time = Time(59853.983, format="mjd", scale="tai")

        self.observatory_model.update_state(start_time.unix)

        return super().setUp()

    def test_constructor(self):

        observation = self.make_fbs_observation(note="std")

        target = FeatureSchedulerTarget(
            observing_script_name="observing_script",
            observing_script_is_standard=True,
            observation=observation,
        )

        slew_time, error = self.observatory_model.get_slew_delay(target)

        self.assertEqual(error, 0)
        self.assertGreater(slew_time, 0.0)

    def test_get_script_config(self):

        observation = self.make_fbs_observation(note="std")

        target = FeatureSchedulerTarget(
            observing_script_name="observing_script",
            observing_script_is_standard=True,
            observation=observation,
        )

        script_config_expected = {
            "targetid":
            target.targetid,
            "band_filter":
            target.filter,
            "ra":
            Angle(float(observation["RA"][0]),
                  unit=units.rad).to_string(unit=units.hourangle, sep=":"),
            "dec":
            Angle(float(observation["dec"][0]),
                  unit=units.rad).to_string(unit=units.degree, sep=":"),
            "name":
            observation["note"][0],
            "program":
            observation["note"][0].rsplit("_", maxsplit=1)[0],
            "rot_sky":
            target.ang,
            "obs_time":
            target.obs_time,
            "num_exp":
            target.num_exp,
            "exp_times":
            target.exp_times,
            "estimated_slew_time":
            target.slewtime,
        }

        script_config_yaml = target.get_script_config()

        script_config_unpacked = yaml.safe_load(script_config_yaml)

        self.assertEqual(script_config_expected, script_config_unpacked)

    def test_get_script_config_cwfs(self):

        observation = self.make_fbs_observation(note="cwfs")

        target = FeatureSchedulerTarget(
            observing_script_name="observing_script",
            observing_script_is_standard=True,
            observation=observation,
        )

        script_config_expected = dict(find_target=dict(
            az=math.degrees(float(observation["az"][0])),
            el=math.degrees(float(observation["alt"][0])),
        ))

        script_config_yaml = target.get_script_config()

        script_config_unpacked = yaml.safe_load(script_config_yaml)

        self.assertEqual(script_config_expected, script_config_unpacked)

    def test_get_script_config_cwfs_with_additional_config(self):

        observation = self.make_fbs_observation(note="cwfs")

        target = FeatureSchedulerTarget(
            observing_script_name="observing_script",
            observing_script_is_standard=True,
            observation=observation,
            script_configuration_cwfs=dict(filter="SDSSg", grating="empty_1"),
        )

        script_config_expected = dict(
            find_target=dict(
                az=math.degrees(float(observation["az"][0])),
                el=math.degrees(float(observation["alt"][0])),
            ),
            filter="SDSSg",
            grating="empty_1",
        )

        script_config_yaml = target.get_script_config()

        script_config_unpacked = yaml.safe_load(script_config_yaml)

        self.assertEqual(script_config_expected, script_config_unpacked)

    def test_get_script_config_spec(self):

        observation = self.make_fbs_observation(note="spec:HD12345")

        target = FeatureSchedulerTarget(
            observing_script_name="observing_script",
            observing_script_is_standard=True,
            observation=observation,
        )

        script_config_expected = {
            "object_name":
            observation["note"][0],
            "object_dec":
            Angle(float(observation["dec"][0]),
                  unit=units.rad).to_string(unit=units.degree, sep=":"),
            "object_ra":
            Angle(float(observation["RA"][0]),
                  unit=units.rad).to_string(unit=units.hourangle, sep=":"),
        }

        script_config_yaml = target.get_script_config()

        script_config_unpacked = yaml.safe_load(script_config_yaml)

        self.assertEqual(script_config_expected, script_config_unpacked)

    def test_get_script_config_spec_with_additional_config(self):

        observation = self.make_fbs_observation(note="spec:HD12345")

        target = FeatureSchedulerTarget(
            observing_script_name="observing_script",
            observing_script_is_standard=True,
            observation=observation,
            script_configuration_spec=dict(
                filter_sequence=["SDSSg", "SDSSg"],
                grating_sequence=["empty_1", "empty_1"],
            ),
        )

        script_config_expected = {
            "object_name":
            observation["note"][0],
            "object_dec":
            Angle(float(observation["dec"][0]),
                  unit=units.rad).to_string(unit=units.degree, sep=":"),
            "object_ra":
            Angle(float(observation["RA"][0]),
                  unit=units.rad).to_string(unit=units.hourangle, sep=":"),
            "filter_sequence": ["SDSSg", "SDSSg"],
            "grating_sequence": ["empty_1", "empty_1"],
        }

        script_config_yaml = target.get_script_config()

        script_config_unpacked = yaml.safe_load(script_config_yaml)

        self.assertEqual(script_config_expected, script_config_unpacked)

    def test_get_script_config_multiple_observations(self):

        filter_obs = "gri"
        observations = self.make_fbs_observation("std", filter_obs=filter_obs)

        target = FeatureSchedulerTarget(
            observing_script_name="observing_script",
            observing_script_is_standard=True,
            observation=observations,
        )

        slew_time, error = self.observatory_model.get_slew_delay(target)

        script_config = yaml.safe_load(target.get_script_config())

        self.assertEqual(len(script_config["exp_times"]), len(filter_obs) * 2)
        for filter_name in filter_obs:
            self.assertIn(filter_name, script_config["band_filter"])

        self.assertEqual(error, 0)
        self.assertGreater(slew_time, 0.0)

    def make_fbs_observation(self, note, filter_obs="r"):

        observations = np.concatenate(
            [empty_observation() for _ in range(len(filter_obs))])

        ra, dec, _ = self.observatory_model.altaz2radecpa(
            self.observatory_model.dateprofile, 65.0, 180.0)
        for obs_filter, observation in zip(filter_obs, observations):
            observation["RA"] = ra
            observation["dec"] = dec
            observation["mjd"] = self.observatory_model.dateprofile.mjd
            observation["filter"] = obs_filter
            observation["exptime"] = 30.0
            observation["nexp"] = 2
            observation["note"] = note

        return observations
Ejemplo n.º 5
0
    def test_transitioner(self):
        observatory = ObservatoryModel()
        observatory.configure_from_module()
        pachon = astroplan.Observer.at_site("Cerro Pachon")
        start_time = astropy.time.Time(59598.66945625747, format='mjd')
        readout_time = observatory.params.readouttime * u.second
        exptime = 15 * u.second
        nexp = 2

        targets = [
            astroplan.FixedTarget(coord=SkyCoord(ra=81.1339111328125 * u.deg,
                                                 dec=-17.532396316528303 *
                                                 u.deg),
                                  name="1857"),
            astroplan.FixedTarget(coord=SkyCoord(ra=81.1758499145508 * u.deg,
                                                 dec=-12.2103328704834 *
                                                 u.deg),
                                  name="2100")
        ]

        constraints = [
            astroplan.AltitudeConstraint(30 * u.deg, 89 * u.deg),
            astroplan.AirmassConstraint(2.2),
            astroplan.AtNightConstraint.twilight_astronomical()
        ]
        obs_blocks = [
            astroplan.ObservingBlock.from_exposures(
                target,
                1,
                exptime,
                nexp,
                readout_time,
                configuration={'filter': band},
                constraints=constraints) for band in ('g', 'i')
            for target in targets
        ]

        self.assertGreater(observatory.params.readouttime, 1.5)
        self.assertGreater(observatory.params.filter_changetime, 15.0)

        slew_src = SlewTimeSource()
        transitioner = apsupp.OpsimTransitioner(slew_src)
        whitepaper_transitioner = apsupp.LSSTTransitioner()
        for old_block, new_block in zip(obs_blocks[:-1], obs_blocks[1:]):
            block = transitioner(old_block, new_block, start_time, pachon)
            wp_block = whitepaper_transitioner(old_block, new_block,
                                               start_time, pachon)
            duration_seconds = (block.duration / u.second).value
            wp_duration_seconds = (wp_block.duration / u.second).value

            self.assertAlmostEqual(duration_seconds,
                                   wp_duration_seconds,
                                   delta=5)

            old_filter = old_block.configuration['filter']
            new_filter = new_block.configuration['filter']
            if old_filter == new_filter:
                min_expected_duration = observatory.params.readouttime
            else:
                min_expected_duration = max(
                    observatory.params.readouttime,
                    observatory.params.filter_changetime)

            self.assertGreaterEqual(duration_seconds, min_expected_duration)
            self.assertLess(duration_seconds, 600)