Пример #1
0
    async def basic_make_script(self, index):
        """Make script and controllers and return a list of all made."""
        self.script = CalSysTakeData(index=index)

        # mock controllers that use callback functions defined below
        # to handle the expected commands
        self.electrometer = salobj.Controller(name="Electrometer", index=1)
        self.monochromator = salobj.Controller(name="ATMonochromator")
        self.fiberspec = salobj.Controller(name="FiberSpectrograph")

        # data that is set by the command callback functions
        # scan durations from Electrometer startScanDt command
        self.scan_durations = []
        # data from FiberSpectrograph captureSpectImage command
        self.image_data = []
        # wavelengths from ATMonochromator changeWavelength command
        self.wavelengths = []
        # slit width data from ATMonochromator changeSlitWidth command
        self.slit_data = []
        # grating types from ATMonochromator gratingType command
        self.grating_types = []

        # assign the command callback functions
        self.electrometer.cmd_startScanDt.callback = self.startScanDt

        self.fiberspec.cmd_expose.callback = self.captureSpectImage

        self.monochromator.cmd_changeWavelength.callback = self.changeWavelength
        self.monochromator.cmd_changeSlitWidth.callback = self.changeSlitWidth
        self.monochromator.cmd_selectGrating.callback = self.selectGrating

        return (self.script, self.electrometer, self.monochromator,
                self.fiberspec)
Пример #2
0
    async def basic_make_script(self, index):
        self.script = Stop(index=index)

        # A dict of name: number of calls
        # where name is {controller_name_index}.{command_name}
        self.num_calls = dict()

        # A dict of name_index: numer of calls
        # where name_index means the SAL component name and index
        # in the form name[:index] and [:index] is only wanted for
        # indexed SAL components.
        self.controllers = dict()

        for name_index in ("ATDome", "ATDomeTrajectory", "ATPtg", "ATMCS"):
            name, index = salobj.name_to_name_index(name_index)
            controller = salobj.Controller(name=name, index=index)
            self.controllers[name_index] = controller
            await controller.evt_summaryState.set_write(
                summaryState=salobj.State.ENABLED)
            for command_name in controller.salinfo.command_names:
                name = f"{name_index}.{command_name}"
                self.num_calls[name] = 0
                command = getattr(controller, f"cmd_{command_name}")
                command.callback = functools.partial(self.callback, name)

        return (self.script, ) + tuple(self.controllers.values())
Пример #3
0
 def connect_to_love_controller():
     global csc
     try:
         csc = salobj.Controller("LOVE", index=None, do_callbacks=False)
     except Exception as e:
         logging.warning(e)
         csc = None
Пример #4
0
    async def basic_make_script(self, index):
        logger.debug("Starting basic_make_script")
        self.script = LatissAcquireAndTakeSequence(index=index)

        # Mock the telescope slews and offsets
        self.script.atcs.slew_object = unittest.mock.AsyncMock()
        self.script.atcs.slew_icrs = unittest.mock.AsyncMock()
        self.script.atcs.offset_xy = unittest.mock.AsyncMock()
        self.script.atcs.add_point_data = unittest.mock.AsyncMock()
        self.script.latiss.ready_to_take_data = unittest.mock.AsyncMock(
            return_value=True)

        # Mock the latiss instrument setups
        self.script.latiss.setup_atspec = unittest.mock.AsyncMock(
            wraps=self.cmd_setup_atspec_callback)

        # Mock method that returns the BestEffortIsr class if it is
        # not available for import
        if not DATA_AVAILABLE:
            self.script.get_best_effort_isr = unittest.mock.Mock()

        # Load controllers and required callbacks to simulate
        # telescope/instrument behaviour
        self.atcamera = salobj.Controller(name="ATCamera")
        self.atcamera.cmd_takeImages.callback = unittest.mock.AsyncMock(
            wraps=self.cmd_take_images_callback)

        self.atheaderservice = salobj.Controller(name="ATHeaderService")
        self.atoods = salobj.Controller(name="ATOODS")
        # Need ataos as the script waits for corrections to be applied on
        # grating/filter changes
        self.ataos = salobj.Controller(name="ATAOS")

        self.atspectrograph = salobj.Controller(name="ATSpectrograph")

        self.end_image_tasks = []

        # things to track
        self.nimages = 0
        self.date = None  # Used to fake dataId output from takeImages
        self.seq_num_start = None  # Used to fake proper dataId from takeImages

        logger.debug("Finished initializing from basic_make_script")
        # Return a single element tuple
        return (self.script, )
