Документ взят из кэша поисковой машины. Адрес оригинального документа : http://www.apo.nmsu.edu/35m_operations/TUI/Scripts/ScriptingManual.html
Дата изменения: Tue Sep 22 21:29:34 2015
Дата индексирования: Sun Apr 10 02:08:04 2016
Кодировка:

Поисковые слова: п п п п п п
TUI:Scripts:Scripting Manual

TUI:Scripts:Scripting Manual

Contents

Introduction

TUI scripts are a way to automate tasks you perform frequently.

Scripts are written in Python. If you are not familiar with python, I strongly recommend the python tutorial at Python's home. A knowledge of python's basics will make script writing much easier.

Once you have the basics of python, I recommend looking through the Scripting Tutorial. It offers many simple example scripts. Other scripts may be found in <tui_root>/TUI/Scripts.

Script Contents

A TUI script must be a text file whose name ends in ".py". The file must include either a ScriptClass class or a run function. I strongly suggest you use a ScriptClass for all but the very simplest of scripts.

ScriptClass

A class with the following special methods:

In addition, ScriptClass may contain any other methods and any variables you like. For examples, see the Scripting Tutorial.

Run Function

For very simple scripts, you may prefer to just define a run(sr) function. Your script may also contain init(sr) and/or end(sr) functions, and all work the same as the ScriptClass methods discussed above. However, if your script needs init and/or end, I strongly recommend writing it as a ScriptClass, so data can more easily be passed around.

Reporting Errors

To report an error, raise sr.ScriptError. For example:

def run(sr):
    ...
    if expTime <= 0:
        raise sr.ScriptError("Specify exposure time")

This will print the specified message to the status bar and halt the script. Other exceptions do this, as well, but also print a traceback to the error log. Thus other exceptions are ideal for internal bug checks, but sr.ScriptError is best for reporting "normal" errors.

ScriptRunner Reference

The run function (as well as init and end, if supplied) is passed a ScriptRunner object. This script runner provides support for your script, including:

The following methods wait, so a yield is required:

getKeyVar(keyVar, ind, defVal)

Return the current value of a keyword variable.

Note: if you want to be sure the keyword data was in response to a particular command that you sent, then use the keyVars argument of startCmd or waitCmd, instead.

Inputs:

A keyword variable contains data read from an instrument, the telescope or other "actor". Although you can create your own keyword variables, you rarely have to do so. Every actor has an associated model in TUI containing most or all of the useful keyword variables for that device.

Every keyword variable contains a list of 0 or more values. Often you only want one particular value. Thus the "ind" argument.

See also waitKeyVar, which can wait for a value.

showMsg(msg, severity=RO.Constants.sevNormal)

Display a message on the status bar.

Inputs:

Note that the status bar also shows the execution status of the script; for instance it says "Done" when the script finishes successfully. If you want more permanent output, consider adding a text or label widget and writing your message to that.

startCmd(
    actor = "",
    cmdStr = "",
    timeLim = 0,
    callFunc = None,
    callTypes = RO.KeyVariable.DoneTypes,
    timeLimKeyword = None,
    abortCmdStr = None,
    keyVars = None,
    checkFail = True,
)

Start a command using the same arguments as waitCmd.

Returns a command variable that you can wait for using waitCmdVars.

waitCmd(
    actor="",
    cmdStr = "",
    timeLim = 0,
    callFunc=None,
    callTypes = RO.KeyVariable.DoneTypes,
    timeLimKeyword = None,
    abortCmdStr = None,
    keyVars = None,
    checkFail = True,
)

Start a command and wait for it to finish. A yield is required. If you want to read any data that must only be in response to this command and no other then be sure to use the keyVars argument.

Inputs:

See also startCmd and waitCmdVars.

waitCmdVars(cmdVars)

Wait for one or more command variables (returned by startCmd) to finish. A yield is required.

Inputs:

Returns successfully once all commands succeed, but fails as soon as any command fails.

See also startCmd and waitCmd.

waitKeyVar(keyVar, ind=0, defVal=Exception, waitNext=False)

Get data from a keyword variable. A yield is required.

Inputs:

The data is returned in sr.value.

If the value is currently unknown or if waitNext is true, wait for the variable to be updated.

See also getKeyVar (which does not wait).

waitMS(msec)

Wait for a period of time specified in milliseconds. A yield is required.

Inputs:

waitThread(func, *args, **kargs)

Run a function as a background thread and wait for completion. A yield is required.

Inputs:

Any value returned by func is put into sr.value.

Warning: func must NOT interact with Tkinter widgets or variables (not even reading them) because Tkinter is not thread-safe. (The only thing I'm sure a background thread can safely do with Tkinter is generate an event, a technique that is used to detect end of thread).

For more information, see RO.ScriptRunner.

Yield When You Wait

Whenever your script calls an sr.wait... function (i.e. wants to wait for anything), it must use yield, as in:

	yield sr.wait...(...)

This is a painful, but it could be much worse. Most languages would force you to break code into many small functions, each of which is registered as a separate callback function. That sort of programming is fine for GUIs (and is used extensively in TUI), but it is not a nice way to write a script.

If you forget the "yield", your script will plow ahead instead of waiting, which is a recipe for trouble. However, TUI will catch this problem the next time you use an sr.wait...() function, at which point it will kill your script, print a message to the status bar and print details to the error log.

Calling Sub-Tasks

Repetitive tasks can be separated out into sub-tasks. If you find your script running the same bit of code more than once, you may want to move that bit into a separate function.

To execute a sub-task that contains yield you must use yield. To remind yourself, I suggest using a name that starts with "wait". For example:

class ScriptClass(object):
	def run(self, sr):
		#...
		yield self.waitDumbTask(sr, 3, 1000)
		#...
	
	def waitDumbTask(self, sr, nreps, dtime):
		for n in range(nreps):
			sr.showMsg("Wait %d" % n)
			yield sr.waitMS(dtime)

Only call a function with yield if the function contains yield. Note that __init__ and end cannot contain yield (cannot wait), so they cannot call functions that contain yield.

Where To Put Scripts

To make a script show up in the Scripts menu, put it into TUIAdditions/Scripts (or a subdirectory of that). If TUIAdditions or TUIAdditions/Scripts doesn't exist, create it. Details:

Debugging

Debug Mode

The script runner includes a basic debug mode which is enabled by putting sr.debug = True in your script. In debug mode, getKeyVar, startCmd and all the wait... commands print a diagnostic message to the error log when they run. Also:

Reloading a Script

To reload a script (i.e. after modifying it), select Reload from the contextual pop-up menu for any of the control buttons (Start, Pause or Cancel).

Warnings:

Diagnostic Output

print statements will print to to the error log. sr.showMsg is an alternative if standard output is not convenient for your platform.

More Information

APO Documentation contains pointers to manuals for the various instruments, the hub and the TCC.

The manual TUI Programming contains much information about the internals of TUI. Some of it is made simpler by using the scripting interface, but much of it is relevant -- especially if you want your script to use widgets (i.e. for user input or output).