Skip to content

Commit

Permalink
Implemented MoveRotator script based on mtcs.move_rotator
Browse files Browse the repository at this point in the history
* Updated unit tests
  • Loading branch information
b1quint committed Oct 12, 2023
1 parent d549f4b commit ebfef49
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 12 deletions.
Empty file.
46 changes: 34 additions & 12 deletions python/lsst/ts/standardscripts/maintel/mtrotator/move_rotator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

__all__ = ["EnableComCam"]

import asyncio
import warnings
__all__ = ["MoveRotator"]

import yaml
from lsst.ts.observatory.control.maintel.mtcs import MTCS, MTCSUsages
Expand Down Expand Up @@ -52,15 +49,19 @@ class MoveRotator(BaseBlockScript):
def __init__(self, index: int, add_remotes: bool = True) -> None:
super().__init__(index=index, descr="Move Rotator")

mtcs_usage = None if add_remotes else MTCSUsages.DryTest

self.mtcs = MTCS(self.domain, intended_usage=mtcs_usage, log=self.log)
self.mtcs = MTCS(
domain=self.domain,
intended_usage=None if add_remotes else MTCSUsages.DryTest,
log=self.log,
)

for comp in self.mtcs.components_attr:
if comp not in ["mtrotator", "mtmount"]:
setattr(self.mtcs.check, comp, False)

self.rotator_time_per_angle = 5.0 # seconds per degree
self.rotator_velocity = 3.5 # degrees per second
self.short_timeout = 10 # seconds
self.long_timeout = 120 # seconds

@classmethod
def get_schema(cls):
Expand All @@ -82,14 +83,14 @@ def get_schema(cls):
minimum: -90
maximum: 90
wait_for_complete:
description: >-
whether wait for the rotator to reach the desired angle or
complete the script before the rotator reaches the desired
description: >-
whether wait for the rotator to reach the desired angle or
complete the script before the rotator reaches the desired
angle.
type: boolean
default: true
required:
- angle
- angle
additionalProperties: false
"""
schema_dict = yaml.safe_load(schema_yaml)
Expand All @@ -102,3 +103,24 @@ def get_schema(cls):
]

return schema_dict

async def configure(self, config):
self.target_angle = config.angle
self.wait_for_complete = config.wait_for_complete

await super().configure(config=config)

def set_metadata(self, metadata):
metadata.duration = self.long_timeout

async def run_block(self):
await self.checkpoint(f"Start moving rotator to {self.target_angle} degrees.")
await self.mtcs.move_rotator(
angle=self.target_angle, wait_for_complete=self.wait_for_complete
)
if self.wait_for_complete:
await self.checkpoint_message(
f"Rotator reached {self.target_angle} degrees."
)
else:
await self.checkpoint("Stop script and keep rotator moving.")
67 changes: 67 additions & 0 deletions tests/test_maintel_mtrotator_move_rotator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import asyncio
import unittest

from lsst.ts import standardscripts
Expand All @@ -31,8 +32,74 @@ class TestMoveRotator(
async def basic_make_script(self, index):
self.script = MoveRotator(index=index, add_remotes=False)

self.start_angle = 0.0 # degrees
self.very_short_sleep = 0.1 # seconds
self.script.mtcs.move_rotator = unittest.mock.AsyncMock(
side_effect=self.mock_move_rotator
)

return (self.script,)

async def mock_move_rotator(self, angle, wait_for_complete):
if wait_for_complete is False:
await asyncio.sleep(self.very_short_sleep)
else:
current_angle = self.start_angle
while current_angle < angle:
await asyncio.sleep(self.very_short_sleep)
current_angle += self.script.rotator_velocity * self.very_short_sleep

async def test_configure_default(self):
"""Test the default configuration"""

async with self.make_script():
target_angle = 45.0

await self.configure_script(angle=target_angle)

assert self.script.target_angle == target_angle
assert self.script.wait_for_complete is True
assert self.script.program is None
assert self.script.reason is None
assert self.script.checkpoint_message is None

async def test_configure_dont_wait_for_complete(self):
"""Test with the configuration where ``wait_for_complete`` is False"""

async with self.make_script():
target_angle = 45.0
wait_for_complete = False

await self.configure_script(angle=target_angle, wait_for_complete=False)

assert self.script.target_angle == target_angle
assert self.script.wait_for_complete is wait_for_complete
assert self.script.program is None
assert self.script.reason is None
assert self.script.checkpoint_message is None

async def test_configure_with_program_reason(self):
"""Testing a valid configuration: with program and reason"""

# Try configure with a list of valid actuators ids
async with self.make_script():
self.script.get_obs_id = unittest.mock.AsyncMock(
side_effect=["202306060001"]
)
await self.configure_script(
angle=10.0,
wait_for_complete=True,
program="BLOCK-123",
reason="SITCOM-321",
)

assert self.script.program == "BLOCK-123"
assert self.script.reason == "SITCOM-321"
assert (
self.script.checkpoint_message
== "MoveRotator BLOCK-123 202306060001 SITCOM-321"
)

async def test_executable(self):
scripts_dir = standardscripts.get_scripts_dir()
script_path = scripts_dir / "maintel" / "mtrotator" / "move_rotator.py"
Expand Down

0 comments on commit ebfef49

Please sign in to comment.