Пример #5
0
    async def test_write_only_true(self) -> None:
        index = next(index_gen)
        # Build a controller and check that callbacks are asigned.
        async with salobj.Controller(name="Test", index=index,
                                     write_only=True) as controller:
            for name in controller.salinfo.command_names:
                assert not hasattr(controller, f"cmd_{name}")

            for name in controller.salinfo.event_names:
                assert hasattr(controller, f"evt_{name}")

            for name in controller.salinfo.telemetry_names:
                assert hasattr(controller, f"tel_{name}")

        with pytest.raises(ValueError):
            salobj.Controller(name="Test",
                              index=index,
                              do_callbacks=True,
                              write_only=True)
    async def basic_make_script(self, index):
        self.script = TakeImageLatiss(index=index)
        self.atcam = salobj.Controller(name="ATCamera")
        self.atspec = salobj.Controller(name="ATSpectrograph")
        self.atheaderservice = salobj.Controller(name="ATHeaderService")

        self.nimages = 0
        self.selected_filter = []
        self.selected_disperser = []
        self.selected_linear_stage = []

        self.atcam.cmd_takeImages.callback = self.cmd_take_images_callback
        self.atspec.cmd_changeFilter.callback = self.cmd_changeFilter_callback
        self.atspec.cmd_changeDisperser.callback = self.cmd_changeDisperser_callback
        self.atspec.cmd_moveLinearStage.callback = self.cmd_moveLinearStage_callback

        self.end_image_tasks = []

        return self.atspec, self.atcam, self.atheaderservice, self.script
Пример #7
0
    async def test_do_callbacks_false(self) -> None:
        index = next(index_gen)
        async with salobj.Controller("Test", index,
                                     do_callbacks=False) as controller:
            command_names = controller.salinfo.command_names
            for name in command_names:
                with self.subTest(name=name):
                    cmd = getattr(controller, "cmd_" + name)
                    assert not cmd.has_callback

            assert controller.salinfo.identity == f"Test:{index}"
Пример #8
0
            async def mtmount_emulator(elevation):
                async with salobj.Controller("MTMount") as mtmount:

                    # xml 7/8 compatibility
                    if hasattr(mtmount.tel_elevation.DataType(), "actualPosition"):
                        mtmount.tel_elevation.set(actualPosition=elevation)
                    else:
                        mtmount.tel_elevation.set(angleActual=elevation)

                    while mtmount.isopen:
                        mtmount.tel_elevation.put()
                        await asyncio.sleep(1.0)
Пример #9
0
 def emit_largeFileObjectAvailable(self, args):
     cam = salobj.Controller(name="EFD", index=0)
     kwInt = {
         'byteSize': args.byteSize,
         'checkSum': args.checkSum,
         'generator': args.generator,
         'mimeType': args.mimeType,
         'url': args.url,
         'version': args.version,
         'id': args.identifier
     }
     cam.evt_largeFileObjectAvailable.set_put(**kwInt)
    async def basic_make_script(self, index):
        self.script = ATGetStdFlatDataset(index=index)

        # Adds controller to Test
        self.at_cam = salobj.Controller(name="ATCamera")
        self.at_spec = salobj.Controller(name="ATSpectrograph")
        self.at_headerservice = salobj.Controller(name="ATHeaderService")

        self.n_bias = 0
        self.n_dark = 0
        self.n_flat = 0

        self.filter = None
        self.grating = None
        self.linear_stage = None

        self.shutter_time = 1.0

        self.end_readout_tasks = []

        return (self.script, self.at_cam, self.at_spec, self.at_headerservice)
Пример #11
0
    async def mock_auxtel(self) -> typing.AsyncGenerator[None, None]:

        try:

            async with salobj.Controller(
                    "ATMCS") as self.atmcs, salobj.Controller(
                        "ATPtg") as self.atptg, salobj.Controller(
                            "ATPneumatics"
                        ) as self.pnematics, salobj.Controller(
                            "ATHexapod") as self.hexapod, salobj.Controller(
                                "ATCamera") as self.camera, salobj.Controller(
                                    "ATSpectrograph") as self.atspectrograph:

                self.set_pneumatics_callbacks()
                self.set_atptg_callbacks()
                self.set_athexapod_callbacks()

                await self.publish_pneumatics_initial_data()
                await self.publish_atspectrograph_initial_data()

                self.running = True

                mount_telemetry_task = asyncio.create_task(
                    self.publish_mount_encoders())
                yield
                self.running = False
                try:
                    await asyncio.wait_for(mount_telemetry_task,
                                           timeout=STD_TIMEOUT)
                except asyncio.TimeoutError:
                    mount_telemetry_task.cancel()

        except Exception as exception:
            raise exception
Пример #12
0
    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())
Пример #13
0
 def emit_startIntegration(self, args):
     cam = salobj.Controller(name="ATCamera", index=0)
     kwInt = {
         'imagesInSequence': args.imagesInSequence,
         'imageName': str(args.imageName),
         'imageIndex': args.imageIndex,
         'imageSource': str(args.imageSource),
         'imageController': str(args.imageController),
         'imageDate': str(args.imageDate),
         'imageNumber': args.imageNumber,
         'timeStampAcquisitionStart': args.timeStampAcquisitionStart,
         'exposureTime': args.exposureTime,
         'imageType': args.imageType,
         'groupId': args.groupId,
         'priority': 1
     }
     cam.evt_startIntegration.set_put(**kwInt)
Пример #14
0
    async def test_call(self):
        name = "ScriptQueue"
        index = 5
        timeout = 0.2

        watcher_config_dict = yaml.safe_load(f"""
            disabled_sal_components: []
            auto_acknowledge_delay: 3600
            auto_unacknowledge_delay: 3600
            rules:
            - classname: Heartbeat
              configs:
              - name: {name}:{index}
                timeout: {timeout}
            escalation: []
            """)
        watcher_config = types.SimpleNamespace(**watcher_config_dict)

        async with salobj.Controller(name=name, index=index) as controller:
            async with watcher.Model(domain=controller.domain,
                                     config=watcher_config) as model:
                model.enable()

                self.assertEqual(len(model.rules), 1)
                rule_name = f"Heartbeat.{name}:{index}"
                rule = model.rules[rule_name]
                alarm = rule.alarm

                controller.evt_heartbeat.put()
                await asyncio.sleep(0.001)
                self.assertTrue(alarm.nominal)

                await asyncio.sleep(timeout / 2)
                controller.evt_heartbeat.put()
                await asyncio.sleep(0.001)
                self.assertTrue(alarm.nominal)

                await asyncio.sleep(timeout * 2)
                self.assertFalse(alarm.nominal)
                self.assertEqual(alarm.severity, AlarmSeverity.SERIOUS)
                controller.evt_heartbeat.put()
                await asyncio.sleep(0.001)
                self.assertFalse(alarm.nominal)
                self.assertEqual(alarm.severity, AlarmSeverity.NONE)
                self.assertEqual(alarm.max_severity, AlarmSeverity.SERIOUS)
