Skip to content

Commit a6ca801

Browse files
committed
Add CBP image sequence ComCam
1 parent e376500 commit a6ca801

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed

python/lsst/ts/externalscripts/base_take_cbp_image_sequence.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,54 @@ async def configure_calsys(self):
7878
def camera(self):
7979
raise NotImplementedError()
8080

81+
@property
82+
@abc.abstractmethod
83+
def tcs(self):
84+
raise NotImplementedError()
85+
8186
@abc.abstractmethod
8287
async def configure_camera(self):
8388
"""Abstract method to configure the camera, to be implemented
8489
in subclasses.
8590
"""
8691
raise NotImplementedError()
8792

93+
@abc.abstractmethod
94+
async def configure_tcs(self):
95+
"""Abstract method to configure the tcs, to be implemented
96+
in subclasses.
97+
"""
98+
raise NotImplementedError()
99+
100+
@abc.abstractmethod
101+
def get_instrument_name(self):
102+
"""Abstract method to be defined in subclasses to provide the
103+
instrument name.
104+
"""
105+
raise NotImplementedError()
106+
107+
@abc.abstractmethod
108+
def get_instrument_configuration(self) -> dict:
109+
"""Abstract method to get the instrument configuration.
110+
111+
Returns
112+
-------
113+
dict
114+
Dictionary with instrument configuration.
115+
"""
116+
raise NotImplementedError()
117+
118+
@abc.abstractmethod
119+
def get_instrument_filter(self) -> str:
120+
"""Abstract method to get the instrument filter configuration.
121+
122+
Returns
123+
-------
124+
str
125+
Instrument filter configuration.
126+
"""
127+
raise NotImplementedError()
128+
88129
@abc.abstractmethod
89130
async def slew_azel_and_setup_instrument(self, azimuth, elevation):
90131
"""Abstract method to configure the TMA, to be implemented
@@ -139,6 +180,10 @@ def get_schema(cls):
139180
description: Elevation of TMA.
140181
type: number
141182
default: 45
183+
tma_rotator_angle:
184+
description: Rotator angle of TMA.
185+
type: number
186+
default: 0
142187
exp_time:
143188
description: Exposure times for camera.
144189
type: number
@@ -263,6 +308,7 @@ async def configure(self, config: types.SimpleNamespace):
263308
"""
264309

265310
await self.configure_camera()
311+
await self.configure_tcs()
266312
self.config = config
267313

268314
await super().configure(config)
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# This file is part of ts_externalscripts
2+
#
3+
# Developed for the LSST Telescope and Site Systems.
4+
# This product includes software developed by the LSST Project
5+
# (https://www.lsst.org).
6+
# See the COPYRIGHT file at the top-level directory of this distribution
7+
# for details of code ownership.
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
21+
__all__ = ["TakeCBPImageSequenceComCam"]
22+
23+
import yaml
24+
from lsst.ts.observatory.control.maintel.comcam import ComCam, ComCamUsages
25+
from lsst.ts.observatory.control.maintel.mtcs import MTCS, MTCSUsages
26+
27+
from ..base_take_cbp_image_sequence import BaseTakeCBPImageSequence
28+
29+
30+
class TakeCBPImageSequenceComCam(BaseTakeCBPImageSequence):
31+
"""Specialized script for taking CBP images with ComCam."""
32+
33+
def __init__(self, index):
34+
super().__init__(index=index, descr="Take CBP images with ComCam.")
35+
36+
self.mtcs = None
37+
self.comcam = None
38+
39+
@property
40+
def tcs(self):
41+
return self.mtcs
42+
43+
@property
44+
def camera(self):
45+
return self.comcam
46+
47+
async def configure_tcs(self) -> None:
48+
"""Handle creating the MTCS object and waiting remote to start."""
49+
if self.mtcs is None:
50+
self.log.debug("Creating MTCS.")
51+
self.mtcs = MTCS(
52+
domain=self.domain,
53+
intended_usage=MTCSUsages.StateTransition | MTCSUsages.Slew,
54+
log=self.log,
55+
)
56+
await self.mtcs.start_task
57+
else:
58+
self.log.debug("MTCS already defined, skipping.")
59+
60+
async def configure_camera(self) -> None:
61+
"""Handle creating the camera object and waiting remote to start."""
62+
if self.comcam is None:
63+
self.log.debug("Creating Camera.")
64+
self.comcam = ComCam(
65+
self.domain,
66+
intended_usage=ComCamUsages.TakeImageFull
67+
| ComCamUsages.StateTransition,
68+
log=self.log,
69+
tcs_ready_to_take_data=self.mtcs.ready_to_take_data,
70+
)
71+
await self.comcam.start_task
72+
else:
73+
self.log.debug("Camera already defined, skipping.")
74+
75+
@classmethod
76+
def get_schema(cls):
77+
schema_yaml = """
78+
$schema: http://json-schema.org/draft-07/schema#
79+
$id: https://github.com/lsst-ts/ts_externalscripts/take_cbp_image_sequence_comcam.yaml
80+
title: TakeCBPImageSequenceComCam v1
81+
description: Configuration for TakeCBPImageSequenceComCam.
82+
type: object
83+
properties:
84+
filter:
85+
description: Filter name or ID.
86+
anyOf:
87+
- type: string
88+
- type: integer
89+
minimum: 1
90+
- type: "null"
91+
additionalProperties: false
92+
"""
93+
schema_dict = yaml.safe_load(schema_yaml)
94+
95+
base_schema_dict = super(TakeCBPImageSequenceComCam, cls).get_schema()
96+
97+
for prop in base_schema_dict["properties"]:
98+
schema_dict["properties"][prop] = base_schema_dict["properties"][prop]
99+
100+
return schema_dict
101+
102+
def get_instrument_name(self) -> str:
103+
"""Get instrument name.
104+
105+
Returns
106+
-------
107+
instrument_name: `string`
108+
"""
109+
return "LSSTComCam"
110+
111+
def get_instrument_configuration(self) -> dict:
112+
return dict(
113+
filter=self.config.filter,
114+
)
115+
116+
def get_instrument_filter(self) -> str:
117+
"""Get instrument filter configuration.
118+
119+
Returns
120+
-------
121+
instrument_filter: `string`
122+
"""
123+
return f"{self.config.filter}"
124+
125+
async def slew_azel_and_setup_instrument(self, az, el):
126+
"""Abstract method to set the instrument. Change the filter
127+
and slew and track target.
128+
129+
Parameters
130+
----------
131+
az : float
132+
Azimuth of target field.
133+
el : float
134+
Elevation of target field.
135+
"""
136+
current_filter = await self.comcam.get_current_filter()
137+
138+
if current_filter != self.config.filter:
139+
self.log.debug(
140+
f"Filter change required: {current_filter} -> {self.config.filter}"
141+
)
142+
await self.comcam.setup_filter(filter=self.config.filter)
143+
else:
144+
self.log.debug(
145+
f"Already in the desired filter ({current_filter}), slewing."
146+
)
147+
148+
await self.mtcs.point_azel(
149+
az=az,
150+
el=el,
151+
rot_tel=self.tma_rotator_angle,
152+
)
153+
154+
async def configure(self, config):
155+
"""Take the sequence of twilight flats twilight flats."""
156+
self.configure_client()
157+
await super().configure(config)

0 commit comments

Comments
 (0)