def instr_permit(): instr_perm = ktl.read("checkapf","INSTR_PERM",binary=True) userkind = ktl.read("checkapf","USERKIND",binary=True) while not instr_perm or userkind != 3: apflog("Waiting for instrument permission to be true and userkind to be robotic") APFTask.waitfor(parent,True,expression="$checkapf.INSTR_PERM = true",timeout=600) APFTask.waitfor(parent,True,expression="$checkapf.USERKIND = robotic",timeout=600) instr_perm = ktl.read("checkapf","INSTR_PERM",binary=True) userkind = ktl.read("checkapf","USERKIND",binary=True) return True
def getScales(instrument, scale): scale_dict = {'mosfire': {'pscale': ktl.read(instrument, 'pscale'), 'gscale': ktl.read(instrument, 'gscale')}, 'lris': {'pscaler': 0.134, 'pscaleb': 0.135, 'gscale': 0.239}, 'hires': {'pscale': 0.12, 'gscale': 0.086}, 'osiris': {'pscale': ktl.read(instrument, 'pscale'), 'sscale': ktl.read(instrument, 'sscale'), 'gscale': 0.1338}, 'kcwi': {'pscale': 0.0076, 'gscale': 0.184}, 'nirc2': {'pscale': 0.009942, 'gscale': 0.134}, 'nirspec': {'pscale': 0.1185, 'gscale': 0.207}, 'esi': {'pscale': 0.153, 'gscale': 0.233}, 'deimos': {'pscale': 0.1185, 'gscale': 0.207}, 'nires': {'pscale': 0.123, 'gscale': 0.244} } return scale_dict[instrument][scale]
def calibrate(self, script, time): s_calibrate = os.path.join(ScriptDir,"calibrate") if self.test: print "Test Mode: calibrate %s %s." % (script, time) APFTask.waitFor(self.task, True, timeout=10) return True if time == 'pre' or 'post': try: APFLib.write("apfmot.DEWARFOCRAW",ktl.read("apftask","FOCUSINSTR_LASTFOCUS",binary=True)) except: apflog("Cannot read the last best fitting focus value or write the dewar focus value", level='error') if self.dewarfoc > 8600 or self.dewarfoc < 8400: apflog("Warning: The dewar focus is currently %d. This is outside the typical range of acceptable values." % (self.dewarfoc), level = "error", echo=True) return False apflog("Running calibrate %s %s" % (script, time), level = 'info') owner = self.apfschedule('OWNRHINT').read() self.apfschedule('OWNRHINT').write('public') cmd = '%s %s %s' % (s_calibrate,script, time) result, code = cmdexec(cmd,debug=True,cwd=os.getcwd()) if not result: apflog("%s %s failed with return code %d" % (s_calibrate, script, code),echo=True) expression="($apftask.CALIBRATE_STATUS != 0) and ($apftask.CALIBRATE_STATUS != 1) " if not APFTask.waitFor(self.task,True,expression=expression,timeout=30): apflog("%s %s failed to exit" % (s_calibrate,script),echo=True) self.apfschedule('OWNRHINT').write(owner) return result else: print "Couldn't understand argument %s, nothing was done." % time
def getTarget(): APFLib.write(self.apf.ucam["RECORD"], "Yes") # safe / sorry if self.apf.nerase != 2: self.apf.nerase.write(2, binary=True) if self.checkObsFinished(): apflog( "getTarget(): Scriptobs phase is input, determining next target.", echo=True) else: apflog("getTarget(): Not at end of block but out of targets.", echo=True) try: self.obsBstar = ktl.read("apftask", "MASTER_OBSBSTAR", binary=True) apflog("getTarget(): Setting obsBstar to %s" % (str(self.obsBstar)), echo=True) except Exception, e: apflog("getTarget(): Cannot read apftask.MASTER_OBSBSTAR: %s" % (e), level='error', echo=True) self.obsBstar = True
def openat(self, sunset=False): """Function to ready the APF for observing. Calls either openatsunset or openatnight. This function will attempt to open successfully twice. If both attempts fail, then it will return false, allowing the master to register the error and behave accodingly. Otherwise it will return True. """ # If this is a test run, just return True if self.test: return True if not self.ok2open: # This should really never happen. In case of a temporary condition, we give # a short waitfor rather than immediatly exiting. chk_open = "$checkapf.OPEN_OK == true" result = APFLib.waitFor(self.task, False, chk_open, timeout=30) if not result: apflog("Tried calling openat with OPEN_OK = False. Can't open.", echo=True) apflog(self.checkapf["OPREASON"].read(), echo=True) return False if float(self.sunel) > SUNEL_HOR: apflog("Sun is still up. Current sunel = %4.2f. Can't open." % self.sunel, echo=True) return False if self.mv_perm.binary == False: apflog("Waiting for permission to move...", echo=True) chk_move = "$checkapf.MOVE_PERM == true" result = APFTask.waitFor(self.task, False, chk_move, timeout=600) if not result: apflog("Can't open. No move permission.",echo=True) return False if self.states_set(): apflog("An unusal emergency state is set.", level="error",echo=True) return False # Everything seems acceptable, so lets try opening if sunset: cmd = '/usr/local/lick/bin/robot/openatsunset' else: cmd = '/usr/local/lick/bin/robot/openatnight' # Make two tries at opening. If they both fail return False so the caller can act # accordingly. result, code = cmdexec(cmd) if not result: apflog("First openup attempt has failed. Exit code = %d. After a pause, will make one more attempt." % code,echo=True) APFTask.waitFor(self.task, True, timeout=10) result, code = cmdexec(cmd) if not result: apflog("Second openup attempt also failed. Exit code %d. Giving up." % code,echo=True) return False rv = self.checkhome() if rv == False: return False try: APFLib.write("eostele.FOCUS",ktl.read("apftask","FOCUSTEL_LASTFOCUS",binary=True)) except: apflog("Cannot move secondary focus.",level="error") return False return True
def findUCSCObsNum(): last = int(ktl.read('apftask', 'MASTER_LAST_OBS_UCSC', binary=True)) last += 100 - (last % 100) if last % 10000 > 9700: last += 10000 - (last % 10000) return last
def readem_or_weep(service, keyword, binary=False): try: value = ktl.read(service, keyword, binary=binary) except: apflog.apflog("cannot read %s.%s" % (service, keyword), echo=True, level='error') sys.exit("cannot read %s.%s" % (service, keyword)) return value
def nightpath(): nightly = Path('/s') tel = ktl.read('dcs', 'TELESCOP') if tel == 'Keck I': nightly = nightly / 'nightly1' else: nightly = nightly / 'nightly2' date = datetime.datetime.utcnow() year, month, day = str(date.strftime("%y")), str(date.strftime("%m")), str( date.strftime("%d")) nightly = nightly / year / month / day return nightly
def read_config(configfile, runstr): srun = primary_run(runstr) config = ConfigParser.ConfigParser() if not os.path.exists(configfile): apflog.apflog("configuration file %s does not exist" % configfile) sys.exit("configuration file %s does not exist" % configfile) config.read(configfile) programs = remap_config(config.items('programs')) program = programs[srun] program_config = remap_config(config.items(program)) last = int(ktl.read('apftask', 'MASTER_LAST_OBS_UCSC', binary=True)) if program_config['obsnum'] == "ucsc": program_config['obsnum'] = findUCSCObsNum(last) if program_config['obsnum'] == "apf": program_config['obsnum'] = findAPFObsNum(last) if program_config['name'] == "ucb": lastcode = ktl.read('apftask', 'MASTER_LAST_OBS_UCB') program_config['name'] = findUCBObsNum(lastcode) if program_config['name'] == "apf": program_config['name'] = findAPFObsName() return program_config
def lastAttempted(observed): failed_obs = None try: lastresult = ktl.read("apftask", "SCRIPTOBS_LINE") lastobj = lastresult.split()[0] except: return None if lastobj not in observed.names: apflog("lastAttempted(): Last objects attempted %s" % (lastobj), echo=True) failed_obs = lastobj return failed_obs
def checkBstar(self, haveobserved): """ Observe.obsBstar(haveobserved) if observing has begun, and the last observation was a success, set Observe.obsBstar to false, writes master_obsbstar to the current value of obsBstar The variable OBSBSTAR still overrides """ self.obsBstar = ktl.read('apftask', 'MASTER_OBSBSTAR', binary=True) if haveobserved and self.lastObsSuccess: self.obsBstar = False try: ktl.write('apftask', 'MASTER_OBSBSTAR', self.obsBstar, binary=True) except Exception, e: apflog("Error: Cannot communicate with apftask: %s" % (e), level="error") self.BstarFailures = 0
def startRobot(self): """Start an instance of scriptobs. Returns the result from subprocess.Popen().""" # For running in test mode if self.test: apflog("Would be taking observation in starlist %s" % observation) APFTask.waitFor(self.task, True, timeout=300) return # Make sure the telescope autofocus is enabled APFLib.write(self.autofoc, "robot_autofocus_enable") chk_foc = '$apftask.SCRIPTOBS_AUTOFOC == robot_autofocus_enable' result = APFTask.waitFor(self.task, False, chk_foc, timeout=60) if not result: apflog("Error setting scriptobs_autofoc", echo=True) return # Make sure APFTEQ is in night mode for observations if self.teqmode.read() != 'Night': self.setTeqMode('Night') # Check the instrument focus for a reasonable value if self.dewarfoc > DEWARMAX or self.dewarfoc < DEWARMIN: lastfit_dewarfoc = ktl.read("apftask","FOCUSINSTR_LASTFOCUS",binary=True) apflog("Warning: The dewar focus is currently %d. This is outside the typical range of acceptable values. Resetting to last derived value %d" % (self.dewarfoc,lastfit_dewarfoc), level = "error", echo=True) APFLib.write("apfmot.DEWARFOCRAW",lastfit_dewarfoc) robotdir = "/usr/local/lick/bin/robot/" telstate = tel['TELSTATE'].read() if telstate == 'Disabled': rv, retc = cmdexec(os.path.join(robotdir,"slew --hold")) if not rv: return rv rv, retc = cmdexec(os.path.join(robotdir,"prep-obs")) if not rv: return rv # Start scriptobs outfile = open("robot.log", 'a') args = ['/usr/local/lick/bin/robot/scriptobs', '-dir', os.getcwd()] p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=outfile, stderr=outfile) return p
def observe(self, observation,skip=False): """ Currently: Takes a string which is the filename of a properly formatted star list. """ if self.test: apflog("Would be taking observation in starlist %s" % observation) APFTask.waitFor(self.task, True, timeout=300) return # Make sure the telescope autofocus is enabled APFLib.write(self.autofoc, "robot_autofocus_enable") APFLib.write(self.ucam["RECORD"], "Yes") chk_foc = '$apftask.SCRIPTOBS_AUTOFOC == robot_autofocus_enable' result = APFTask.waitFor(self.task, False, chk_foc, timeout=60) if not result: apflog("Error setting scriptobs_autofoc", echo=True) return # Make sure APFTEQ is in night mode for observations if self.teqmode.read() != 'Night': self.setTeqMode('Night') # Check the instrument focus for a reasonable value if self.dewarfoc > 8600 or self.dewarfoc < 8400: lastfit_dewarfoc = ktl.read("apftask","FOCUSINSTR_LASTFOCUS",binary=True) apflog("Error: The dewar focus is currently %d. This is outside the typical range of acceptable values. Resetting to last derived value %d" % (self.dewarfoc,lastfit_dewarfoc), level = "error", echo=True) APFLib.write("apfmot.DEWARFOCRAW",lastfit_dewarfoc) # Check Telescope M2 Focus robotdir = "/usr/local/lick/bin/robot/" infile = open(observation,'r') outfile = open("robot.log", 'a') if skip: args = ['/usr/local/lick/bin/robot/scriptobs', '-dir', os.getcwd(),'-skip'] else: args = ['/usr/local/lick/bin/robot/scriptobs', '-dir', os.getcwd()] p = subprocess.Popen(args,stdin=infile, stdout=outfile,stderr = subprocess.PIPE, cwd=robotdir)
def getNext(ctime, seeing, slowdown, bstar=False, verbose=False,template=False,sheetns=["Bstars"],owner='public',outfn="googledex.dat",outdir=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 """ if not outdir: outdir = os.getcwd() # Convert the unix timestamp into a python datetime if type(ctime) == float: dt = datetime.utcfromtimestamp(int(ctime)) elif type(ctime) == datetime: dt = ctime elif type(ctime) == ephem.Date: dt = ctime.datetime() else: dt = datetime.utcfromtimestamp(int(time.time())) # 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.utcfromtimestamp(stamp) except: if type(dt) == datetime: ptime = dt else: ptime = datetime.utcfromtimestamp(int(time.time())) observed, obstimes = ParseGoogledex.update_local_googledex(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] 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) 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) if verbose: 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) if verbose: 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? if verbose: 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: 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 = 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] = 1e9 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 if verbose: 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 if verbose: 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 _ ] if verbose: apflog("getNext(): Computing exposure times",echo=True) exp_times, exp_counts, i2counts = calculate_ucsc_exposure_time( star_table[f,DS_VMAG], \ star_table[f,DS_ERR], 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 if verbose: 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) if verbose: 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? if verbose: 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? if verbose: 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 = compute_priorities(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] 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 = dict() res['RA'] = stars[idx].a_ra res['DEC'] = stars[idx].a_dec res['PM_RA'] = star_table[idx, DS_PMRA] res['PM_DEC'] = star_table[idx, DS_PMDEC] res['VMAG'] = star_table[idx, DS_VMAG] res['BV'] = star_table[idx, DS_BV] res['COUNTS'] = star_table[idx, DS_COUNTS] res['EXP_TIME'] = star_table[idx, DS_EXPT] res['NEXP'] = star_table[idx, DS_NSHOTS] res['TOTEXP_TIME'] = totexptimes[idx] res['I2CNTS'] = i2cnts[idx] res['NAME'] = sn[idx] res['SCORE'] = star_table[idx,DS_NSHOTS] res['PRI'] = star_table[idx, DS_APFPRI] res['DECKER'] = flags['decker'][idx] res['I2'] = flags['I2'][idx] res['owner'] = flags['owner'][idx] res['SCRIPTOBS'] = makeScriptobsLine(sn[idx], star_table[idx,:], flags['do'][idx], dt, decker=flags['decker'][idx], I2=flags['I2'][idx], owner=flags['owner'][idx]) return res
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
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 getTarget(): apflog("getTarget(): Scriptobs phase is input, determining next target.",echo=True) APFLib.write(APF.ucam["RECORD"], "Yes") # safe / sorry try: self.obsBstar = bool(ktl.read("apftask","master_var_3")) except: self.obsBstar = True if self.scriptobs is None: apflog("Called getTarget, but there is not instance of scriptobs associated with Heimdallr. This is an error condition.", echo=True) return None # Calculate the slowdown factor. if self.BV is None: apflog("Warning!: Ended up in getTarget() with no B Magnitude value, slowdown can't be computed.", echo=True) self.BV = 0.6 # use a default average if self.VMAG is None: apflog("Warning!: Ended up in getTarget() with no V Magnitude value, slowdown can't be computed.", echo=True) slowdown = 5 elif APF.avg_fwhm < 1.0: apflog("Warning!: AVG_FWHM = %4.2f. By Odin's beard that seems low." % APF.avg_fwhm, echo=True) slowdown = 5 else: apflog("Calculating expected counts") apflog("self.VMAG [%4.2f] - self.BV [%4.2f] - APF.ael [%4.2f]" % (self.VMAG, self.BV, APF.ael)) exp_cnts_sec = ExposureCalculations.getEXPMeter_Rate(self.VMAG, self.BV, APF.ael,APF.avg_fwhm, self.decker) try: if APF.countrate <= 0: try: APF.countrate = APF.ccountrate except: APF.countrate = -1.0 slowdown = exp_cnts_sec / APF.countrate if APF.countrate*10 < APF.ccountrate: APF.countrate = APF.ccountrate if slowdown < 0: slowdown = 1 apflog("Countrate non-sensical %g" % (APF.countrate), echo=True, level='warn') APF.counts.monitor(start=False) APF.counts.monitor(start=True) APF.counts.callback(ad.countmon) # yes this happened. if slowdown < SchedulerConsts.SLOWDOWN_MIN: slowdown = SchedulerConsts.SLOWDOWN_MIN apflog("slowdown too low, countrate= %g" % (APF.countrate), echo=True, level='debug') # yes this happened. if slowdown > SchedulerConsts.SLOWDOWN_MAX: slowdown = SchedulerConsts.SLOWDOWN_MAX apflog("slowdown too high, countrate= %g" % (APF.countrate), echo=True, level='debug') except ZeroDivisionError: apflog("Current countrate was 0. Slowdown will be set to 1.", echo=True) slowdown = 1 apflog("getTarget(): slowdown factor = %4.2f" % slowdown, echo=True) APFLib.write(apf.robot["MASTER_VAR_1"], slowdown) apflog("getTarget(): countrate = %.2f, ccountrate = %.2f" % (APF.countrate,APF.ccountrate)) # Check for a valid seeing measurment. If there isn't one, use a default if APF.avg_fwhm == 0.: apflog("getTarget(): Warning AVG_FWHM is 0. A default value of 15 will be used in its place.",echo=True) seeing = 15 else: seeing = float(APF.avg_fwhm) apflog("getTarget(): Current AVG_FWHM = %4.2f" % seeing) target = ds.getNext(time.time(), seeing, slowdown, bstar=self.obsBstar, verbose=True, sheetns=self.sheetn, owner=self.owner) self.set_autofocval() if target is None: apflog("No acceptable target was found. Since there does not seem to be anything to observe, Heimdallr will now shut down.", echo=True) # Send scriptobs EOF to finish execution - wouldn't want to leave a zombie scriptobs running self.scriptobs.stdin.close() APF.close() apf.countrate = -1.0 # sleep for a half hour to see if the clouds blow by APFTask.waitfor(self.task, True, timeout=60*45) return else: apflog("Observing target: %s" % target['NAME'], echo=True) self.scriptobs.stdin.write(target["SCRIPTOBS"] + '\n') # Set the Vmag and B-V mag of the latest target self.VMAG = target["VMAG"] self.BV = target["BV"] self.decker = target["DECKER"] apflog("getTarget(): V=%.2f B-V=%.2f Pri=%.2f " % (self.VMAG, self.BV, target["PRI"])) apflog("getTarget(): FWHM=%.2f Slowdown=%.2f Countrate=%.2f" % (APF.avg_fwhm, slowdown, APF.countrate)) apflog("getTarget(): Target= %s" % target["NAME"]) apflog("getTarget(): Counts=%.2f EXPTime=%.2f Nexp=%d" % (target["COUNTS"], target["EXP_TIME"], target["NEXP"]))
apflog("Setting SCRIPTOBS_LINES_DONE to 0") APFLib.write(apf.robot["SCRIPTOBS_LINES_DONE"], 0) APFLib.write(apf.robot["MASTER_VAR_2"], time.time()) APFTask.phase(parent, "Focus") apflog("Phase is now %s" % phase) # 2) Run autofocus cube if "Focus" == str(phase).strip(): apflog("Starting focusinstr script.", level='Info', echo=True) instr_permit() result = apf.focus() if not result: focusdict = APFTask.get("focusinstr",["phase","nominal"]) instr_perm = ktl.read("checkapf","INSTR_PERM",binary=True) if not instr_perm: while not instr_perm: apflog("Waiting for instrument permission to be true") APFTask.waitfor(parent,True,expression="$checkapf.INSTR_PERM = true",timeout=600) instr_perm = ktl.read("checkapf","INSTR_PERM",binary=True) if len(focusdict['phase']) > 0: flags = " ".join(["-p",focusdict['phase']]) else: flags = "-b" result = apf.focus(flags=flags) else: apflog("Focusinstr has failed. Seeting to %s." % (focusdict["nominal"]),level='error',echo=True) APFLib.write("apfmot.DEWARFOCRAW",focusdict["nominal"],binary=True) # sys.exit(1)
def getPscale(instrument): inst = ktl.read(instrument) return ktl.read(inst, 'pscale')
def getGscale(instrument): inst = ktl.read(instrument) return ktl.read(inst, 'gscale')