Пример #15
0
    async def basic_make_script(self, index):
        self.script = LatissCWFSAlign(index=index, remotes=True)

        self.visit_id_angles = {}
        self.end_image_tasks = []
        self.img_cnt_override_list = None

        # Load controllers and required callbacks to simulate
        # telescope/instrument behaviour

        self.atcamera = salobj.Controller(name="ATCamera")
        self.atheaderservice = salobj.Controller(name="ATHeaderService")
        self.atoods = salobj.Controller(name="ATOODS")
        self.ataos = salobj.Controller(name="ATAOS")
        self.athexapod = salobj.Controller(name="ATHexapod")
        self.atptg = salobj.Controller(name="ATPtg")
        self.atmcs = salobj.Controller(name="ATMCS")

        # Create mocks
        self.atcamera.cmd_takeImages.callback = unittest.mock.AsyncMock(
            wraps=self.cmd_take_images_callback)
        self.script.latiss.ready_to_take_data = unittest.mock.AsyncMock(
            return_value=True)
        # mock latiss instrument setup
        self.script.latiss.setup_atspec = unittest.mock.AsyncMock()

        self.ataos.cmd_offset.callback = unittest.mock.AsyncMock(
            wraps=self.ataos_cmd_offset_callback)
        self.script.atcs.offset_xy = unittest.mock.AsyncMock()
        self.script.atcs.add_point_data = unittest.mock.AsyncMock()
        # callback for boresight angle
        self.script.atcs.get_bore_sight_angle = unittest.mock.AsyncMock(
            wraps=self.atcs_get_bore_sight_angle)

        # Mock method that returns the BestEffortIsr class if it is
        # not available for import
        if not DATA_AVAILABLE:
            self.script.get_best_effort_isr = unittest.mock.AsyncMock()

        # things to track
        self.nimages = 0
        self.date = None  # Used to fake dataId output from takeImages
        self.seq_num_start = None  # Used to fake proper dataId from takeImages

        # Return a single element tuple
        return (self.script, )
Пример #16
0
 async def make_csc(
     self,
     initial_state,
     config_dir=None,
     override="",
     simulation_mode=0,
     log_level=None,
 ):
     async with super().make_csc(
             initial_state=initial_state,
             config_dir=config_dir,
             override=override,
             simulation_mode=simulation_mode,
             log_level=log_level,
     ), ATDomeTrajectory.MockDome(
             initial_state=salobj.State.ENABLED
     ) as self.dome_csc, salobj.Remote(
             domain=self.dome_csc.domain,
             name="ATDome") as self.dome_remote, salobj.Controller(
                 "ATMCS") as self.atmcs_controller:
         yield
Пример #17
0
    async def test_write_speed(self) -> None:
        async with salobj.Controller(
            name="Test", index=self.index, do_callbacks=False
        ) as controller:

            num_samples = 1000

            t0 = time.monotonic()
            for i in range(num_samples):
                await controller.tel_arrays.write()
            dt = time.monotonic() - t0
            arrays_write_speed = num_samples / dt
            print(
                f"Wrote {arrays_write_speed:0.0f} arrays samples/second ({num_samples} samples)"
            )

            self.insert_measurement(
                verify.Measurement(
                    "salobj.WriteTest_arrays", arrays_write_speed * u.ct / u.second
                )
            )

            t0 = time.monotonic()
            for _ in range(num_samples):
                await controller.evt_logLevel.write()
                await asyncio.sleep(0)
            dt = time.monotonic() - t0
            log_level_write_speed = num_samples / dt
            print(
                f"Wrote {log_level_write_speed:0.0f} logLevel samples/second ({num_samples} samples)"
            )

            self.insert_measurement(
                verify.Measurement(
                    "salobj.WriteTest_logLevel",
                    log_level_write_speed * u.ct / u.second,
                )
            )
