-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
594 additions
and
0 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
python/lsst/ts/standardscripts/auxtel/calibrations/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# This file is part of ts_standardscripts | ||
# | ||
# Developed for the LSST Telescope and Site Systems. | ||
# This product includes software developed by the LSST Project | ||
# (https://www.lsst.org). | ||
# See the COPYRIGHT file at the top-level directory of this distribution | ||
# for details of code ownership. | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from .power_on_atcalsys import * |
300 changes: 300 additions & 0 deletions
300
python/lsst/ts/standardscripts/auxtel/calibrations/power_on_atcalsys.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
# This file is part of ts_standardscripts | ||
# | ||
# Developed for the LSST Telescope and Site Systems. | ||
# This product includes software developed by the LSST Project | ||
# (https://www.lsst.org). | ||
# See the COPYRIGHT file at the top-level directory of this distribution | ||
# for details of code ownership. | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# 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__ = ["PowerOnATCalSys"] | ||
|
||
import asyncio | ||
import time as time | ||
|
||
import yaml | ||
from lsst.ts.idl.enums import ATWhiteLight | ||
|
||
from lsst.ts import salobj | ||
|
||
|
||
class PowerOnATCalSys(salobj.BaseScript): | ||
"""Powers on the ATCalSys dome flat illuminator | ||
(ATWhiteLight and ATMonochromator) | ||
required to perform image calibrations over white light. | ||
Parameters | ||
---------- | ||
index : `int` | ||
Index of Script SAL component. | ||
""" | ||
|
||
def __init__(self, index, add_remotes: bool = True): | ||
super().__init__( | ||
index=index, | ||
descr="Power On AT Calibration System ", | ||
) | ||
|
||
self.white_light_source = None | ||
self.monochromator = None | ||
|
||
# White lamp config | ||
self.timeout_lamp_warm_up = 60 * 15 | ||
self.track_lamp_warmup = 60 | ||
self.cmd_timeout = 30 | ||
self.timeout_std = 20 | ||
|
||
# Chiller config | ||
self.timeout_chiller_cool_down = 60 * 15 | ||
self.chiller_temp_tolerance_relative = 0.2 | ||
|
||
# Shutter | ||
self.timeout_open_shutter = 60 * 3 | ||
|
||
@classmethod | ||
def get_schema(cls): | ||
schema_yaml = """ | ||
$schema: http://json-schema.org/draft-07/schema# | ||
$id: https://github.com/lsst-ts/ts_standardscripts/auxtel/calibrations/power_on_atcalsys.yaml | ||
title: PowerOnATCalSys v1 | ||
description: Configuration for PowerOnATCalSys. | ||
Each attribute can be specified as a scalar or array. | ||
All arrays must have the same length (one item per image). | ||
type: object | ||
properties: | ||
chiller_temperature: | ||
description: Set temperature for the chiller | ||
type: number | ||
default: 20 | ||
minimum: 10 | ||
whitelight_power: | ||
description: White light power. | ||
type: number | ||
default: 910 | ||
minimum: 0 | ||
wavelength: | ||
description: Wavelength (nm). 0 nm is for white light. | ||
type: number | ||
default: 0 | ||
minimum: 0 | ||
grating_type: | ||
description: Grating type for each image. The choices are 0=blue, 1=red, 2=mirror. | ||
type: integer | ||
enum: [0, 1, 2] | ||
default: 2 | ||
entrance_slit_width: | ||
description: Width of the monochrometer entrance slit (mm) | ||
type: number | ||
minimum: 0 | ||
default: 7 | ||
exit_slit_width: | ||
description: Width of the monochromator entrance slit (mm) | ||
type: number | ||
minimum: 0 | ||
default: 7 | ||
additionalProperties: false | ||
""" | ||
return yaml.safe_load(schema_yaml) | ||
|
||
async def configure(self, config): | ||
"""Configure the script. | ||
Parameters | ||
---------- | ||
config : ``self.cmd_configure.DataType`` | ||
""" | ||
self.log.info("Configure started") | ||
|
||
self.chiller_temperature = config.chiller_temperature | ||
self.whitelight_power = config.whitelight_power | ||
self.wavelength = config.wavelength | ||
self.grating_type = config.grating_type | ||
self.entrance_slit_width = config.entrance_slit_width | ||
self.exit_slit_width = config.exit_slit_width | ||
|
||
if self.white_light_source is None: | ||
self.white_light_source = salobj.Remote( | ||
domain=self.domain, | ||
name="ATWhiteLight", | ||
) | ||
|
||
if self.monochromator is None: | ||
self.monochromator = salobj.Remote( | ||
domain=self.domain, | ||
name="ATMonochromator", | ||
) | ||
|
||
await asyncio.gather( | ||
self.white_light_source.start_task, | ||
self.monochromator.start_task, | ||
) | ||
|
||
self.log.info("Configure completed") | ||
|
||
def set_metadata(self, metadata): | ||
"""Compute estimated duration. | ||
Parameters | ||
---------- | ||
metadata : SAPY_Script.Script_logevent_metadataC | ||
""" | ||
metadata.duration = self.timeout_chiller_cool_down + self.timeout_lamp_warm_up | ||
|
||
async def run(self): | ||
"""Run script.""" | ||
await self.assert_components_enabled() | ||
|
||
await self.checkpoint("Starting chiller") | ||
await self.start_chiller() | ||
|
||
await self.checkpoint("Waiting for chiller to cool to set temperature") | ||
await self.wait_for_chiller_temp_within_tolerance() | ||
|
||
await self.checkpoint("Opening the shutter") | ||
await self.open_white_light_shutter() | ||
|
||
await self.checkpoint("Turning on lamp") | ||
await self.switch_lamp_on() | ||
|
||
await self.checkpoint("Waiting for lamp to warm up") | ||
await self.wait_for_lamp_to_warm_up() | ||
|
||
await self.checkpoint("Configuring ATMonochromator") | ||
await self.configure_atmonochromator() | ||
|
||
async def start_chiller(self): | ||
await self.white_light_source.cmd_setChillerTemperature.set_start( | ||
temperature=self.chiller_temperature, timeout=self.cmd_timeout | ||
) | ||
await self.white_light_source.cmd_startChiller.start( | ||
timeout=self.timeout_chiller_cool_down | ||
) | ||
|
||
async def wait_for_chiller_temp_within_tolerance(self): | ||
start_chill_time = time.time() | ||
while time.time() - start_chill_time < self.timeout_chiller_cool_down: | ||
chiller_temps = await self.white_light_source.tel_chillerTemperatures.next( | ||
flush=True, timeout=self.timeout_std | ||
) | ||
tel_chiller_temp = chiller_temps.supplyTemperature | ||
self.log.debug( | ||
f"Chiller supply temperature: {tel_chiller_temp:0.1f} deg " | ||
f"[set:{chiller_temps.setTemperature} deg]." | ||
) | ||
if ( | ||
abs(chiller_temps.setTemperature - tel_chiller_temp) | ||
/ chiller_temps.setTemperature | ||
<= self.chiller_temp_tolerance_relative | ||
): | ||
chill_time = time.time() - start_chill_time | ||
self.log.info( | ||
f"Chiller reached target temperature, {tel_chiller_temp:0.1f} deg" | ||
f"within tolerance in {chill_time:0.1f} s." | ||
) | ||
break | ||
else: | ||
continue | ||
else: | ||
raise TimeoutError( | ||
f"Timeout waiting after {self.timeout_chiller_cool_down} s " | ||
f"for the chiller to chill to {chiller_temps.setTemperature} deg. " | ||
f"Stayed at {tel_chiller_temp:0.1f} deg." | ||
) | ||
|
||
async def open_white_light_shutter(self): | ||
await self.white_light_source.cmd_openShutter.start( | ||
timeout=self.timeout_open_shutter | ||
) | ||
|
||
async def switch_lamp_on(self): | ||
self.white_light_source.evt_lampState.flush() | ||
|
||
await self.white_light_source.cmd_turnLampOn.set_start( | ||
power=self.whitelight_power, timeout=self.timeout_lamp_warm_up | ||
) | ||
|
||
async def wait_for_lamp_to_warm_up(self): | ||
lamp_state = await self.white_light_source.evt_lampState.aget( | ||
timeout=self.timeout_lamp_warm_up | ||
) # gets the most recent data | ||
self.log.info( | ||
f"Lamp state: {ATWhiteLight.LampBasicState(lamp_state.basicState)!r}." | ||
) | ||
|
||
# Now enters the loop with the stop condition being that the lamp is ON | ||
|
||
while lamp_state.basicState != ATWhiteLight.LampBasicState.ON: | ||
try: | ||
lamp_state = await self.white_light_source.evt_lampState.next( | ||
flush=False, timeout=self.timeout_lamp_warm_up | ||
) | ||
self.log.info( | ||
f"Lamp state: {ATWhiteLight.LampBasicState(lamp_state.basicState)!r}." | ||
) | ||
except asyncio.TimeoutError: | ||
raise RuntimeError( | ||
f"White Light Lamp failed to turn on after {self.timeout_lamp_warm_up} s." | ||
) | ||
|
||
async def configure_atmonochromator(self): | ||
await self.monochromator.cmd_selectGrating.set_start( | ||
gratingType=self.grating_type, timeout=self.cmd_timeout | ||
) | ||
|
||
await self.monochromator.cmd_changeWavelength.set_start( | ||
wavelength=self.wavelength, timeout=self.cmd_timeout | ||
) | ||
|
||
await self.monochromator.cmd_changeSlitWidth.set_start( | ||
slit=1, slitWidth=self.entrance_slit_width, timeout=self.cmd_timeout | ||
) | ||
|
||
await self.monochromator.cmd_changeSlitWidth.set_start( | ||
slit=2, slitWidth=self.exit_slit_width, timeout=self.cmd_timeout | ||
) | ||
|
||
params = await self.get_monochromator_parameters() | ||
|
||
self.log.info( | ||
f"ATMonochromator grating is {params[0]}, \n" | ||
f"wavelength is {params[1]}, \n" | ||
f"with entry slit width {params[2]}, \n" | ||
f"and exit slit width {params[3]}" | ||
) | ||
|
||
async def get_monochromator_parameters(self): | ||
return await asyncio.gather( | ||
self.monochromator.evt_selectedGrating.aget(timeout=self.cmd_timeout), | ||
self.monochromator.evt_wavelength.aget(timeout=self.cmd_timeout), | ||
self.monochromator.evt_entrySlitWidth.aget(timeout=self.cmd_timeout), | ||
self.monochromator.evt_exitSlitWidth.aget(timeout=self.cmd_timeout), | ||
) | ||
|
||
async def assert_components_enabled(self): | ||
"""Check if ATWhiteLight and ATMonochromator are ENABLED""" | ||
for comp in [self.white_light_source, self.monochromator]: | ||
summary_state = await comp.evt_summaryState.aget() | ||
if salobj.State(summary_state.summaryState) != salobj.State( | ||
salobj.State.ENABLED | ||
): | ||
raise RuntimeError(f"{comp} is not ENABLED") |
27 changes: 27 additions & 0 deletions
27
python/lsst/ts/standardscripts/data/scripts/auxtel/calibrations/power_on_atcalsys.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/usr/bin/env python | ||
# This file is part of ts_standardscripts | ||
# | ||
# Developed for the LSST Telescope and Site Systems. | ||
# This product includes software developed by the LSST Project | ||
# (https://www.lsst.org). | ||
# See the COPYRIGHT file at the top-level directory of this distribution | ||
# for details of code ownership. | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# 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 | ||
|
||
from lsst.ts.standardscripts.auxtel.calibrations import PowerOnATCalSys | ||
|
||
asyncio.run(PowerOnATCalSys.amain()) |
Oops, something went wrong.