#!/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}")