Пример #18
0
 async def make_csc(
     self,
     initial_state,
     config_dir=None,
     initial_elevation=0,
     override="",
     simulation_mode=0,
     log_level=None,
 ):
     async with super().make_csc(
             initial_state=initial_state,
             config_dir=config_dir,
             override=override,
             simulation_mode=simulation_mode,
             log_level=log_level,
     ), mtdometrajectory.MockDome(
             initial_state=salobj.State.ENABLED,
             initial_elevation=initial_elevation
     ) as self.dome_csc, salobj.Remote(
             domain=self.dome_csc.domain,
             name="MTDome") as self.dome_remote, salobj.Controller(
                 "MTMount") as self.mtmount_controller:
         yield
Пример #19
0
    async def make_model(self, names, enable, escalation=()):
        """Make a Model as self.model, with one or more Enabled rules.

        Parameters
        ----------
        names : `list` [`str`]
            Name and index of one or more CSCs.
            Each entry is of the form "name" or name:index".
            The associated alarm names have a prefix of "Enabled.".
        enable : `bool`
            Enable the model?
        escalation : `list` of `dict`, optional
            Escalation information.
            See `CONFIG_SCHEMA` for the format of entries.
        """
        if not names:
            raise ValueError("Must specify one or more CSCs")
        self.name_index_list = [
            salobj.name_to_name_index(name) for name in names
        ]

        configs = [dict(name=name_index) for name_index in names]
        watcher_config_dict = dict(
            disabled_sal_components=[],
            auto_acknowledge_delay=3600,
            auto_unacknowledge_delay=3600,
            rules=[dict(classname="Enabled", configs=configs)],
            escalation=escalation,
        )
        watcher_config = types.SimpleNamespace(**watcher_config_dict)

        self.read_severities = dict()
        self.read_max_severities = dict()

        self.controllers = []
        for name_index in names:
            name, index = salobj.name_to_name_index(name_index)
            self.controllers.append(salobj.Controller(name=name, index=index))
        self.model = watcher.Model(
            domain=self.controllers[0].domain,
            config=watcher_config,
            alarm_callback=self.alarm_callback,
        )

        for name in self.model.rules:
            self.read_severities[name] = []
            self.read_max_severities[name] = []

        controller_start_tasks = [
            controller.start_task for controller in self.controllers
        ]
        await asyncio.gather(self.model.start_task, *controller_start_tasks)
        if enable:
            self.model.enable()
            await self.model.enable_task

        for rule in self.model.rules.values():
            self.assertTrue(rule.alarm.nominal)
            self.assertFalse(rule.alarm.acknowledged)
            self.assertFalse(rule.alarm.muted)
            self.assertNotMuted(rule.alarm)

        try:
            yield
        finally:
            await self.model.close()
            controller_close_tasks = [
                asyncio.create_task(controller.close())
                for controller in self.controllers
            ]
            await asyncio.gather(*controller_close_tasks)
Пример #20
0
    async def test_call(self):
        name = "ScriptQueue"
        index = 5

        watcher_config_dict = yaml.safe_load(
            f"""
            disabled_sal_components: []
            auto_acknowledge_delay: 3600
            auto_unacknowledge_delay: 3600
            rules:
            - classname: Enabled
              configs:
              - name: {name}:{index}
            escalation: []
            """
        )
        watcher_config = types.SimpleNamespace(**watcher_config_dict)

        async with salobj.Controller(name=name, index=index) as controller:
            async with watcher.Model(
                domain=controller.domain, config=watcher_config
            ) as model:
                model.enable()

                self.assertEqual(len(model.rules), 1)
                rule_name = f"Enabled.{name}:{index}"
                rule = model.rules[rule_name]

                read_severities = []

                def alarm_callback(alarm):
                    nonlocal read_severities
                    read_severities.append(alarm.severity)

                rule.alarm.callback = alarm_callback

                expected_severities = []
                for state in (
                    salobj.State.STANDBY,
                    salobj.State.DISABLED,
                    salobj.State.ENABLED,
                    salobj.State.FAULT,
                    salobj.State.STANDBY,
                    salobj.State.DISABLED,
                    salobj.State.FAULT,
                    salobj.State.STANDBY,
                    salobj.State.DISABLED,
                    salobj.State.ENABLED,
                ):
                    if state == salobj.State.ENABLED:
                        expected_severities.append(AlarmSeverity.NONE)
                    elif state == salobj.State.FAULT:
                        expected_severities.append(AlarmSeverity.SERIOUS)
                    else:
                        expected_severities.append(AlarmSeverity.WARNING)

                    controller.evt_summaryState.set_put(
                        summaryState=state, force_output=True
                    )
                    # give the remote a chance to read the data
                    await asyncio.sleep(0.001)

                self.assertEqual(read_severities, expected_severities)
Пример #21
0
 async def basic_make_script(self, index):
     self.script = standardscripts.RunCommand(index=index)
     self.controller = salobj.Controller("Test", index=1)
     self.controller.cmd_setScalars.callback = self.set_scalars_callback
     return [self.script, self.controller]
Пример #22
0
    async def make_csc(
        self,
        initial_state=salobj.State.OFFLINE,
        config_dir=None,
        simulation_mode=1,
        log_level=None,
        timeout=STD_TIMEOUT,
        run_mock_ccw=True,  # Set False to test failure to enable
        **kwargs,
    ):
        """Override make_csc

        This exists primarily because we need to start a mock
        camera cable wrap controller before we can enable the CSC.
        It also offers the opportunity to make better defaults.

        Parameters
        ----------
        name : `str`
            Name of SAL component.
        initial_state : `lsst.ts.salobj.State` or `int`, optional
            The initial state of the CSC. Defaults to STANDBY.
        config_dir : `str`, optional
            Directory of configuration files, or `None` (the default)
            for the standard configuration directory (obtained from
            `ConfigureCsc._get_default_config_dir`).
        simulation_mode : `int`, optional
            Simulation mode. Defaults to 0 because not all CSCs support
            simulation. However, tests of CSCs that support simulation
            will almost certainly want to set this nonzero.
        log_level : `int` or `None`, optional
            Logging level, such as `logging.INFO`.
            If `None` then do not set the log level, leaving the default
            behavior of `SalInfo`: increase the log level to INFO.
        timeout : `float`, optional
            Time limit for the CSC to start (seconds).
        run_mock_ccw : `bool`, optional
            If True then start a mock camera cable wrap controller.
        **kwargs : `dict`, optional
            Extra keyword arguments for `basic_make_csc`.
            For a configurable CSC this may include ``settings_to_apply``,
            especially if ``initial_state`` is DISABLED or ENABLED.

        """
        # We cannot transition the CSC to ENABLED
        # until the CCW following loop is running.
        # So if initial_state is ENABLED
        # start the CSC in DISABLED, start the CCW following loop,
        # then transition to ENABLED and swallow the DISABLED state
        # and associated controller state (make_csc reads all but the final
        # CSC summary state and controller state).
        if initial_state == salobj.State.ENABLED:
            modified_initial_state = salobj.State.DISABLED
        else:
            modified_initial_state = initial_state

        async with super().make_csc(
                initial_state=modified_initial_state,
                config_dir=config_dir,
                simulation_mode=simulation_mode,
                log_level=log_level,
                timeout=timeout,
                **kwargs,
        ), salobj.Controller(name="MTMount") as self.mtmount_controller:
            if run_mock_ccw:
                self.mock_ccw_task = asyncio.create_task(self.mock_ccw_loop())
            else:
                print("do not run mock_ccw_loop")
                self.mock_ccw_task = salobj.make_done_future()
            if initial_state != modified_initial_state:
                await self.remote.cmd_enable.start(timeout=STD_TIMEOUT)
                await self.assert_next_summary_state(salobj.State.DISABLED)
                await self.assert_next_sample(
                    topic=self.remote.evt_controllerState,
                    controllerState=ControllerState.DISABLED,
                )
            try:
                yield
            finally:
                self.enable_mock_ccw_telemetry = False
                await asyncio.wait_for(self.mock_ccw_task, timeout=STD_TIMEOUT)