#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# System modules
from time import sleep
# Third-party modules
from astropy.time import Time
# Other templates
from ..config.constants import (camera_state, filter_name, filter_number,
filter_state, frame_number, frame_type,
image_state, temp_fits)
from ..devices import cam, dom, tel
from ..utils.coordinates import apply_offset
from ..utils.logger import log
from .basetemplate import BaseTemplate
from .fillheader import Template as FillHeader
from .lampsoff import Template as LampsOff
[docs]
class Template(BaseTemplate):
def __init__(self):
super().__init__()
self.name = "observation"
self.description = "Observes a field"
# self.box = 300
# self.recenter = False
# #self.domeslewing = None
# if not hasattr(self, "domeslewing"):
# log.warning("domeslewing attribute undefined, setting to False")
# self.domeslewing = False
[docs]
def content(self, params):
########################
##### Params check #####
########################
try:
objname = params.get("object") or "test"
repeat = params.get("repeat") or 1
frametype = params.get("frametype") or "Light"
binning = params.get("binning") or cam.binning
filt = params.get("filter") or filter_name[cam.filter]
xystart = params.get("xystart") or cam.xystart
xyend = params.get("xyend") or cam.xyend
exptime = params["exptime"]
self.domeslewing = params.get("domeslewing") or False
self.recenter = params.get("recenter") or False
self.box = params.get("box") or 300
except KeyError as e:
msg = f"Parameter {e} not found"
log.error(msg)
self.error.append(msg)
return
#########################################
##### Switch off lamps if not Flat #####
#########################################
if frametype != "Flat":
log.info("Not a 'Flat' frametype: switching off lamps")
lao = LampsOff()
lao.run({})
if frametype != "Light":
log.info("Not a 'Light' frametype: switching off recentering")
self.recenter = False
########################
##### Camera setup #####
########################
# Bringing back the camera to Idle state.
if cam.state != 0:
log.warning(
f"Resetting camera from state {camera_state[cam.state]}.")
cam.abort()
sleep(0.1)
log.info(f"Camera is {camera_state[cam.state]}")
# Changing binning if not the same as the current one
if binning != cam.binning:
log.info(f"Changing binning to {binning}")
cam.binning = [binning, binning]
sleep(0.1)
log.info(f"Camera is {camera_state[cam.state]}")
# Changing filter if not the same as the current one
# On bad ctrl-c, filter can be 15 (?!)
log.warning(f"Filter is number {cam.filter}")
log.warning(
f"Filter is {filter_name[cam.filter]}, we have selected {filt}")
if filter_number[filt] != cam.filter:
msg = f"Changing filter to {filt}, "
msg += f"Which is number {filter_number[filt]}"
log.info(msg)
# Setting filter based on its number
cam.filter = filter_number[filt]
sleep(0.2)
# Check until filter is not moving
status = 1
while status != 0:
self.check_pause_or_abort()
try:
status = int(cam.is_moving)
except ValueError as e:
msg = f"Error trying to contact the camera: {e}"
log.error(msg)
self.error.append(msg)
if status == 2: # i.e. error in moving filter
msg = f"Filter {filter_state[status]}"
log.error(msg)
self.error.append(msg)
return
else:
log.warning(f"Filter {filter_state[status]}")
sleep(0.75)
# Changing windowing
if xystart and xyend:
log.info(
f"Changing windowding to xystart:{xystart}, xyend:{xyend}")
cam.xystart = xystart
cam.xyend = xyend
else:
msg = f"No windowing: full frame in bininng {binning}"
log.warning(msg)
cam.full_frame()
#########################
##### Exposure loop #####
#########################
log.info(f"Starting {repeat} {frametype} frames of {exptime}s")
# Looping on the number of exposures
for exposure in range(repeat):
if self.check_pause_or_abort():
return
# RA, DEC, ALT, AZ, UTC are asked to cabinet
# simultaneously in order to avoid latency.
log.info(f"Asking cabinet time and coordinates")
basic_cabinet = tel.coordinates
gps = Time(tel.coordinates["utc"], format="unix")
log.info(f"Starting Exposure {exposure} of {repeat - 1}")
# ########################
# ##### Dome Slewing #####
# ########################
log.info(f"Dome slewing is {self.domeslewing}")
if frametype == "Light":
if self.domeslewing:
log.info(f"Check Dome position")
while (abs(tel.coordinates["altaz"][1] - dom.azimuth) > 3):
if not self.domeslewing:
log.debug("Stop slewing anyway")
return
dom.azimuth = tel.coordinates["altaz"][1]
sleep(0.5)
while dom.is_moving:
if self.check_pause_or_abort():
log.debug(
"check_pause_or_abort returned true. I'm here")
return
log.warning(f"Waiting for Dome to Stop")
sleep(0.5)
##########################
##### Start exposure #####
##########################
try:
cam.start(exptime,
frame_number[frametype],
datetime=gps.isot)
except Exception as e:
msg = f"An error occurred : {e}"
log.error(msg)
self.error.append(msg)
return
# Some debug time counter
now = Time.now()
# Checking if the exposure is still running
status = 1
while status != 0:
if self.check_pause_or_abort():
log.debug("check_pause_or_abort returned true. I'm here")
return
try:
status = int(cam.state)
except TypeError as e:
msg = f"Error trying to read camera status: {e}"
log.error(msg)
self.error.append(msg)
if status == 5: # i.e. error in camera
msg = f"Camera {camera_state[status]}"
log.error(msg)
self.error.append(msg)
return
else:
elapsed = (Time.now() - now).sec
msg = f"Camera {
camera_state[status]}, {
elapsed:.1f}/{exptime}s "
msg += f"of exposure {exposure}/{repeat - 1}"
log.warning(msg)
sleep(0.75)
log.debug("check_pause_or_abort before the download")
if self.check_pause_or_abort():
log.debug("check_pause_or_abort returned true. I'm here")
return
################################
##### Download from camera #####
################################
log.info(f"Downloading frame as {temp_fits}")
# Checking if the image is ready to be downloaded
while cam.ready != 1:
sleep(0.5)
if self.check_pause_or_abort():
log.warning(f"Buffer still {image_state[cam.ready]}")
return
cam.download()
log.info(f"Elapsed {(Time.now() - now).sec:.2f}")
##################################
##### Update header and save #####
##################################
fih_params = {
"object": objname,
# Add in some way also ob_file and template name from json
}
fih_params.update(basic_cabinet) # radec, altaz, utc, lst
fih = FillHeader()
fih.run(fih_params)
log.debug(f"observation {fih.filename}")
self.filename = fih.filename
self.filenames.append(fih.filename)
log.debug(f"filenames from obs tpl {self.filenames}")
######################################
##### Calculate and apply offset #####
######################################
log.info(f"Recenter is {self.recenter}")
if self.recenter:
log.info(f"... with box={self.box}px")
if frametype == "Light":
if self.recenter:
try:
apply_offset(
fits_file=temp_fits, box=self.box, display=False)
except Exception as e:
log.warning(f"Cannot apply offset: {e}")
return