kcas_calib
Parses a calibration flat file and take calibration images
usage: kcas_calib: [-h, --help] [-f, --file] [-n, --night] [-p, --park] [-d, --dry-run]
#! @KPYTHON@
from KCWI import Calibration, Blue
from KCWI.Helper import say
import argparse
import sys, os, time
import ktl
import signal
# Parsing arguments
description = "Parses a calibration flat file and take calibration images"
parser = argparse.ArgumentParser(description=description)
parser.add_argument('-f','--file',dest='filen',nargs="?",default=None, help='File to load cal script from')
parser.add_argument('-n','--night',dest='night',default=False, help='Is this a night-time calibration (auto-parks) ?', action='store_true')
parser.add_argument('-p','--park',dest='park',default=False, help='Park calibration unit at the end', action='store_true')
parser.add_argument('-d','--dry-run',dest='dry',default=False, help='List steps but do not execute calibrations', action='store_true')
thar_lampid=1
fear_lampid=0
cont_lampid=3
dome_lampid=-1
bias_lampid=-2
dark_lampid=-3
def sig_handler(signum, frame, dry):
say("Stop (CTRL+C) detected.")
# turns lamps off
execute(dry, Calibration.lamp,'all','off')
# CLOSE shutters
execute(dry, Calibration.lamp_shutter,'thar','close')
execute(dry, Calibration.lamp_shutter,'fear','close')
# abort exposure
exposeip = ktl.cache('kbds','exposip')
if exposeip.read() == 1:
say("Aborting current exposure")
abortex = ktl.cache('kbs','abortex')
execute(dry, abortex.write, 1)
# abort movements
status = ktl.cache('kcas','status')
status.monitor()
if status.read() == 'Moving':
abort = ktl.cache('kcas','abort')
execute(dry, abort.write, 1)
ok = ktl.Expression('kcas.status == OK')
result = ok.wait(timeout = 30)
execute(dry, Calibration.cal_mirror, 'Sky')
sys.exit(0)
def printInfo(calibration):
say("")
say("Executing the following calibration:")
say("Lamp: %s, Object: %s, Exptime: %s, Afternoon exposures: %s, Night exposures: %s, Geometry: %s" % \
(calibration['lamp'],calibration['object'],calibration['exptime'],calibration['afternoon'],calibration['night'],calibration['geometry']))
def setObject(calibration):
if calibration['geometry']=='1':
geometryFlag = "/Mode=Geom"
else:
geometryFlag = ""
if calibration['lamp']=='DARK':
lampFlag = "None"
else:
lampFlag = calibration['lamp']
currentObject = "Lamp=%s/CalObj=%s/Expt=%s sec.%s" % (lampFlag,calibration['object'],calibration['exptime'],geometryFlag)
say("Setting object to: %s" % (currentObject))
object = ktl.cache('kbds','object')
object.write(currentObject)
# this is a wrapper that disables the functions if in dry-run mode
def execute(dry, func, *args, **kwargs):
if not dry:
func(*args, **kwargs)
else:
string_args = []
for arg in args:
string_args.append(str(arg))
print "DRY RUN: %s(%s)" % (func.__name__,
','.join(list(string_args) + ["%s=%s" % (str(k), str(v)) for (k, v) in kwargs.iteritems()]))
def convertLampNametoID(lampname):
lampname = lampname.lower()
if lampname in ['thar','tha','th','t',1]:
lampid = thar_lampid
elif lampname in ['fear','fea','fe','f','f',0]:
lampid = fear_lampid
elif lampname in ['continuum','cont','led',3]:
lampid = cont_lampid
elif lampname in ['dome','dom','d',-1]:
lampid = dome_lampid
elif lampname in ['bias','bs',-2]:
lampid = bias_lampid
elif lampname in ['dark','dar','dk']:
lampid = dark_lampid
else:
say("Error: Invalid lamp %s" % (lampname))
sys.exit(1)
return lampid
def CheckObjectName(object):
object = object.lower()
if object in ['dark','0','pin300','1','medbarsa','medbars','2','medbarsb','3','finbars','4', \
'diaglin','5','flata','flat','6','flatb','7','lrgbarsa','lrgbars','8','lrgbarsb', \
'lrgbars','9','pin500','10','tpat','11','horlin','12','mira','13']:
return
else:
say("Error: Unkown object %s" % (object))
sys.exit(1)
def convertGeometryFlag(flag):
flag = flag.lower()
if flag in ['yes','y','1']:
convflag = 1
elif flag in ['no','n','0']:
convflag = 0
return convflag
def kcas_calib(filen,night,park, dry):
caltype="day"
park=0
dark = False
if night:
caltype='night'
park = 1
thar_used=0
fear_used=0
dome_used=0
expectedNumberOfColumns = 6
# record current detector status
detAmpmodeInit = Blue.ampmodeb()
detGainMulInit = Blue.gainmulb()
detCcdModeInit = Blue.ccdmodeb()
detExptimeInit = Blue.tintb()
detSleep = 2
# create an empty array of calibrations to be executed
# this will be an array of dictionaries
Calibrations = []
# check if the file exists, and read it
try:
say("Opening file %s" % (filen))
calFile = open(filen,"r")
lines = calFile.readlines()
calFile.close()
except:
raise RuntimeError("The input flat file does not exist")
# process the lines
for line in lines:
# skip comments
if '#' in line:
continue
# if the line contains an = sign, then it indicates the original state file
if '=' in line:
statusFile = line.split('=')[1]
continue
# for all other cases, ingest the information
data = line.split()
if len(data) != expectedNumberOfColumns:
say("Skipping line: %s" % line)
continue
else:
calibration = {}
calibration["lamp"]=data[0]
calibration["object"]=data[1]
calibration["exptime"]=data[2]
calibration["afternoon"]=data[3]
calibration["night"]=data[4]
calibration["geometry"]=data[5]
# add the current calibration line to the array
Calibrations.append(calibration)
# make sure the calibration axes are homed
kcas = ktl.cache('kcas')
calxhomed = kcas['calxhomed']
calyhomed = kcas['calyhomed']
calmhomed = kcas['calmhomed']
for axis in [calxhomed,calyhomed,calmhomed]:
if int(axis['ascii'])==0:
say("Calibration axis %s is not homed" % axis['NAME'])
exit(1)
# conversions and checks
for calibration in Calibrations:
# lamp
calibration["lampid"] = convertLampNametoID(calibration["lamp"])
# object
CheckObjectName(calibration["object"])
# geometry
calibration["geometry"] = convertGeometryFlag(calibration["geometry"])
# check which lamps are used (continumm is always used)
thar_used = 0
fear_used = 0
dome_used = 0
for calibration in Calibrations:
if (caltype == 'day' and int(calibration['afternoon']) > 0) or (caltype == 'night' and int(calibration['night']) > 0):
if calibration['lampid'] == thar_lampid:
thar_used = 1
if calibration['lampid'] == fear_lampid:
fear_used = 1
if (caltype == 'day' and int(calibration['afternoon']) > 0):
if calibration['lampid'] == dome_lampid:
dome_used = 1
say("Caltype = %s" % (caltype))
say("Thar used = %s" % (str(thar_used)))
say("Fear used = %s" % (str(fear_used)))
say("Dome used = %s" % (str(dome_used)))
if (thar_used):
execute(dry,Calibration.lamp,'thar','on')
execute(dry,Calibration.lamp_shutter,'thar','close')
if (fear_used):
execute(dry,Calibration.lamp,'fear','on')
execute(dry,Calibration.lamp_shutter,'fear','close')
# Close the hatch
execute(dry,Calibration.hatch,'close')
# Loop through the calibrations (INTERNAL ONLY)
for calibration in Calibrations:
# skip the dome calibration
if calibration['lampid'] == dome_lampid:
continue
#
time.sleep(1)
# print info
printInfo(calibration)
# set object
setObject(calibration)
if caltype == 'day':
count = calibration['afternoon']
elif calitype == 'night':
count = calibration['night']
say("Count: %s" % (count))
say("Geomtry: %s" % (calibration['geometry']))
autoshut = ktl.cache('kbds','autoshut')
if int(count) > 0:
if calibration['lampid'] == fear_lampid:
execute(dry, Calibration.lamp_shutter,'fear','open')
execute(dry, Calibration.lamp_shutter,'thar','close')
execute(dry, Calibration.lamp,'cont','off')
dark = False
if calibration['lampid'] == thar_lampid:
execute(dry, Calibration.lamp_shutter,'fear','close')
execute(dry, Calibration.lamp_shutter,'thar','open')
execute(dry, Calibration.lamp,'cont','off')
dark = False
if calibration['lampid'] == cont_lampid:
execute(dry, Calibration.lamp_shutter,'fear','close')
execute(dry, Calibration.lamp_shutter,'thar','close')
execute(dry, Calibration.lamp,'cont','on')
dark = False
if calibration['lampid'] == dark_lampid or calibration['lampid'] == bias_lampid:
execute(dry, Calibration.lamp_shutter,'fear','close')
execute(dry, Calibration.lamp_shutter,'thar','close')
execute(dry, Calibration.lamp,'cont','off')
dark = True
# move mirror axis
execute(dry, Calibration.cal_mirror,position="Mirror")
# move calx and caly objects
execute(dry, Calibration.cal_object,position=calibration['object'])
# set exposure time
execute(dry, Blue.tintb,str(calibration['exptime']))
# if geometry is set to 1, modify the detector configuration
if calibration['geometry'] != 0:
execute(dry, Blue.ampmodeb,0)
execute(dry, Blue.gainmulb,10)
execute(dry, Blue.ccdmodeb,1)
# otherwise restore the initial configuration
else:
execute(dry, Blue.ampmodeb,detAmpmodeInit)
execute(dry, Blue.gainmulb,detGainMulInit)
execute(dry, Blue.ccdmodeb,detCcdModeInit)
# exposure time
execute(dry, Blue.tintb,calibration['exptime'])
# take exposures
say("Exposing. Count = %d, Dark = %s." % (int(count),str(dark)))
execute(dry, Blue.goib,count, dark)
# turn off continuum
execute(dry, Calibration.lamp,'cont','off')
# close arc shutters
execute(dry, Calibration.lamp_shutter,'thar','close')
execute(dry, Calibration.lamp_shutter,'fear','close')
# return detector to initial configuration
execute(dry, Blue.ampmodeb,detAmpmodeInit)
execute(dry, Blue.gainmulb,detGainMulInit)
execute(dry, Blue.ccdmodeb,detCcdModeInit)
# Loop through the calibrations (DOME ONLY)
dark = False
if dome_used:
for calibration in Calibrations:
# skip the internal calibrations
if calibration['lampid'] != dome_lampid:
continue
# print info
printInfo(calibration)
if caltype == 'day':
count = calibration['afternoon']
elif calitype == 'night':
count = calibration['night']
say("Count: %s" % (count))
say("Geomtry: %s" % (calibration['geometry']))
# TURN ON DOME LAMPS
# INSERT A CALL TO THE COMMAND TO TURN ON DOME LAMPS TBD !!!!!!!!
# open hatch
execute(dry, Calibration.hatch,'open')
# move cal mirrot out of the way
execute(dry, Calibration.cal_mirror,position='Sky')
# move cal x y in place
execute(dry, Calibration.cal_object,position=calibration['object'])
# set exposure time
execute(dry, Blue.tintb,calibration['exptime'])
# take exposures
say("Exposing. Count = %d, Dark = %s." % (int(count),str(dark)))
execute(dry, Blue.goib,count, dark)
# return exposure time to original
execute(dry, Blue.tintb,detExptimeInit)
# close arc shutters, turns off continuum
execute(dry, Calibration.lamp_shutter,'thar','close')
execute(dry, Calibration.lamp_shutter,'fear','close')
execute(dry, Calibration.lamp,'cont','off')
if park:
# turns off lamps
execute(dry, Calibration.lamp,'all','off')
execute(dry, Calibration.cal_object,'Dark')
execute(dry, calibration.cal_mirror,'Sky')
if __name__ == '__main__':
args = parser.parse_args()
filen = args.filen
night = args.night
park = args.night
dry = args.dry
signal.signal(signal.SIGINT,sig_handler)
signal.signal(signal.SIGILL,sig_handler)
signal.signal(signal.SIGTERM,sig_handler)
kcas_calib(filen, night, park, dry)