-
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
358 additions
and
0 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
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,21 @@ | ||
# 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 | ||
|
||
from .power_on_atcalsys import * |
255 changes: 255 additions & 0 deletions
255
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,255 @@ | ||
# 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 | ||
|
||
__all__ = ["PowerOnATCalSys"] | ||
|
||
import asyncio | ||
import collections | ||
|
||
import numpy as np | ||
import yaml | ||
|
||
from lsst.ts.idl.enums.Script import ScriptState | ||
from lsst.ts.idl.enums import ATMonochromator, ATWhiteLight | ||
|
||
from lsst.ts import salobj | ||
|
||
|
||
class PowerOnATCalSys(salobj.BaseScript): | ||
"""Powers on the ATCalSys dome flat illuminator (ATWhiteLight and ATMonochromator) | ||
required to perform imaging white light calibrations. | ||
Parameters | ||
---------- | ||
index : `int` | ||
Index of Script SAL component. | ||
Notes | ||
----- | ||
""" | ||
def __init__(self, index): | ||
super().__init__( | ||
index=index, | ||
descr="Power On AT Calibration System ", | ||
) | ||
self.whitelightsource = salobj.Remote( | ||
domain=self.domain, name="ATWhiteLight", log=self.log | ||
) | ||
|
||
self.monochromator = salobj.Remote( | ||
domain=self.domain, name="ATMonochromator", log=self.log | ||
) | ||
|
||
# self.cmd_timeout = 10 | ||
self.change_grating_time = 60 | ||
self.open_shutter_time = 20 | ||
self.chiller_temp_tolerance_relative = 0.1 | ||
self.chiller_temp_time = 60 * 2 | ||
self.track_lamp_warmup = 60 | ||
self.lamp_warmup_time = 15 * 60 | ||
|
||
@classmethod | ||
def get_schema(cls): | ||
schema_yaml = """ | ||
$schema: http://json-schema.org/draft-07/schema# | ||
$id: https://github.com/lsst-ts/ts_standardscripts/auxtel/SlewTelescopeIcrs.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: | ||
default: 20 | ||
- type: number | ||
minimum: 0 | ||
whitelight_power: | ||
description: White light power. | ||
default: 910 | ||
- type: number | ||
minimum: 0 | ||
wavelength: | ||
description: Wavelength (nm). 0 nm is for white light. | ||
default: 0 | ||
- type: number | ||
minimum: 0 | ||
grating_type: | ||
description: Grating type for each image. The choices are 0=blue, 1=red, 2=mirror. | ||
default: 2 | ||
anyOf: | ||
- type: integer | ||
enum: [0, 1, 2] | ||
entrance_slit_width: | ||
description: Width of the monochrometer entrance slit (mm) | ||
default: 5 | ||
- type: number | ||
minimum: 0 | ||
exit_slit_width: | ||
description: Width of the monochromator entrance slit (mm) | ||
default: 5 | ||
- type: number | ||
minimum: 0 | ||
additionalProperties: false | ||
""" | ||
return yaml.safe_load(schema_yaml) | ||
|
||
async def configure(self, config): | ||
"""Configure the script. | ||
Parameters | ||
---------- | ||
config : ``self.cmd_configure.DataType`` | ||
Raises | ||
------ | ||
salobj.ExpectedError : | ||
If the data does not match the schema, or the lengths | ||
of all values that are arrays do not match. | ||
""" | ||
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 | ||
|
||
self.config = config | ||
|
||
self.log.info("Configure completed") | ||
|
||
def set_metadata(self, metadata): | ||
"""Compute estimated duration. | ||
Parameters | ||
---------- | ||
metadata : SAPY_Script.Script_logevent_metadataC | ||
""" | ||
metadata.duration = 60 * 15 | ||
|
||
async def run(self): | ||
"""Run script.""" | ||
|
||
await self.checkpoint("Start the chiller") | ||
|
||
await whitelightsource.cmd_setChillerTemperature.set_start(temperature=self.chiller_temperature) | ||
await whitelightsource.cmd_startChiller.set_start() | ||
|
||
# confirm the chiller is running at chiller_temperature within tolerance | ||
try: | ||
await asyncio.wait_for( | ||
is_chiller_temp_within_tolerance(), self.chiller_temp_time | ||
) | ||
except asyncio.TimeoutError: | ||
self.log.info(f"Gave up waiting after {self.chiller_temp_time} for the chiller to chill to {self.chiller_temperature}") | ||
|
||
await self.checkpoint("Open the shutter") | ||
|
||
await whitelightsource.cmd_openShutter.set_start() | ||
|
||
# Confirm shutter is open or sent an error message? Should we include an error message if it fails rather than the RunTimeError | ||
## shutter_state = await whitelightsource.evt_shutterState.aget() | ||
|
||
await self.checkpoint("Turning on lamp") | ||
await whitelightsource.cmd_turnLampOn.set_start(power = self.whitelight_power) | ||
|
||
# Confirm lamp state turns on (It will go into a warm up period before it will turn on) | ||
try: | ||
await asyncio.wait_for( | ||
has_lamp_finish_warm_up(), self.lamp_warm_up_time | ||
), | ||
except asyncio.TimeoutError: | ||
self.log.info(f"Lamp didn't turn on after {self.lamp_warm_up_time} s") | ||
|
||
await self.checkpoint("Configuring ATMonochromator") | ||
|
||
await self.checkpoint("Set the grating") | ||
|
||
await monochromator.cmd_selectGrating.set_start(gratingType=self.grating, timeout = 180) | ||
|
||
await self.checkpoint("Set wavelength") | ||
|
||
await monochromator.cmd_changeWavelength.set_start(wavelength=self.wavelength) | ||
|
||
await self.checkpoint("Set slits wide open") | ||
|
||
await monochromator.cmd_changeSlitWidth.set_start(slit=1, slitWidth= self.entrance_slit_width) | ||
await monochromator.cmd_changeSlitWidth.set_start(slit=2, slitWidth= self.exit_slit_width) | ||
|
||
params = await get_monochromator_parameters() | ||
|
||
script.log.info(f"ATMonochromator grating is {params[0]}, wavelength is {params[1]} nm with entry slit width {param[2]} and exit slit width {param[3]}") | ||
|
||
async def get_monochromator_parameters(): | ||
tmp1 = await monochromator.evt_selectedGrating.aget() | ||
tmp2 = await monochromator.evt_wavelength.aget() | ||
tmp3 = await monochromator.evt_entrySlitWidth.aget() | ||
tmp4 = await monochromator.evt_exitSlitWidth.aget() | ||
return (tmp1.gratingType, tmp2.wavelength, tmp3.width, tmp4.width ) | ||
|
||
|
||
async def has_lamp_finish_warm_up(): | ||
lamp_done_warm_up = False | ||
start_time_lamp_warm_up = time.time() | ||
while not lamp_done_warm_up: | ||
lamp_state = await whitelightsource.evt_lampState.aget() | ||
if lamp_state.basicState == ATWhiteLight.LampBasicState.WARMUP: | ||
warmup_time_left = lamp_state.warmupEndTime - lamp_state.private_rcvStamp | ||
script.log.info("Time Left for lamp warmup: {} min.".format(warmup_time_left/60.)) | ||
await asyncio.sleep(self.track_lamp_warmup) | ||
lamp_done_warm_up = False | ||
elif lamp_state.basicState == ATWhiteLight.LampBasicState.ON: | ||
lamp_done_warm_up = True | ||
warm_up_elapsed_time = time.time() - start_time_lamp_warm_up | ||
script.log.info(f"White Light Lamp is on after {warm_up_elapsed_time} s") | ||
else: | ||
continue | ||
|
||
async def is_chiller_temp_within_tolerance(): | ||
chiller_temp_within_tolerance = False | ||
start_time_chill_time = time.time() | ||
while not chiller_temp_within_tolerance: | ||
chiller_temps = await whitelightsource.tel_chillerTemperatures.aget() | ||
if ( | ||
chiller_temps.setTemperature * (1.0 - self.chiller_temp_tolerance_relative) | ||
< chiller_temps.supplyTemperature | ||
< chiller_temps.setTemperature * (1.0 + self.chiller_temp_tolerance_relative) | ||
): | ||
chiller_temp_within_tolerance = True | ||
chill_time = time.time() - start_time_chill_time | ||
script.log.info(f"Chiller reached target temperature within tolerance in {chill_time} s") | ||
else: | ||
continue | ||
|
26 changes: 26 additions & 0 deletions
26
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,26 @@ | ||
#!/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 | ||
|
||
import asyncio | ||
|
||
from lsst.ts.standardscripts.auxtel.calibrations import PowerOnATCalSys | ||
|
||
asyncio.run(PowerOnATCalSys.amain()) |
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,56 @@ | ||
# 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 | ||
|
||
import asyncio | ||
import logging | ||
import random | ||
import unittest | ||
|
||
import pytest | ||
from lsst.ts.idl.enums import ATMonochromator, Script | ||
|
||
from lsst.ts import salobj, standardscripts | ||
from lsst.ts.standardscripts.auxtel import PowerOnATCalSys | ||
|
||
random.seed(47) # for set_random_lsst_dds_partition_prefix | ||
|
||
logging.basicConfig() | ||
|
||
class TestPowerOnATCalSys(standardscripts.BaseScriptTestCase, unittest.IsolatedAsyncioTestCase): | ||
async def basic_make_script(self, index): | ||
self.script = PowerOnATCalSys(index=index) | ||
#self.atcs_mock = ATCSMock() | ||
|
||
return (self.script, self.atcs_mock) | ||
|
||
async def test_run(self): | ||
async with self.make_script(): | ||
await self.configure_script() | ||
|
||
await self.run_script() | ||
|
||
async def test_executable(self): | ||
scripts_dir = standardscripts.get_scripts_dir() | ||
script_path = scripts_dir / "auxtel" / "calibrations" / "power_on_atcalsys.py" | ||
await self.check_executable(script_path) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |