Source code for noctua.templates.observation

#!/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