def mark(): dcs = ktl.Service('dcs') instrument = dcs.read('INSTRUME') instService = ktl.Service(instrument) raoff = dcs['raoff'] decoff = dcs['decoff'] raoff = raoff * 180 * 3600 / math.pi decoff = decoff * 180 * 3600 / math.pi dec = dcs.read('dec') raoff = raoff * math.cos(dec) instService['RAOFFSET'].write(raoff) instService['DECOFFSET'].write(decoff) log = KeckLogger.getLogger() log.info("[mark] stored offsets RA %f, DEC %f" % (x, y)) return True
def __init__(self, service_name, service_config_dict, verbose=True): self.andor_service = ktl.Service(service_name) # _write_keywords(self.andor_service, service_config_dict) _write_keywords(self.andor_service, service_config_dict, verbose=verbose)
def __init__(self, task='example', test=False): self.test = test self.task = task self.apfucam = ktl.Service('apfucam') self.apftask = ktl.Service('apftask') self.apfmot = ktl.Service('apfmot') self.combo_ps = self.apfucam['combo_ps'] self.combo_ps.monitor() self.ctalkto = self.apfucam['ctalkto'] self.ctalkto.monitor() self.ucam_command = self.apftask['UCAMLAUNCHER_UCAM_COMMAND'] self.ucam_command.monitor() self.ucam_status = self.apftask['UCAMLAUNCHER_UCAM_STATUS'] self.ucam_status.monitor()
def mxy(n, abs, x, y): dcs = ktl.Service('dcs') instrument = dcs.read('INSTRUME') #TODO double check if math is right on CSU conversion if instrument == 'mosfire': #CSU conversion angle = 0.136 # offset between CSU and detector [deg] x = (x * math.cos(math.radians(angle))) + ( y * math.sin(math.radians(angle))) y = (y * math.cos(math.radians(angle))) - (x * sin(math.radians(angle))) instxoff = dcs['instxoff'] instyoff = dcs['instyoff'] if n == True: print( "[mxy] move command (NOT SENT) is: instxoff.write(%f) instyoff.write(%f)" % (x, y)) return if abs == True: print('Sending moves rel2base') instxoff.write(x, rel2base='t') instyoff.write(y, rel2base='t') else: print('Sending moves rel2curr') instxoff.write(x, rel2curr='t') instyoff.write(y, rel2curr='t') elapsedTime = wftel() log = KeckLogger.getLogger() log.info("[mxy] offest %f, %f, abs = %s in detector coordinates" % (x, y, abs)) print("[mxy] wftel completed in %f sec" % elapsedTime) return
def start(self): '''Start monitoring 'trigger' keyword for new files.''' #Get service instance. Keep retrying if it fails. try: self.service = ktl.Service(self.servicename) except Exception as e: log.error(traceback.format_exc()) msg = (f"Could not start KTL monitoring for {self.instr} '{self.service}'. " f"Retry in {KTL_START_RETRY_SEC} seconds.") log.error('KTL_START_ERROR: ' + msg) threading.Timer(KTL_START_RETRY_SEC, self.start).start() return #get keyword that indicates new file and define callback kw = self.service[self.keys['trigger']] kw.callback(self.on_new_file) # Start monitoring. Prime callback to ensure it gets called at least once with current val if kw['monitored'] == True: self.on_new_file(kw) else: kw.monitor() #establish heartbeat restart mechanism and service check interval hb = self.keys.get('heartbeat') if hb: period = hb[1] + 10 #add 10 seconds of padding if period < 30: period = 30 #not too small self.service.heartbeat(hb[0], period) threading.Timer(SERVICE_CHECK_SEC, self.check_service).start() self.check_failed = False self.resuscitations = self.service.resuscitations
def startTelescope(): '''This starts up the telescope if the Az drive is disabled or the E-Stop State is True If the telescope is just disabled, the start up procedure for a new version of scriptobs should clear that state. ''' rv = False eosdome = ktl.Service('eosdome') isenabled = eosdome['AZDRVENA'].read(binary=True) isstopped = eosdome['ESTOPST'].read(binary=True) fullstop = eosdome['SWESTOP'].read(binary=True) if fullstop: rv = False # cannot start the telescope else: # we can! if isstopped: eosdome['ESTOPCMD'].write('ResetEStop') if isenabled is False: eosdome['AZENABLE'].write('Enable') isenabled = eosdome['AZDRVENA'].read(binary=True) isstopped = eosdome['ESTOPST'].read(binary=True) if isenabled and isstopped is False: rv = True else: rv = False return rv
def wftel(): dcs = ktl.Service('dcs') autresum = dcs.read('autresum') startTime = time.time() axestat = dcs.monitor('AXESTAT') ktl.waitfor(axestat == "tracking") active = dcs.read("AUTACTIV") if (active == 'no'): print("WARNING: guider not currently active.\n") return count = 0 while (True): if autresum != dcs.read('autresum'): break count += 1 if count >= 20: print( "[wftel] WARNING: timeoutwaiting for AUTRESUM to increment\n\a" ) break time.sleep(1) count = 0 while (true): autgo = dcs.read('autgo') if autgo.upper() == "RESUMEACK" or augo.upper() == "GUIDE": break count += 1 if count >= 20: print( "[wftel]WARNING: timeout waiting for AUTGO to be RESUMEACK or GUIDE\n\a" ) break time.sleep(1) elapsedTime = time.time() - startTime return elapsedTime
def __init__(self): threading.Thread.__init__(self) self.setDaemon(True) self.apfucam = ktl.Service('apfucam') self.outdir = self.apfucam['OUTDIR'].read() self.checked_list = {} self.signal = True
def gomark(): dcs = ktl.Service('dcs') instrument = dcs.read('INSTRUME') instService = ktl.Service(instrument) raoff = instService['raoffset'] decoff = instService['decoffset'] pattern = instService['pattern'] if pattern == "Stare": print("NOTE: Dither mode is set to Stare, so skipping \n") print(" move to base in gomark script -- exiting\n") return if raoff == 0 and decoff == 0: print("[gomark] NOTE: RA and DEC moves are both zero -- exiting\n") return dcs['raoff'].write(raoff, rel2base='t') dcs['decoff'].write(decoff, rel2base='t') elapsedTime = wftel() log = KeckLogger.getLogger() log.info("[gomark] offset %f in RA, %f in DEC" % (raoff, decoff)) print("[gomark] wftel completed in %f sec" % elapsedTime) return True
def azel(x, y): dcs = ktl.Service('dcs') azoff = dcs['azoff'] eloff = dcs['eloff'] azoff.write(x, rel2curr = t) eloff.write(y, rel2curr = t) time.sleep(3) elapsedTime = wftel() log = KeckLogger.getLogger() log.info("[azel] offset %f arcsec in AZ, %f arcsec in EL" % (x, y)) print("[azel] wftel completed in %f sec" % elapsedTime) return True
def gxy(n, x, y): dcs = ktl.Service('dcs') tvxoff = self.dcs['tvxoff'] tvyoff = self.dcs['tvyoff'] if n == True: print("[gxy] move command (NOT SENT) is: tvxoff.write(%f) tvyoff.write(%f)" % (x, y)) return tvxoff.write(x, rel2curr = 't') tvyoff.write(y, rel2curr = 't') elapsedTime = wftel() log = KeckLogger.getLogger() log.info("[gxy] offset %f, %f in guider coordinates" % (x, y)) print("[gxy] wftel completed in %f sec" % elapsedTime) return True
def en(x, y): if(x == 0.0 and yf == 0.0): print("WARNING: x and y moves are both zero -- exiting\n"") quit() dcs = ktl.Service('dcs') raoff = dcs['raoff'] decoff = dcs['decoff'] raoff.write(x, rel2curr = t) decoff.write(y, rel2curr = t) time.sleep(3) elapsedTime = wftel() log = KeckLogger.getLogger() log.info("[en] offset %f arcsec in RA, %f arcsec in DEC" % (x, y)) print("[en] wftel completed in %f sec" % elapsedTime) return True
def mxy(n, abs, x, y): dcs = ktl.Service('dcs') instxoff = dcs['instxoff'] instyoff = dcs['instyoff'] if n == True: print( "[mxy] move command (NOT SENT) is: instxoff.write(%f) instyoff.write(%f)" % (x, y)) return if abs == True: print('Sending moves rel2base') instxoff.write(x, rel2base='t') instyoff.write(y, rel2base='t') else: instxoff.write(x, rel2curr='t') instyoff.write(y, rel2curr='t') elapsedTime = wftel() log = KeckLogger.getLogger() log.info("[mxy] offest %f, %f, abs = %s in detector coordinates" % (x, y, abs)) print("[mxy] wftel completed in %f sec" % elapsedTime) return
def start(self): '''Start monitoring 'trigger' keyword for new files.''' keys = self.keys # get service instance try: self.service = ktl.Service(self.service_name) except Exception as e: self.log.error(traceback.format_exc()) msg = (f"Could not start KTL monitoring for {self.instr} '{self.service}'. " f"Retry in {KTL_START_RETRY_SEC} seconds.") self.queue_mgr.handle_error('KTL_START_ERROR', msg) threading.Timer(KTL_START_RETRY_SEC, self.start).start() return # monitor keyword that indicates new file kw = self.service[keys['trigger']] kw.callback(self.on_new_file) # Prime callback to ensure it gets called at least once with current val if kw['monitored']: self.on_new_file(kw) else: kw.monitor() # establish heartbeat restart mechanism and service check interval # NOTE: Adding a couple seconds to heartbeat interval in case there # are edge cases to using exact heartbeat frequency hb = self.keys.get('heartbeat') if hb: period = hb[1] + 2 self.service.heartbeat(hb[0], period) threading.Timer(SERVICE_CHECK_SEC, self.check_service).start() self.check_failed = False self.resuscitations = self.service.resuscitations
import time import datetime from subprocess import Popen, PIPE from pathlib import Path import logging import ktl dcs = ktl.Service('dcs') def gxy(x, y): tvxoff = dcs['tvxoff'] tvyoff = dcs['tvyoff'] tvxoff.write(x, rel2curr='t') tvyoff.write(y, rel2curr='t') print("Offset executed") elapsedTime = wftel() log = myLogger() log.info("[gxy] offset %f, %f in guider coordinates" % (x, y)) print("[gxy] wftel completed in %f sec" % elapsedTime) return True def nightpath(): nightly = Path('/s') tel = ktl.read('dcs', 'TELESCOP') if tel == 'Keck I': nightly = nightly / 'nightly1' else: nightly = nightly / 'nightly2'
parser.add_argument("-n", "--nomove", action='store_true', help="don't send moves") parser.add_argument("x1", type=float, help="initial x pixel postion") parser.add_argument("y1", type=float, help="initial y pixel postion") parser.add_argument("x2", type=float, help="final x pixel postion") parser.add_argument("y2", type=float, help="final y pixel postion") args = parser.parse_args() log = KeckLogger.getLogger() dcs = ktl.Service('dcs') instrument = dcs.read('INSTRUME') instService = ktl.Service(instrument) gscale = instService.read('gscale') #NOTE gscale is not unified on instruments: #MOSFIRE: This keyword SHOULD work #KCWI: gscale is currently hardcoded dx = gscale * (args.x1-args.x2) dy = gscale * (args.y2-args.y1) if argos.nomove: print("Required %f in x and %f in y" % (dx, dy)) else: print("Moving %f in x and %f in y" % (dx, dy)) gxy(False, dx, dy)
def __init__(self): self.dcs = ktl.Service('dcs') self.instrument = self.dcs.read('INSTRUME') self.instService = ktl.Service(self.instrument) self.autresum = self.dcs.monitor('autresum')
def getNext(ctime, seeing, slowdown, bstar=False, template=False, sheetns=["RECUR_A100"], owner='public', outfn="googledex.dat", toofn="too.dat", outdir=None, focval=0, inst='', rank_sheetn='rank_table', frac_sheet=None): """ Determine the best target for UCSC team to observe for the given input. Takes the time, seeing, and slowdown factor. Returns a dict with target RA, DEC, Total Exposure time, and scritobs line """ global last_objs_attempted if not outdir: outdir = os.getcwd() dt = computeDatetime(ctime) config = configDefaults(owner) apflog("getNext(): Finding target for time %s" % (dt), echo=True) if slowdown > SLOWDOWN_MAX: apflog( "getNext(): Slowndown value of %f exceeds maximum of %f at time %s" % (slowdown, SLOWDOWN_MAX, dt), echo=True) return None try: apfguide = ktl.Service('apfguide') stamp = apfguide['midptfin'].read(binary=True) ptime = datetime.utcfromtimestamp(stamp) except: if type(dt) == datetime: ptime = dt else: ptime = datetime.utcfromtimestamp(int(time.time())) apflog("getNext(): Updating star list with previous observations", echo=True) observed, star_table = ParseUCOSched.updateLocalStarlist( ptime, outfn=outfn, toofn=toofn, observed_file="observed_targets") hour_table = None if frac_sheet is not None: hour_table = makeHourTable(frac_sheet, dt) hour_table = updateHourTable(hour_table, observed, dt) # Parse the Googledex # Note -- RA and Dec are returned in Radians if star_table is None: apflog("getNext(): Parsing the star list", echo=True) star_table, stars = ParseUCOSched.parseUCOSched(sheetns=sheetns, outfn=outfn, outdir=outdir, config=config) else: stars = ParseUCOSched.genStars(star_table) targNum = len(stars) # List of targets already observed lastfailure = lastAttempted(observed) if lastfailure is not None: last_objs_attempted.append(lastfailure) if len(last_objs_attempted) == 5: apflog("getNext(): 5 failed acquisition attempts", level="warn", echo=True) ### # Need to update the googledex with the lastObserved date for observed targets # Scriptobs line uth utm can be used for this # Need to convert a uth and utm to a JD quickly. # timedelta = now - uth,utm : minus current JD? ### apf_obs = makeAPFObs(dt) # APF latitude in radians apf_lat = (37 + 20 / 60. + 33.1 / 3600.) * np.pi / 180. # Calculate the moon's location moon = ephem.Moon() moon.compute(apf_obs) do_templates = template and templateConditions(moon, seeing, slowdown) apflog("getNext(): Parsed the Googledex...", echo=True) apflog("getNext(): Finding B stars", echo=True) # Note which of these are B-Stars for later. bstars = (star_table['Bstar'] == 'Y') | (star_table['Bstar'] == 'y') # Distance to stay away from the moon totexptimes = np.zeros(targNum, dtype=float) totexptimes = star_table['texp'] * star_table['nexp'] + 40 * ( star_table['nexp'] - 1) available = np.ones(targNum, dtype=bool) cur_elevations = np.zeros(targNum, dtype=float) scaled_elevations = np.zeros(targNum, dtype=float) # Is the target behind the moon? moon_check = behindMoon(moon, star_table['ra'], star_table['dec']) available = available & moon_check if len(last_objs_attempted) > 0: for n in last_objs_attempted: attempted = (star_table['name'] == n) available = available & np.logical_not( attempted) # Available and not observed if bstar: # We just need a B star apflog("getNext(): Selecting B stars", echo=True) available = available & bstars else: apflog("getNext(): Culling B stars", echo=True) available = available & np.logical_not(bstars) # Calculate the exposure time for the target # Want to pass the entire list of targets to this function apflog("getNext(): Computing exposure times", echo=True) exp_counts = star_table['expcount'] # Is the exposure time too long? apflog("getNext(): Removing really long exposures", echo=True) time_check = timeCheck(star_table, totexptimes, dt, hour_table) available = available & time_check if np.any(available) == False: apflog("getNext(): Not enough time left to observe any targets", level="error", echo=True) return None apflog("getNext(): Computing star elevations", echo=True) fstars = [s for s, _ in zip(stars, available) if _] vis, star_elevations, fin_star_elevations, scaled_els = Visible.visible( apf_obs, fstars, totexptimes[available], shiftwest=True) currently_available = available if len(star_elevations) > 0: currently_available[available] = currently_available[available] & vis else: apflog("getNext(): Couldn't find any suitable targets!", level="error", echo=True) return None cur_elevations[available] += star_elevations[vis] scaled_elevations[available] += scaled_els[vis] if slowdown > SLOWDOWN_THRESH or seeing > SEEING_THRESH: bright_enough = star_table['Vmag'] < SLOWDOWN_VMAG_LIM available = available & bright_enough # Now just sort by priority, then cadence. Return top target if len(star_table['name'][available]) < 1: apflog("getNext(): Couldn't find any suitable targets!", level="error", echo=True) return None final_priorities = computePriorities(star_table, dt, rank_table=makeRankTable(rank_sheetn), hour_table=hour_table, observed=observed) try: pri = max(final_priorities[available]) sort_i = (final_priorities == pri) & available except: apflog("getNext(): Couldn't find any suitable targets!", level="error", echo=True) return None if bstar: sort_j = cur_elevations[sort_i].argsort()[::-1] focval = 2 else: sort_j = scaled_elevations[sort_i].argsort()[::-1] allidx, = np.where(sort_i) idx = allidx[sort_j][0] t_n = star_table['name'][idx] o_n = star_table['sheetn'][idx] p_n = final_priorities[idx] apflog("getNext(): selected target %s for program %s at priority %.0f" % (t_n, o_n, p_n)) nmstr = "getNext(): star names %s" % (np.asarray( star_table['name'][sort_i][sort_j])) pristr = "getNext(): star priorities %s" % (np.asarray( final_priorities[sort_i][sort_j])) mxpristr = "getNext(): max priority %d" % (pri) shstr = "getNext(): star sheet names %s" % (np.asarray( star_table['sheetn'][sort_i][sort_j])) if bstar: elstr = "getNext(): Bstar current elevations %s" % ( cur_elevations[sort_i][sort_j]) else: elstr = "getNext(): star scaled elevations %s" % ( scaled_elevations[sort_i][sort_j]) apflog(nmstr, echo=True) apflog(shstr, echo=True) apflog(pristr, echo=True) apflog(mxpristr, echo=True) apflog(elstr, echo=True) stars[idx].compute(apf_obs) res = makeResult(stars, star_table, totexptimes, final_priorities, dt, idx, focval=focval, bstar=bstar, mode=config['mode']) if do_templates and star_table['Template'][idx] == 'N' and star_table[ 'I2'][idx] == 'Y': bidx, bfinidx = findBstars(star_table, idx, bstars) if enoughTimeTemplates(star_table, stars, idx, apf_obs, dt): bline = makeScriptobsLine(star_table[bidx], dt, decker="N", I2="Y", owner=res['owner'], focval=2) line = makeScriptobsLine(star_table[idx], dt, decker="N", I2="N", owner=res['owner'], temp=True) bfinline = makeScriptobsLine(star_table[bfinidx], dt, decker="N", I2="Y", owner=res['owner'], focval=0) res['SCRIPTOBS'] = [] res['SCRIPTOBS'].append(bfinline + " # temp=Y end") res['SCRIPTOBS'].append(line + " # temp=Y") res['SCRIPTOBS'].append(bline + " # temp=Y") res['isTemp'] = True apflog("Attempting template observation of %s" % (star_table['name'][idx]), echo=True) return res
def markbase(): dcs = ktl.Service('dcs') self.dcs['mark'].write('true') log = KeckLogger.getLogger() log.info("[mark] stored offsets RA %f, DEC %f" % (x, y)) return True
from datetime import datetime import ktl import APFTask from apflog import apflog from tharfwhm import tharfwhm import matplotlib matplotlib.use('Agg') import pylab as pl parent = 'focusinstr' apfmot = ktl.Service('apfmot') dewfoc = apfmot['DEWARFOCRAW'] ucam = ktl.Service('apfucam') dewfoc = apfmot['DEWARFOCRAW'] dewfoc.monitor() startfoc = dewfoc.binary numsteps = 21 stepsize = 100 tharexp = 10.0 normfoc = 8200 ucscoff = 305. focuspos = {
def getNext(ctime, seeing, slowdown, bstar=False, template=False, sheetns=["Bstars"], owner='public', outfn="googledex.dat", toofn="too.dat", outdir=None, focval=0): """ Determine the best target for UCSC team to observe for the given input. Takes the time, seeing, and slowdown factor. Returns a dict with target RA, DEC, Total Exposure time, and scritobs line """ if not outdir: outdir = os.getcwd() dt = computeDatetime(ctime) confg = dict() confg['I2'] = 'Y' confg['decker'] = 'W' apflog("getNext(): Finding target for time %s" % (dt), echo=True) if slowdown > SLOWDOWN_MAX: apflog( "getNext(): Slowndown value of %f exceeds maximum of %f at time %s" % (slowdown, SLOWDOWN_MAX, dt), echo=True) return None try: apfguide = ktl.Service('apfguide') stamp = apfguide['midptfin'].read(binary=True) ptime = datetime.utcfromtimestamp(stamp) except: if type(dt) == datetime: ptime = dt else: ptime = datetime.utcfromtimestamp(int(time.time())) observed = ParseGoogledex.updateLocalGoogledex( ptime, googledex_file=os.path.join(outdir, "googledex.dat"), observed_file=os.path.join(outdir, "observed_targets")) # List of targets already observed global last_objs_attempted try: lastline = ktl.read("apftask", "SCRIPTOBS_LINE") if not bstar: # otherwise from previous night lastobj = lastline.split()[0] else: lastobj = None except: lastobj = None if lastobj: if lastobj not in observed and lastobj not in last_objs_attempted: last_objs_attempted.append(lastobj) apflog("getNext(): Last objects attempted %s" % (last_objs_attempted), echo=True) if len(last_objs_attempted) > 5: apflog("getNext(): 5 failed acquisition attempts", echo=True) last_objs_attempted = [] return None else: last_objs_attempted = [] # we had a succes so we are zeroing this out ### # Need to update the googledex with the lastObserved date for observed targets # Scriptobs line uth utm can be used for this # Need to convert a uth and utm to a JD quickly. # timedelta = now - uth,utm : minus current JD? ### apf_obs = makeAPFObs(dt) # APF latitude in radians apf_lat = (37 + 20 / 60. + 33.1 / 3600.) * np.pi / 180. # Calculate the moon's location moon = ephem.Moon() moon.compute(apf_obs) do_templates = template and templateConditions(moon, seeing, slowdown) # Parse the Googledex # Note -- RA and Dec are returned in Radians apflog("getNext(): Parsing the Googledex...", echo=True) config = {'I2': 'Y', 'decker': 'W', 'owner': owner} sn, star_table, flags, stars = ParseGoogledex.parseGoogledex( sheetns=sheetns, outfn=outfn, outdir=outdir, config=config) sn = np.array(sn) deckers = np.array(flags['decker']) targNum = len(sn) apflog("getNext(): Parsed the Googledex...", echo=True) # Note which of these are B-Stars for later. bstars = np.array([True if 'HR' in n else False for n in sn], dtype=bool) apflog("getNext(): Finding B stars", echo=True) # Distance to stay away from the moon md = TARGET_MOON_DIST_MAX - TARGET_MOON_DIST_MIN minMoonDist = ((moon.phase / 100.) * md) + TARGET_MOON_DIST_MIN moonDist = np.degrees( np.sqrt((moon.ra - star_table[:, DS_RA])**2 + (moon.dec - star_table[:, DS_DEC])**2)) available = np.ones(targNum, dtype=bool) totexptimes = np.zeros(targNum, dtype=float) cur_elevations = np.zeros(targNum, dtype=float) scaled_elevations = np.zeros(targNum, dtype=float) i2cnts = np.zeros(targNum, dtype=float) # Is the target behind the moon? apflog("getNext(): Culling stars behind the moon", echo=True) moon_check = moonDist > minMoonDist available = available & moon_check # totobs_check = (star_table[:,DS_NOB] < star_table[:,DS_TOT]) | (star_table[:,DS_TOT] <= 0) # available = available & totobs_check # We just need a B star, so restrict our math to those if bstar: apflog("getNext(): Selecting B stars", echo=True) available = available & bstars f = available apflog("getNext(): Computing star elevations", echo=True) fstars = [s for s, _ in zip(stars, f) if _] vis, star_elevations, fin_star_elevations = Visible.is_visible( apf_obs, fstars, [400] * len(bstars[f])) available[f] = available[f] & vis cur_elevations[np.where(f)] += star_elevations[np.where(vis)] star_table[available, DS_COUNTS] = 2e9 star_table[available, DS_EXPT] = 900 star_table[available, DS_NSHOTS] = 2 totexptimes[available] = 400 # Just need a normal star for observing else: # Available and not a BStar apflog("getNext(): Culling B stars", echo=True) available = np.logical_and(available, np.logical_not(bstars)) # has the star been observed - commented out as redundant with cadence if len(last_objs_attempted) > 0: for n in last_objs_attempted: attempted = (sn == n) available = available & np.logical_not( attempted) # Available and not observed # Calculate the exposure time for the target # Want to pass the entire list of targets to this function f = available apflog("getNext(): Computing star elevations", echo=True) fstars = [s for s, _ in zip(stars, f) if _] vis, star_elevations, fin_star_elevations, scaled_els = Visible.is_visible_se( apf_obs, fstars, [0] * len(fstars)) # vis,star_elevations,fin_star_elevations = Visible.is_visible( apf_obs,fstars,[0]*len(fstars)) available[f] = available[f] & vis f = available fstars = [s for s, _ in zip(stars, f) if _] apflog("getNext(): Computing exposure times", echo=True) exp_times, exp_counts, i2counts = calculateUCSCExposureTime( star_table[f,DS_VMAG], \ star_table[f,DS_I2CNTS], star_elevations[np.array(vis)], seeing, \ star_table[f,DS_BV], deckers[f]) exp_times = exp_times * slowdown totexptimes[f] += computeMaxTimes(exp_times, star_table[f, DS_MAX]) i2cnts[f] += i2counts apflog("getNext(): Formating exposure times", echo=True) mxtime = np.zeros_like(star_table[f, DS_MAX]) mxtime += MAX_EXPTIME shorter = (star_table[f, DS_MAX] < MAX_EXPTIME) & (star_table[f, DS_MAX] > 0) mxtime[shorter] = star_table[f, DS_MAX][shorter] star_table[f, DS_EXPT], exps = format_time(totexptimes[f], i2counts, star_table[f, DS_NSHOTS], star_table[f, DS_MIN], mxtime) apflog("getNext(): Formating exposure meter", echo=True) star_table[f, DS_COUNTS], star_table[f, DS_NSHOTS] = format_expmeter( exp_counts, exps, totexptimes[f]) # Is the exposure time too long? apflog("getNext(): Removing really long exposures", echo=True) time_check = np.where(exp_times < TARGET_EXPOSURE_TIME_MAX, True, False) available[f] = available[f] & time_check f = available # Is the star currently visible? apflog("getNext(): Computing stars visibility", echo=True) fstars = [s for s, _ in zip(stars, f) if _] vis, star_elevations, fin_star_elevations, scaled_els = Visible.is_visible_se( apf_obs, fstars, exp_times) if vis != []: available[f] = available[f] & vis cur_elevations[np.where(f)] += star_elevations[np.where(vis)] scaled_elevations[np.where(f)] += scaled_els[np.where(vis)] # Now just sort by priority, then cadence. Return top target if len(sn[available]) < 1: apflog("getNext(): Couldn't find any suitable targets!", level="error", echo=True) return None final_priorities = computePriorities(star_table, available, dt, flags) cadence_check = (ephem.julian_date(dt) - star_table[:, DS_LAST]) / star_table[:, DS_CAD] good_cadence = np.where(cadence_check > 1.0, True, False) good_cadence_available = available & good_cadence if any(good_cadence_available): try: pri = max(final_priorities[good_cadence_available]) sort_i = (final_priorities == pri) & good_cadence_available except: pri = max(final_priorities[available]) sort_i = (final_priorities == pri) & available elif any(available): apflog( "getNext(): No new stars available, going back to the previously observed list.", level="warn", echo=True) pri = max(final_priorities[available]) sort_i = (final_priorities == pri) & available else: apflog("getNext(): Couldn't find any suitable targets!", level="error", echo=True) return None starstr = "getNext(): star table available: %s" % (sn[sort_i]) apflog(starstr, echo=True) starstr = "getNext(): star table available priorities: %s" % ( final_priorities[sort_i]) apflog(starstr, echo=True) if bstar: sort_j = cur_elevations[sort_i].argsort()[::-1] focval = 2 else: sort_j = scaled_elevations[sort_i].argsort()[::-1] cstr = "getNext(): cadence check: %s" % ( cadence_check[sort_i][sort_j][0]) apflog(cstr, echo=True) t_n = sn[sort_i][sort_j][0] elstr = "getNext(): star elevations %s" % (cur_elevations[sort_i][sort_j]) apflog(elstr, echo=True) t_n = sn[sort_i][sort_j][0] apflog("getNext(): selected target %s" % (t_n)) idx, = np.where(sn == t_n) idx = idx[0] stars[idx].compute(apf_obs) cstr = "getNext(): cadence check: %f (%f %f %f)" % ( ((ephem.julian_date(dt) - star_table[idx, DS_LAST]) / star_table[idx, DS_CAD]), ephem.julian_date(dt), star_table[idx, DS_LAST], star_table[idx, DS_CAD]) apflog(cstr, echo=True) res = makeResult(stars, star_table, flags, totexptimes, i2cnts, sn, dt, idx, focval=focval) if do_templates and flags['template'][idx] == 'N' and flags['I2'][ idx] == 'Y': bname, brow, bnamefin, browfin = findBstars(sn, star_table, idx, bstars) row = makeTempRow(star_table, idx) if enoughTime(star_table, stars, idx, row, apf_obs, dt): bline = makeScriptobsLine(bname, brow, '', dt, decker="N", I2="Y", owner='public', focval=2) line = makeScriptobsLine(sn[idx], row, flags['do'][idx], dt, decker="N", I2="N", owner=flags['owner'][idx]) bfinline = makeScriptobsLine(bnamefin, browfin, '', dt, decker="N", I2="Y", owner=flags['owner'][idx], focval=2) res['SCRIPTOBS'] = [] res['SCRIPTOBS'].append(bfinline + " # temp=Y end") res['SCRIPTOBS'].append(line + " # temp=Y") res['SCRIPTOBS'].append(bline + " # temp=Y") res['isTemp'] = True apflog("Attempting template observation of %s" % (sn[idx]), echo=True) return res
def __init__(self, apf, opt, totTemps=4, task='master'): threading.Thread.__init__(self) self.setDaemon(True) self.apf = apf self.task = task if opt.name: self.user = opt.name else: self.user = '******' if opt.owner: self.owner = opt.owner else: self.owner = 'public' if opt.windshield: self.windshield_mode = opt.windshield else: self.windshield_mode = 'auto' self.name = 'Observe' self.signal = True self.scriptobs = None self.BV = None self.VMAG = None self.blank = False self.decker = "W" self.obsBstar = True self.lastObsSuccess = True self.lastObsFinished = True self.BstarFailures = 0 if opt.fixed: self.fixedList = opt.fixed else: self.fixedList = None if opt.sheet: self.sheetn = opt.sheet else: self.sheetn = 'RECUR_A100' if opt.rank_table: self.rank_tablen = opt.rank_table else: self.rank_tablen = None if opt.frac_table: self.frac_tablen = opt.frac_table else: self.frac_tablen = None if opt.start: try: self.starttime = float(opt.start) except ValueError as e: apflog("ValueError: %s" % (e), echo=True, level='error') self.starttime = None else: self.starttime = None if opt.raster: self.raster = opt.raster else: self.raster = False if opt.test: self.debug = opt.test else: self.debug = False self.doTemp = True self.nTemps = 0 self.focval = 0 self.totTemps = totTemps self.target = None self.fixedtarget = None self.apftask = ktl.Service('apftask') self.lineresult = self.apftask['SCRIPTOBS_LINE_RESULT'] self.lineresult.monitor() self.observed = self.apftask['SCRIPTOBS_OBSERVED'] self.observed.monitor() self.canOpen = True self.badWeather = False
def getNext(time, seeing, slowdown, star_dates, bstar=False, standardstar=False, verbose=False, sheetn="FakeGoogledex", owner='Vogt', googledex_file="./newgoogledex.csv", method="inquad", observed_file="observed_targets"): """ Determine the best target for UCSC team to observe for the given input. Takes the time, seeing, and slowdown factor. Returns a dict with target RA, DEC, Total Exposure time, and scritobs line """ # Convert the unix timestamp into a python datetime if type(time) == float: dt = datetime.utcfromtimestamp(int(time)) elif type(time) == datetime: dt = time elif type(time) == ephem.Date: dt = time.datetime() else: dt = datetime.utcnow() # punt confg = dict() confg['I2'] = 'Y' confg['decker'] = 'W' if verbose: apflog("getNext(): Finding target for time %s" % (dt), echo=True) if slowdown > SLOWDOWN_MAX: apflog( "getNext(): Slowndown value of %f exceeds maximum of %f at time %s" % (slowdown, SLOWDOWN_MAX, dt), echo=True) return None try: apfguide = ktl.Service('apfguide') stamp = apfguide['midptfin'].read(binary=True) ptime = datetime.fromtimestamp(stamp) except: if type(dt) == datetime: ptime = dt else: ptime = datetime.utcnow() # List of targets already observed observed, obstimes = update_local_googledex(ptime, googledex_file=googledex_file, observed_file=observed_file) global last_objs_attempted try: lastline = ktl.read("apftask", "SCRIPTOBS_LINE") if not bstar: # otherwise from previous night lastobj = lastline.split()[0] if verbose: apflog("getNext(): Last object attempted %s" % (lastobj), echo=True) except: lastobj = None if lastobj: if lastobj not in observed and lastobj not in last_objs_attempted: last_objs_attempted.append(lastobj) if verbose: apflog("getNext(): Last objects attempted %s" % (last_objs_attempted), echo=True) if len(last_objs_attempted) > 5: apflog("getNext(): 5 failed acquisition attempts", echo=True) last_objs_attempted = [] return None ### # Need to update the googledex with the lastObserved date for observed targets # Scriptobs line uth utm can be used for this # Need to convert a uth and utm to a JD quickly. # timedelta = now - uth,utm : minus current JD? ### # Generate a pyephem observer for the APF apf_obs = ephem.Observer() apf_obs.lat = '37:20:33.1' apf_obs.long = '-121:38:17.7' apf_obs.elevation = 1274 # Minimum observation to observe things at apf_obs.horizon = str(TARGET_ELEVATION_MIN) apf_obs.date = dt # APF latitude in radians apf_lat = (37 + 20 / 60. + 33.1 / 3600.) * np.pi / 180. # Calculate the moon's location moon = ephem.Moon() moon.compute(apf_obs) # Parse the Googledex # Note -- RA and Dec are returned in Radians if verbose: apflog("getNext(): Parsing the Googledex...", echo=True) sn, star_table, do_flag, stars = parseGoogledex(sheetn=sheetn, outfn=googledex_file) star_table['apfpri'], star_table['phases'] = getpriority.getpriority( star_table['starname'], star_table, ephem.julian_date(dt), star_dates, apf_obs.sidereal_time(), method=method, standard=standardstar) targNum = len(sn) if verbose: apflog("getNext(): Parsed the Googledex...", echo=True) # Note which of these are B-Stars for later. bstars = star_table['comments'] == 'B star' if verbose: apflog("getNext(): Finding B stars", echo=True) available = np.ones(targNum, dtype=bool) totexptimes = np.zeros(targNum, dtype=float) cur_elevations = np.zeros(targNum, dtype=float) i2cnts = np.zeros(targNum, dtype=float) star_table['counts'] = np.zeros(targNum, dtype=float) star_table['expt'] = np.zeros(targNum, dtype=float) star_table['nshots'] = np.zeros(targNum, dtype=int) # Is the target behind the moon? # Distance to stay away from the moon md = TARGET_MOON_DIST_MAX - TARGET_MOON_DIST_MIN minMoonDist = ((moon.phase / 100.) * md) + TARGET_MOON_DIST_MIN moonDist = np.degrees( np.sqrt((moon.ra - star_table['ra'])**2 + (moon.dec - star_table['dec'])**2)) if verbose: apflog("getNext(): Culling stars behind the moon", echo=True) moon_check = np.where(moonDist > minMoonDist, True, False) available = available & moon_check # We just need a B star, so restrict our math to those if bstar: if verbose: apflog("getNext(): Selecting B stars", echo=True) available = available & bstars f = available if verbose: apflog("getNext(): Computing star elevations", echo=True) fstars = [s for s, _ in zip(stars, f) if _] vis, star_elevations, fin_star_elevations = is_visible( fstars, apf_obs, [400] * len(bstars[f]), TARGET_ELEVATION_MIN, TARGET_ELEVATION_PREF_MIN, TARGET_ELEVATION_MAX) available[f] = available[f] & vis cur_elevations[np.where(f)] += star_elevations[np.where(vis)] star_table['counts'][available] = 1e9 star_table['expt'][available] = 900 star_table['nshots'][available] = 2 totexptimes[available] = 400 # Just need a normal star for observing else: # Available and not a BStar if verbose: apflog("getNext(): Culling B stars", echo=True) available = np.logical_and(available, np.logical_not(bstars)) if len(last_objs_attempted) > 0: for n in last_objs_attempted: attempted = (sn == n) available = available & np.logical_not( attempted) # Available and not observed # Calculate the exposure time for the target # Want to pass the entire list of targets to this function f = available if verbose: apflog("getNext(): Computing star elevations", echo=True) fstars = [s for s, _ in zip(stars, f) if _] # star_elevations=calc_elevations(fstars,apf_obs) vis, star_elevations, fin_star_elevations = is_visible( fstars, apf_obs, [0] * len(fstars), TARGET_ELEVATION_MIN, TARGET_ELEVATION_PREF_MIN, TARGET_ELEVATION_MAX) available[f] = available[f] & vis f = available fstars = [s for s, _ in zip(stars, f) if _] if verbose: apflog("getNext(): Computing exposure times", echo=True) exp_times, exp_counts, i2counts = calculate_ucsc_exposure_time( star_table['vmag'][f], star_table['precision'][f], star_elevations[np.array(vis)], seeing, star_table['b-v'][f]) exp_times = exp_times * slowdown maxtimes = computeMaxTimes(sn[f], exp_times) totexptimes[f] += exp_times i2cnts[f] += i2counts if verbose: apflog("getNext(): Formating exposure times", echo=True) star_table['expt'][f], star_table['nshots'][f] = format_time( exp_times, i2counts) # exp_counts /= star_table[f, DS_NSHOTS] if verbose: apflog("getNext(): Formating exposure meter", echo=True) star_table['counts'][f], star_table['nshots'][f] = format_expmeter( exp_counts, star_table['nshots'][f]) # Is the exposure time too long? if verbose: apflog("getNext(): Removing really long exposures", echo=True) time_check = np.where(exp_times < maxtimes, True, False) available[f] = available[f] & time_check f = available # Is the star currently visible? if verbose: apflog("getNext(): Computing stars visibility", echo=True) fstars = [s for s, _ in zip(stars, f) if _] vis, star_elevations, fin_star_elevations = is_visible( fstars, apf_obs, exp_times, TARGET_ELEVATION_MIN, TARGET_ELEVATION_PREF_MIN, TARGET_ELEVATION_MAX) if vis != []: available[f] = available[f] & vis cur_elevations[np.where(f)] += star_elevations[np.where(vis)] # Now just sort by priority, then cadence. Return top target if len(sn[available]) < 1: apflog("getNext(): Couldn't find any suitable targets!", level="error", echo=True) return None cadence_check = (ephem.julian_date(dt) - star_table['lastobs']) / star_table['cadence'] good_cadence = np.where(cadence_check > 1.0, True, False) good_cadence_available = available & good_cadence if any(good_cadence_available): try: pri = max(star_table['apfpri'][good_cadence_available]) sort_i = np.where( star_table['apfpri'][good_cadence_available] == pri, True, False) available = good_cadence_available except: pri = max(star_table['apfpri'][available]) sort_i = np.where(star_table['apfpri'][available] == pri, True, False) elif any(available): apflog( "getNext(): No new stars available, going back to the previously observed list.", level="warn", echo=True) pri = max(star_table['apfpri'][available]) sort_i = np.where(star_table['apfpri'][available] == pri, True, False) else: apflog("getNext(): Couldn't find any suitable targets!", level="error", echo=True) return None starstr = "getNext(): star table available: %s" % (sn[available][sort_i]) apflog(starstr, echo=True) sort_j = cur_elevations[available][sort_i].argsort()[::-1] t_n = sn[available][sort_i][sort_j][0] elstr = "getNext(): star elevations %s" % ( cur_elevations[available][sort_i][sort_j]) apflog(elstr, echo=True) t_n = sn[available][sort_i][sort_j][0] apflog("getNext(): selected target %s" % (t_n)) idx, = np.where(sn == t_n) idx = idx[0] stars[idx].compute(apf_obs) res = dict() res['RA'] = stars[idx].a_ra res['DEC'] = stars[idx].a_dec res['PM_RA'] = 0.0 res['PM_DEC'] = 0.0 res['VMAG'] = star_table['vmag'][idx] res['BV'] = star_table['b-v'][idx] res['COUNTS'] = star_table['counts'][idx] res['EXP_TIME'] = star_table['expt'][idx] res['NEXP'] = star_table['nshots'][idx] res['TOTEXP_TIME'] = totexptimes[idx] res['I2CNTS'] = i2cnts[idx] res['NAME'] = sn[idx] res['SCORE'] = star_table['apfpri'][idx] res['PRI'] = star_table['apfpri'][idx] res['SCRIPTOBS'] = makeScriptobsLine(res, do_flag[idx], dt, decker=confg['decker'], I2=confg['I2'], owner=owner) return res