NIRC Scripting Examples
|
|
||
Scripting in the new NIRC software is basically scripting in the
UNIX shell. We cannot pretend to cover all of the ins and outs
of this topic, but fortunately there are many excellent books
on the subject.
The simplest user scripts will consist simply of lists of existing
NIRC commands, just the way you would type them in if you were
to enter them one by one on the command line. In this case all
you need is the line #!/bin/csh -f
at the start of your script.
A more complicated script will use UNIX commands to do more than
automate what you would type at the comand line. It is advisable
to use as an example an existing script as a starting point. You
will likely be able to find a "facility" script that
contains most of what you need. In that spirit we will dissect
a small number of facility scripts, starting below with the dithering
command bxy9. Remember
that the best technique to use in UNIX is to try out questionable
lines one-by-one. You can often tell how a variable substitution
or a command substitution will work by trying it at first on a
line by itself, possibly adding echo
to the beginning to print the line without executing it. Also,
complicated expressions can be built up piece by piece, checking
the functionality as each new piece is added. On to our first
dissection
The first line of the script, #!/bin/csh
-f, tells the computer that we will be using the
csh shell. This is the default for all of the NIRC facility scripts,
although you could run any number of programs, shells, and languages.
Note the -f after the shell
name. This tells the shell not to run the .cshrc file, which will
speed up the script.
The # signs are comment
statements (unless followed by "!"
as is the first line of the script). The if
statement tests to see whether two arguments have been passed.
#argv is a variable containing
the number of arguments, the {}
are delimiters used to make sure that the variable is clear to
the script, and the $ is
a variable substitution. Note that if bxy9
is not provided with two variables the else
section of the if block
is run, which merely prints out a reminder of the usage of the
script.
The command set x = $1
sets the variable x to
the script's first argument, represented by $1.
Similarly y is set to the
second argument. Next two one-dimensional arrays, xoff
and yoff, are defined.
These will be the offset positions.
The foreach statement sets
the variable pos to each
value enclosed in parantheses, in this case the integers 1 through
9. These values will be used as array indices later.
At each position (pos),
an image is taken by calling goi.
The telescope is then moved to the next position, which is offset
from the previous position by the arrays xoff
and yoff.
Note that the move command mxy
takes two arguments, the offset in x and the offset in y. The
scale factor for the offset in x is given by xoff,
and the specific value of xoff
is given by the position index, pos.
Hence the scale factor if $xoff[$pos],
where the $ again implies
variable substitution, and the square brackets specifies the index
of the array. This values is inside an echo
statement, which also includes an asterisk, denoting multiplication,
and the value of the argument for the pattern's step size in x,
given by x. The asterisk
is a special UNIX character, which generally is treated as a wildcard
character. In this case we have avoided this treatment by putting
it in double quotes, in which case it is treated simply as an
asterisk.
This echo statement will
send a string to the standard output (normally your terminal)
consisting of the appropriate xoffset
scale factor, and asterisk, and the box pattern x size. The pipe
character, |, takes this
string and diverts it from the terminal into the bc
-lm command. The bc command performs math on the
string; the -lm qualifier
makes sure it performs floating point math! In bc
the asterisk implies multiplication, so the result is the product
of xoff and x.
This again is normally sent to the standard output, but the back
quotes again intercept it and place it on the mxy
line. Back quotes mean "substitute the result of this command
or command sequence."
The odiff command displays
the difference of the last two files. Note the "&"
at the end of the line; this spawns the odiff
command as a separate process, letting the dither pattern get
on with its data-taking while the difference is being calculated
and displayed. This saves several seconds of time during the entire
bxy9 script.
The next script we will dissect is one used to take linearity
data. Rather than discuss each line, we only point out a number
of interesting constructions.
In the math in this script, note that the echo
statements do not use double quotes. In this case the asterick
must be escaped by prepending a "\".
Following the echo and
the bc parts of the math,
sed is used to truncate
the integration times to microseconds. In the sed
quotation marks, the initial "s"
means we will substitute what is between the first "/"
marks with what is between the second and third. The first string
is "\..*" which
contains several special characters. The "\"
escapes the first ".",
meaning the period (or decimal point, in this context) character.
The second "."
is unescaped, hence stands for any character. The "*"
at the end indicates any number of following characters, in other
words the rest of the string. Hence sed
is matching the decimal point and everything after it. It then
replaces it with nothing, since there is nothing between the second
and third "/"
marks. Thus the floating point number is effectively truncated.
The pstat command has five
arguments: the file number, for which the script uses the results
of the "lastfile"
command, a starting (x,y) pair, and an ending (x,y) pair. "lastfile"
returns the (numeric) value of the last file written. With only
one argument, pstat will
calculate statistics over the whole image. The last four arguments
restrict the statistics window to pixel (10,10) through pixel
(246,246). This is because the NIRC detector often has unusual
characeristics around its edge.
A third script shows the use of array math by invoking IDL. It
is the foc8 script, which
will step through 8 secondary focus positions, taking images at
each focus, subtracting the appropriate region from a sky frame,
and reassemble the central strips of the 8 images into a single
frame, showing the strips stacked on top of each other. The observer
is then meant to choose the strip with the best image quality,
setting the secondary to the appropriate focus.
In order to pass arguments to IDL, we set UNIX environment variables:
IDL_ARG1 and IDL_ARG2.
(These are not IDL-specific variables by nature, but you want
to assure that the names are unique enough that you don't accidentally
write over other important environment variables.)
IDL is then invoked; the <<'endofinput'
construct tells the script to pass everything from that point
until the line containing only 'endofinput'
is reached. This latter line must be left justified; do not indent
it even if the IDL call is in the midst of other indented lines.
The |& egrep
part of the IDL call is a means of trapping some of the header
and introductory text that IDL normally prints out when it is
started. This is not strictly necessary, but it makes the script's
output more concise and less confusing to the user.
Finally, the single command foc8,
which refers to a file foc8.pro
within the IDL path, is performed within IDL. We show that below
In this document we won't go into any IDL details, other than
the interaction with the script parameters and with the UNIX shell.
The former is demonstrated by the line containing GETENV('IDL_ARG1'),
which gets the environment variable set in the foc8
script. Note that such variables may require type adjustment;
they are brought into IDL as strings, but may be needed as numeric
variables.
This IDL script shows two methods for interacting with the UNIX
shell while inside IDL. The spawn
command can be used to send UNIX commands; but make sure you use
the /noshell qualifier
if you need to run NIRC commands. Otherwise the PATH will be set
to the login default, which doesn't include the NIRC commands.
Another technique is shown towards the end, where the command
sent to the UNIX shell includes a command, p3path,
which sets the appropriate PATH; in this case you do not need
the /noshell qualifier.
Some other comments on programming in the NIRC P3 software
There is always a possibility that you will use a variable name
in one script which then calls a second script, which also contains
a (different) variable with that name. This may be a particular
problem in calling facility scripts, which you may never have
seen, so you may not know what variables they contain. This is
a potential source of bugs which you should keep in mind.
Also, UNIX caches executable commands. What this means is that
if you have set your user directory using the "user
xyz" command, and then create a new command
in that directory and faithfully chmod
it to have execute permission, you may type the command name and
get a "command not found"
error. This is because UNIX is using its "hash table,"
the cache or table of executables which it created previously,
and which does not contain the new command. To reload the hash
table, type rehash. Then
your command should be accessible. Significantly, you do not have to limit yourself to csh scripts with an occassional IDL script to do array math. You can write C or Fortran code, Perl scripts, tcl/tk scripts, or whatever UNIX tools you want. |
|