Source code for noctua.templates.fillheader

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Third-party modules
import numpy as np
from astropy import units as u
from astropy.io import fits
from astropy.time import Time

# Other templates
from ..config.constants import alt, lat, lon, pixscale, rotangle, temp_fits
from ..devices import cam, dom, foc, lamp, light, rot, tel, tel_temp
from ..utils.logger import log
from ..utils.structure import save_filename
from .basetemplate import BaseTemplate


[docs] class Template(BaseTemplate): def __init__(self): super().__init__() self.name = "fillheader" self.description = "Fills the header of observed FITS files"
[docs] def content(self, params): ######################## ##### Params check ##### ######################## try: save = params.get("save") or True objname = params.get("object") or "test" ob = params.get("ob") or None tpl = params.get("template") or None radec = params["radec"] altaz = params["altaz"] utc = params["utc"] lst = params["lst"] except KeyError as e: log.error(f"Parameter {e} not found") return ######################### ##### Header update ##### ######################### filename = temp_fits gps = Time(utc, format="unix") try: with fits.open(filename, 'update') as h: for hdu in h: ###################### ##### Basic info ##### ###################### now1 = Time.now() # log.debug(f"CONST keys start {(Time.now()-now).sec :.2f}") hdu.header['object'] = objname, "Object name" hdu.header['latitude'] = lat, "[deg] Telescope latitude N" hdu.header['longitud'] = lon, "[deg] Telescope longitude E from Greeenwich" hdu.header['altitude'] = alt, "[m] Telescope height from sea level" hdu.header['equinox'] = 2000, "Equinox" hdu.header['date'] = Time.now( ).isot, "(UTC) Date the file was written" # log.debug(f"CONST keys end {(Time.now()-now).sec :.2f}") ######################## ##### Cabinet info ##### ######################## # now = Time.now() # log.debug(f"CABINET keys start {(Time.now()-now).sec :.2f}") # Asking to the cabinet basic info (ra, dec, alt, az, utc) hdu.header['alt'] = altaz[0], "[deg] Altitude at start" hdu.header['az'] = altaz[1], "[deg] Azimuth clockwise from N at start" hdu.header['ra'] = radec[0] * \ 15.0, "[deg] Right ascension J2000 at start" hdu.header['dec'] = radec[1], "[deg] Declination J2000 at start" hdu.header['mjd-obs'] = gps.mjd, "[day] (MJD) Date the exposure was started" hdu.header['date-obs'] = gps.isot[:- 4], "(UTC) Date the exposure was started" hdu.header['lst'] = lst, "Local Sidereal Time" hdu.header['ha'] = lst - radec[0], "Hour Angle at start" alt_rad = np.radians(altaz[0]) sec_z = np.nan if np.isclose( np.sin(alt_rad), 0) else round( 1 / np.sin(alt_rad), 2) hdu.header['airmass'] = sec_z, "Airmass at start" focrel = foc.position focabs = foc.absolute temperatures = tel_temp.temperature cover = tel.cover hdu.header['telfocus'] = focrel, "[mm] M2 Relative position" hdu.header['hierarch TEL FOC REL'] = focrel, "[mm] M2 Relative position" hdu.header['hierarch TEL FOC ABS'] = focabs, "[mm] M2 Absolute position" hdu.header['hierarch TEL M1 TEMP'] = temperatures[0], "[C] M1 temperature" hdu.header['hierarch TEL M2 TEMP'] = temperatures[1], "[C] M2 temperature" hdu.header['hierarch TEL M3 TEMP'] = temperatures[2], "[C] M3 temperature" hdu.header['hierarch TEL COVER'] = cover, "M1 cover. 1.0 if full open, 0.0 if close" # log.debug(f"CABINET keys end {(Time.now()-now).sec :.2f}") ###################### ##### ASCOM info ##### ###################### # now = Time.now() # log.debug(f"ASCOM keys start {(Time.now()-now).sec :.2f}") rotpos = rot.position rotabs = rot.absolute hdu.header['hierarch TEL ROT REL'] = rotpos, "[deg] Relative rotator position angle" hdu.header['hierarch TEL ROT ABS'] = rotabs, "[deg] Absolute rotator position angle" hdu.header['hierarch TEL OFFSET ALT'] = tel.offset[0], "[rad] Offset in alt" hdu.header['hierarch TEL OFFSET AZ'] = tel.offset[1], "[rad] Offset in az" hdu.header['hierarch TEL PARKED'] = tel.park, "True if telescope is parked" hdu.header['hierarch DOM AZIMUTH'] = dom.azimuth, "[deg] Dome Azimuth clockwise from N" hdu.header['hierarch DOM SHUTTER'] = dom.open, "Dome Shutter. False if close, True if open" hdu.header['hierarch DOM SLAVED'] = dom.slave, "True if dome slaved to telescope at start" hdu.header['hierarch DOM LAMP'] = lamp.state, "Flat lamp. True if on, False if off" hdu.header['hierarch DOM LIGHT'] = light.state, "Dome light. True if on, False if off" # log.debug(f"ASCOM keys end {(Time.now()-now).sec :.2f}") ####################### ##### Camera info ##### ####################### # Calling all from camera's GetImageParamter.cgi ca = cam.all xpixscale = round(pixscale * int(ca["binning"][0]), 3) ypixscale = round(pixscale * int(ca["binning"][1]), 3) camx = ca["xrange"] camy = ca["yrange"] hdu.header['hierarch CAM AMBIENT'] = ca["ambient"], "[C] Camera ambient temperature" hdu.header['hierarch CAM FAN'] = ca["fan"], "Cooler power in percent of usage" hdu.header['hierarch CAM COOLER'] = ca["cooler"], "Camera cooler. True if on, False if off" hdu.header['hierarch CAM TEMP'] = ca["temperature"], "[C] Camera temperature" hdu.header['hierarch CAM XPIXSCALE'] = xpixscale, "[arcsec/px] X scale of px in current binning" hdu.header['hierarch CAM YPIXSCALE'] = ypixscale, "[arcsec/px] Y scale of px in current binning" hdu.header['hierarch CAM XRANGE'] = str( camx), "[x_start, x_end] in current binning" hdu.header['hierarch CAM YRANGE'] = str( camy), "[y_start, y_end] in current binning" # #log.debug(f"CAM keys end {(Time.now()-now).sec :.2f}" ######################## ##### WCS keywords ##### ######################## xdegscale = xpixscale * u.arcsec.to(u.deg) ydegscale = ypixscale * u.arcsec.to(u.deg) angle = np.deg2rad(rotpos + rotangle) flip = -1 hdu.header["WCSAXES"] = 2 hdu.header["CRPIX1"] = ( camx[1] - camx[0]) / 2., "Pixel coordinate of reference point" hdu.header["CRPIX2"] = ( camy[1] - camy[0]) / 2., "Pixel coordinate of reference point" hdu.header["PC1_1"] = np.cos( angle), "Coordinate transformation matrix element" hdu.header["PC2_1"] = np.sin( angle), "Coordinate transformation matrix element" hdu.header["PC1_2"] = np.sin( angle), "Coordinate transformation matrix element" hdu.header["PC2_2"] = flip * \ np.cos(angle), "Coordinate transformation matrix element" hdu.header["CDELT1"] = xdegscale, "[deg] Coordinate increment at reference point" hdu.header["CDELT2"] = ydegscale, "[deg] Coordinate increment at reference point" hdu.header["CUNIT1"] = 'deg', "Units of coordinate increment and value" hdu.header["CUNIT2"] = 'deg', "Units of coordinate increment and value" hdu.header["CTYPE1"] = 'RA---TAN', "Right ascension, gnomonic projection" hdu.header["CTYPE2"] = 'DEC--TAN', "Declination, gnomonic projection" hdu.header["CRVAL1"] = radec[0] * 15.0 hdu.header["CRVAL2"] = radec[1] hdu.header["RADESYS"] = "ICRS" # wcss = WCS() # wcss.wcs.ctype = ["RA---TAN", "DEC--TAN"] # wcss.wcs.cd = scale*np.array([[np.cos(angle), np.sin(angle)], # [np.sin(angle), flip*np.cos(angle)]]) # wcss.wcs.cunit = ['deg', 'deg'] # wcss.wcs.crval = [radec, # radec*15] # wcss.wcs.crpix = [ (camx[1]-camx[0])/2., # (camy[1]-camy[0])/2.] # hdu.header.update(wcss.to_header()) log.debug( f"Header updated in {(Time.now() - now1).sec:.2f}") except FileNotFoundError as e: log.error("File not found") log.error(e) ############################### ##### Saving in data path ##### ############################### if save: outpath = save_filename(filename) log.info(f"Copying {filename} as {outpath}") self.filename = str(outpath) log.debug(f"fillheader {self.filename}")