def expose(cmd, actorState, replyQueue, expTime, stack=1, cartridge=None, expType='expose', camera='gcamera'): """Take an exposure with the e/gcamera, and succeed/fail as appropriate.""" cmd.respond('text="starting %s exposure"' % camera) filenameKey = actorState.models[camera].keyVarDict['filename'] cmdStr = '{0} time={1} stack={2}'.format(expType, expTime, stack) if expType == 'flat': cmdStr += ' cartridge={0}'.format(cartridge) responseMsg = Msg.FLAT_FINISHED elif expType == 'dark': responseMsg = Msg.DARK_FINISHED else: responseMsg = Msg.EXPOSURE_FINISHED # Allow for readout time for each exposure in the stack, plus a bit extra. timeLim = stack * expTime + stack * 5 + 15 cmd.diag('text="{0} {1} with timeLim={2}"'.format(camera, cmdStr, timeLim)) try: cmdVar = actorState.actor.cmdr.call(actor=camera, cmdStr=cmdStr, keyVars=[filenameKey], timeLim=timeLim, forUserCmd=cmd) cmd.diag('text="{0} {1} didFail={2}"'.format(camera, cmdStr, cmdVar.didFail)) except Exception as e: cmd.warn('text="{0} {1} raised {2}"'.format(camera, cmdStr, e)) return if cmdVar.didFail: cmd.warn('text="Failed to take {0} exposure"'.format(camera)) if cmdVar.lastReply and 'Timeout' in cmdVar.lastReply.keywords: cmd.warn( 'text="{0} expose command exceeded time limit: {1}."'.format( camera, timeLim)) replyQueue.put(Msg(responseMsg, cmd=cmd, success=False)) return filename = cmdVar.getLastKeyVarData(filenameKey)[0] replyQueue.put( Msg(responseMsg, cmd=cmd, filename=filename, camera=camera, success=True))
def disableFibersImpl(self, cmd, enable=True): """Disable a set of fibers""" if 'fibers' in cmd.cmd.keywords: for f in cmd.cmd.keywords['fibers'].values: myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.ENABLE_FIBER, cmd=cmd, fiber=f, enable=enable)) elif 'gprobes' in cmd.cmd.keywords: gprobeType = cmd.cmd.keywords['gprobes'].values[0].upper() myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.ENABLE_FIBER, cmd=cmd, fiber=gprobeType, enable=enable)) self.status(cmd) # finishes this command
def flat(self, cmd): """Take, and process, a guider flat.""" expTime = cmd.cmd.keywords['time'].values[ 0] if 'time' in cmd.cmd.keywords else 0.5 force = 'force' in cmd.cmd.keywords myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.TAKE_FLAT, cmd=cmd, expTime=expTime, force=force))
def setPID(self, cmd): """Set something's PID coefficients""" axis = None for k in ['raDec', 'rot', 'focus', 'scale']: if k in cmd.cmd.keywords: axis = k break if not axis: cmd.fail("text=\"Impossible condition in setPID\"") # TODO: should Imax and nfilt default to zero? (JSG) Kp = cmd.cmd.keywords['Kp'].values[0] Ti = cmd.cmd.keywords['Ti'].values[0] if 'Ti' in cmd.cmd.keywords else 0 Td = cmd.cmd.keywords['Td'].values[0] if 'Td' in cmd.cmd.keywords else 0 Imax = cmd.cmd.keywords['Imax'].values[ 0] if 'Imax' in cmd.cmd.keywords else 0 nfilt = cmd.cmd.keywords['nfilt'].values[ 0] if 'nfilt' in cmd.cmd.keywords else 0 ncorr = cmd.cmd.keywords['ncorr'].values[ 0] if 'ncorr' in cmd.cmd.keywords else 1 myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.SET_PID, cmd=cmd, axis=axis, Kp=Kp, Ti=Ti, Td=Td, Imax=Imax, nfilt=nfilt, ncorr=ncorr))
def starInFiber(self, cmd): """ Put a star down a given probe """ probe = cmd.cmd.keywords['probe'].values[ 0] if 'probe' in cmd.cmd.keywords else None gprobe = cmd.cmd.keywords['gprobe'].values[ 0] if 'gprobe' in cmd.cmd.keywords else None if (probe is None and gprobe is None) or (probe is not None and gprobe is not None): cmd.fail('text="exactly one destination probe must specified"') return fromProbe = cmd.cmd.keywords["fromProbe"].values[ 0] if 'fromProbe' in cmd.cmd.keywords else None fromGprobe = cmd.cmd.keywords["fromGprobe"].values[ 0] if 'fromGprobe' in cmd.cmd.keywords else None if (fromProbe is not None and fromGprobe is not None): cmd.fail('text="no more than one source probe can be specified"') return myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.STAR_IN_FIBER, cmd=cmd, probe=probe, gprobe=gprobe, fromProbe=fromProbe, fromGprobe=fromGprobe))
def reprocessFile(self, cmd): """Reprocess a single file.""" myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.REPROCESS_FILE, cmd=cmd, filename=cmd.cmd.keywords["file"].values[0]))
def mangaDither(self, cmd): """Specify a particular manga dither position for decentered guiding.""" # ra, dec, rot dithers = { 'N': { 'decenterRA': -0.417, 'decenterDec': +0.721, 'decenterRot': 0.0 }, 'S': { 'decenterRA': -0.417, 'decenterDec': -0.721, 'decenterRot': 0.0 }, 'E': { 'decenterRA': +0.833, 'decenterDec': 0., 'decenterRot': 0.0 }, 'C': { 'decenterRA': 0., 'decenterDec': 0., 'decenterRot': 0.0 } } ditherPos = cmd.cmd.keywords['ditherPos'].values[0] try: decenters = dithers[ditherPos] decenters['mangaDither'] = ditherPos except KeyError: cmd.fail("text=%s" % qstr( "Failed to parse manga dither position: %s" % ditherPos)) else: masterQueue = myGlobals.actorState.queues[guiderActor.MASTER] masterQueue.put(Msg(Msg.DECENTER, cmd=cmd, decenters=decenters))
def oneStep(self, cmd): """Centers stars in acquisition gprobes.""" expTime = (cmd.cmd.keywords['time'].values[0] if 'time' in cmd.cmd.keywords else 0.5) myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.ONESTEP, cmd=cmd, expTime=expTime))
def setExpTime(self, cmd): """Set the exposure time""" expTime = cmd.cmd.keywords['time'].values[0] stack = cmd.cmd.keywords['stack'].values[ 0] if 'stack' in cmd.cmd.keywords else 1 myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.SET_TIME, cmd=cmd, expTime=expTime, stack=stack))
def loadPlateFiles(self, cmd): """Read in cartridge and plugmap files. """ myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.READ_PLATE_FILES, cmd=cmd, plugfile=cmd.cmd.keywords["plugfile"].values[0], cartfile=cmd.cmd.keywords["cartfile"].values[0]))
def status(self, cmd, full=True): """Return guide status status""" self.actor.sendVersionKey(cmd) if "geek" in cmd.cmd.keywords: for t in threading.enumerate(): cmd.inform('text="%s"' % t) myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.STATUS, cmd=cmd, finish=True))
def fk5InFiber(self, cmd): """Have the TCC put a bright star down a given probe""" actorState = guiderActor.myGlobals.actorState probe = cmd.cmd.keywords['probe'].values[ 0] if 'probe' in cmd.cmd.keywords else None expTime = cmd.cmd.keywords['time'].values[ 0] if 'time' in cmd.cmd.keywords else 0.1 stack = cmd.cmd.keywords['stack'].values[ 0] if 'stack' in cmd.cmd.keywords else 1 # Force up an image-only guide loop for what in ['scale', 'focus', 'axes']: actorState.queues[guiderActor.MASTER].put( Msg(Msg.SET_GUIDE_MODE, cmd=cmd, what=what, enable=False)) actorState.queues[guiderActor.MASTER].put( Msg(Msg.START_GUIDING, cmd=cmd, oneExposure=False, expTime=expTime, stack=stack, force=True)) if probe: cmdVar = actorState.actor.cmdr.call(actor='tcc', forUserCmd=cmd, cmdStr='set ptErrProbe=%d' % (probe)) if cmdVar.didFail: cmd.fail( "text=\"Failed to set the pointing error probe to %s\"" % (probe)) return cmdVar = actorState.actor.cmdr.call(actor='tcc', forUserCmd=cmd, cmdStr='track/pterr') if cmdVar.didFail: cmd.fail("text=\"Failed to move to a bright star\"") return cmd.finish("text='There should be a bright star in probe'")
def bias(self, cmd): """Takes a stack of bias images.""" stack = (cmd.cmd.keywords['stack'].values[0] if 'stack' in cmd.cmd.keywords else 7) if stack < 5: cmd.fail('text="bias requires a minimum stack of 5 images."') return myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.TAKE_BIAS, cmd=cmd, stack=stack))
def dark(self, cmd): """ Take, and process, a guider dark. Recommended: guider dark time=15 stack=9 Minimum for a processed dark: guider dark time=10 stack=5 """ expTime = cmd.cmd.keywords["time"].values[ 0] if "time" in cmd.cmd.keywords else 15 stack = cmd.cmd.keywords["stack"].values[ 0] if "stack" in cmd.cmd.keywords else 3 myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.TAKE_DARK, cmd=cmd, expTime=expTime, stack=stack))
def makeMovie(self, cmd): """Create a movie of guider images in /data/gcam/movieMJD from a range of exposures from start to end.""" mjd = cmd.cmd.keywords['movieMJD'].values[ 0] if 'movieMJD' in cmd.cmd.keywords else None start = cmd.cmd.keywords['start'].values[0] end = cmd.cmd.keywords['end'].values[0] movieQueue = myGlobals.actorState.queues[guiderActor.MOVIE] movieQueue.put( Msg(Msg.MAKE_MOVIE, cmd=cmd, mjd=mjd, start=start, end=end, finish=True))
def setRefractionBalance(self, cmd): """Set refraction balance to a specific correction ratio.""" keywords = cmd.cmd.keywords corrRatio = keywords['corrRatio'].values[ 0] if 'corrRatio' in keywords else None plateType = keywords['plateType'].values[ 0] if 'plateType' in keywords else None surveyMode = keywords['surveyMode'].values[ 0] if 'surveyMode' in keywords else None myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.SET_REFRACTION, corrRatio=corrRatio, plateType=plateType, surveyMode=surveyMode, cmd=cmd))
def setDecenter(self, cmd): """Specify absolute offset location for decentered guiding.""" keywords = cmd.cmd.keywords # for now Decenter rot is around (RA+decenterRA, Dec+decenterDec) decenters = {} decenters['decenterRA'] = keywords["decenterRA"].values[ 0] if "decenterRA" in keywords else 0 decenters['decenterDec'] = keywords["decenterDec"].values[ 0] if "decenterDEC" in keywords else 0 # Though these are currently available, we don't want to use them. if "decenterRot" in keywords: cmd.fail('Guider cannot apply a decenter in Rotation (yet).') return masterQueue = myGlobals.actorState.queues[guiderActor.MASTER] masterQueue.put(Msg(Msg.DECENTER, cmd=cmd, decenters=decenters))
def restart(self, cmd): """Restart the worker threads""" myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.STOP_GUIDING, cmd=cmd)) actorState = myGlobals.actorState cmd.inform('text="Restarting threads or at least _trying to_)"') # We can't finish this command after all the threads have died, 'cuz we might not get there. actorState.actor.startThreads( actorState, actorState.actor.bcast, restart=True, restartQueues=True) cmd.finish("text=\"Nunc dimittis servum tuum Domine\"")
def ecam_findstar(self, cmd): """ Take one ecam exposure, reduce it, and output the stars found therein. """ time = cmd.cmd.keywords['time'].values[ 0] if 'time' in cmd.cmd.keywords else 5 # TBD: Can't change ecam binning yet! bin = cmd.cmd.keywords['bin'].values[ 0] if 'bin' in cmd.cmd.keywords else 1 queue = myGlobals.actorState.queues[guiderActor.MASTER] queue.put( Msg(Msg.START_GUIDING, cmd=cmd, expTime=time, oneExposure=True, bin=bin, camera='ecamera'))
def guideOn(self, cmd): """Turn guiding on""" force = "force" in cmd.cmd.keywords oneExposure = "oneExposure" in cmd.cmd.keywords expTime = cmd.cmd.keywords["time"].values[ 0] if "time" in cmd.cmd.keywords else None stack = cmd.cmd.keywords["stack"].values[ 0] if "stack" in cmd.cmd.keywords else 1 camera = 'ecamera' if myGlobals.actorState.gState.plateType == 'ecamera' else 'gcamera' myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.START_GUIDING, cmd=cmd, expTime=expTime, stack=stack, camera=camera, force=force, oneExposure=oneExposure))
def resetPID(self, cmd): """Resets all or some of the PIDs terms to their default value.""" if len(cmd.cmd.keywords) == 1: terms = [cmd.cmd.keywords[0].name] cmd.inform('text="reseting PID terms for {0}"'.format(terms[0])) elif len(cmd.cmd.keywords) == 0: terms = None cmd.inform('text="reseting all PID terms"') else: cmd.fail('text="failed"') return myGlobals.actorState.gState.reset_pid_defaults(terms=terms) if terms is None: terms = myGlobals.actorState.gState.pid.keys() for term in terms: myGlobals.actorState.gState.pid[term].reset() myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.STATUS, cmd=cmd, finish=True))
def setPID(self, cmd): """Set something's PID coefficients""" what = None for k in ["raDec", "rot", "focus", "scale"]: if k in cmd.cmd.keywords: what = k break if not what: cmd.fail("text=\"Impossible condition in setPID\"") return Kp = cmd.cmd.keywords["Kp"].values[0] Ti = cmd.cmd.keywords["Ti"].values[ 0] if "Ti" in cmd.cmd.keywords else None Td = cmd.cmd.keywords["Td"].values[ 0] if "Td" in cmd.cmd.keywords else None Imax = cmd.cmd.keywords["Imax"].values[ 0] if "Imax" in cmd.cmd.keywords else None nfilt = cmd.cmd.keywords["nfilt"].values[ 0] if "nfilt" in cmd.cmd.keywords else None if what == 'raDec' and Ti is not None: # Disable automatic scaling with alitude since we have set # a custom value. myGlobals.actorState.gState.diable_ti_scaling = True myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.SET_PID, cmd=cmd, axis=what, Kp=Kp, Ti=Ti, Td=Td, Imax=Imax, nfilt=nfilt))
def correctionImpl(self, cmd, what): """Turn guiding something on or off""" on = "on" in cmd.cmd.keywords myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.SET_GUIDE_MODE, cmd=cmd, what=what, enable=on))
def centerUp(self, cmd): """Force a single XY offset""" myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.CENTERUP, cmd=cmd))
def flat(self, cmd): """Take, and process, a guider flat.""" expTime = cmd.cmd.keywords["time"].values[ 0] if "time" in cmd.cmd.keywords else 0.5 myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.TAKE_FLAT, cmd=cmd, expTime=expTime))
def decenter(self, cmd): """Enable/disable decentered guiding.""" on = "on" in cmd.cmd.keywords masterQueue = myGlobals.actorState.queues[guiderActor.MASTER] masterQueue.put(Msg(Msg.DECENTER, cmd=cmd, enable=on))
def setScale(self, cmd): """Change telescope scale by a factor of (1 + 0.01*delta), or to scale """ myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.CHANGE_SCALE, cmd=cmd, finish=True))
def showCartridge(self, cmd, full=True): """Reveal the identity of the current cartridge""" myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.STATUS, cmd=cmd, full=False, finish=True))
def guideOff(self, cmd): """Turn guiding off""" myGlobals.actorState.queues[guiderActor.MASTER].put( Msg(Msg.STOP_GUIDING, cmd=cmd))
def loadCartridge(self, cmd): """ Load a cartridge. If the cartridge ID is omitted the currently-mounted cartridge is used. Error if cartridge that isn't actually mounted is specified (unless force is also given). """ queue = myGlobals.actorState.queues[guiderActor.MASTER] force = "force" in cmd.cmd.keywords cartridge = cmd.cmd.keywords["cartridge"].values[ 0] if "cartridge" in cmd.cmd.keywords else -1 pointing = cmd.cmd.keywords["pointing"].values[ 0] if "pointing" in cmd.cmd.keywords else "A" # If they specify a plate explicitly, # we'll bypass the active table and give them what they want plate = str(cmd.cmd.keywords["plate"].values[ 0]) if "plate" in cmd.cmd.keywords else None mjd = cmd.cmd.keywords["mjd"].values[ 0] if "mjd" in cmd.cmd.keywords else None fscanId = cmd.cmd.keywords["fscanId"].values[ 0] if "fscanId" in cmd.cmd.keywords else None guideWavelength = (cmd.cmd.keywords['guideWavelength'].values[0] if 'guideWavelength' in cmd.cmd.keywords else None) # Cartridge ID of 0 means that no cartridge is loaded if cartridge == 0: gprobes = {} plate = 0 boresight_ra = float("NaN") boresight_dec = float("NaN") design_ha = ("NaN") # Send that information off to the master thread queue.put( Msg(Msg.LOAD_CARTRIDGE, cmd=cmd, cartridge=cartridge, plate=plate, pointing=pointing, boresight_ra=boresight_ra, boresight_dec=boresight_dec, design_ha=design_ha, gprobes=gprobes)) return # # Check that the claimed cartridge is actually on the telescope # actorState = guiderActor.myGlobals.actorState if force and cartridge != -1: loadedCartridge = cartridge cmd.inform('text="Assuming cartridge {} is on the telescope"' .format(loadedCartridge)) else: instrumentNumKey = actorState.models["mcp"].keyVarDict["instrumentNum"] cmdVar = actorState.actor.cmdr.call( actor="mcp", forUserCmd=cmd, cmdStr="info", keyVars=[instrumentNumKey]) if cmdVar.didFail: cmd.fail("text=\"Failed to ask mcp for info on cartridges\"") return loadedCartridge = cmdVar.getLastKeyVarData(instrumentNumKey)[0] cmd.inform( "text=\"Cartridge %s is on the telescope\"" % loadedCartridge) # Only auto-select the cart if a plate was not specified. if cartridge < 0 and plate is None: cartridge = loadedCartridge if loadedCartridge != cartridge: msg = "Expected cartridge %s, but %s is loaded" % (cartridge, loadedCartridge) if force: cmd.warn("text=\"%s\"" % (msg + "; proceeding")) else: cmd.fail("text=\"%s\"" % msg) return # cart 19 is the engineering camera, and has no info in platedb. if cartridge == 19: # don't do anything but clear the gprobes and output status. gState = actorState.gState gState.deleteAllGprobes() gState.cartridge = cartridge gState.plate = 0 gState.pointing = pointing gState.plateType = 'ecamera' gState.surveyMode = None queue.put(Msg(Msg.STATUS, cmd, finish=True)) return # Get the plate from the plateDB extraArgs = "" if plate: extraArgs += " plate=%s" % (plate) if mjd: extraArgs += " mjd=%s" % (mjd) if fscanId: extraArgs += " fscanId=%s" % (fscanId) pointingInfoKey = actorState.models['platedb'].keyVarDict[ 'pointingInfo'] guideWavelengthKey = actorState.models['platedb'].keyVarDict[ 'guideWavelength'] cmdVar = actorState.actor.cmdr.call(actor="platedb", forUserCmd=cmd, cmdStr="loadCartridge cartridge=%d pointing=%s %s" % \ (cartridge, pointing, extraArgs), keyVars=[pointingInfoKey, guideWavelengthKey]) if cmdVar.didFail: cmd.fail("text=\"Failed to lookup plate corresponding to %d/%s\"" % (cartridge, pointing)) return plate = cmdVar.getLastKeyVarData(pointingInfoKey)[0] boresight_ra = cmdVar.getLastKeyVarData(pointingInfoKey)[3] boresight_dec = cmdVar.getLastKeyVarData(pointingInfoKey)[4] design_ha = cmdVar.getLastKeyVarData(pointingInfoKey)[5] survey = cmdVar.getLastKeyVarData(pointingInfoKey)[8] surveyMode = cmdVar.getLastKeyVarData(pointingInfoKey)[9] # Retrieves the guide wavelength from the DB. If guideWavelength has # not been defined in the command, uses that. if not guideWavelength: dbGuideWavelength = cmdVar.getLastKeyVarData(guideWavelengthKey)[0] guideWavelength = int( dbGuideWavelength) if dbGuideWavelength else None else: guideWavelength = int(guideWavelength) # If the guideWavelength is not defined and the plate is APOGEE-lead, # we set the default guide wavelength if not guideWavelength or guideWavelength == -1: if survey in ['APOGEE', 'APOGEE-2']: guideWavelength = 16600 elif survey in ['APOGEE&MaNGA', 'APOGEE-2&MaNGA']: if surveyMode == 'APOGEE lead': guideWavelength = 16600 if design_ha < 0: design_ha += 360 # Lookup the valid gprobes gprobeKey = actorState.models["platedb"].keyVarDict["gprobe"] gprobesInUseKey = actorState.models["platedb"].keyVarDict[ "gprobesInUse"] cmdVar = actorState.actor.cmdr.call( actor="platedb", forUserCmd=cmd, cmdStr="getGprobes cartridge=%d pointing=%s %s" % (cartridge, pointing, extraArgs), keyVars=[gprobeKey, gprobesInUseKey]) if cmdVar.didFail: cmd.fail("text=\"Failed to lookup gprobes for cartridge %d\"" % (cartridge)) return # Unpack the various platedb guider keys into a Probe instance for each probe # NOTE: ordered so that we first set the gprobebits, then fill in the rest of the values. # as otherwise the gprobebits would overwrite some of the state we set. gprobes = {} for key in cmdVar.getLastKeyVarData(gprobesInUseKey): probeId, flags = key.strip('()').split('=') gprobes[int(probeId)] = GuiderState.GProbe(int(probeId)) gprobes[int(probeId)].gprobebits = int(flags, 16) for key in cmdVar.getKeyVarData(gprobeKey): try: gprobes[key[1]].from_platedb_gprobe(key) except (KeyError, ValueError), e: cmd.warn('text=%s' % e) cmd.warn('text="Unknown probeId %s from platedb.gprobe. %s"' % (probeId, str(key))) continue