If that's all there was to it, using PyRAF would be very simple. But we would be missing much of the point of using it, because from CL emulation mode we can't access many of the powerful programming features of the Python language. CL emulation mode may be comfortable for IRAF users, but when the time comes to write new scripts you should learn how to run IRAF tasks using native Python syntax.
Currently there are a number of ways of running tasks and setting parameters. The system is still under development, and depending on user feedback, we may decide to eliminate some of them. Below we identify our preferred methods, which we do not intend to eliminate and which we recommend for writing scripts.
When the PyRAF system is started using the pyraf command as described previously, the user's commands are actually being passed to an enhanced interpreter environment that allows use of IRAF CL emulation and provides other capabilities beyond those provided by the standard Python interpreter. In fact, when pyraf is typed, a special interpreter is run which is a front end to the Python interpreter. This front-end interpreter handles the translation of CL syntax to Python, command logging, filename completion, shell escapes and the like which are not available in the default Python interpreter.
It is also possible to use PyRAF from a standard Python session, which is typically started by simply typing python at the Unix shell prompt. In that case the simple CL syntax for calling tasks is not available and tab-completion, logging, etc., are not active. For interactive use, the conveniences that come with the PyRAF interpreter are valuable and we expect that most users will use PyRAF in this mode.
One important thing to understand is that the alternate syntax supported by the PyRAF front end interpreter is provided purely for interactive convenience. When such input is logged, it is logged in its translated, Python form. Scripts should always use the normal Python form of the syntax. The advantage of this requirement is that such scripts need no preprocessing to be executed by Python, and so they can be freely mixed with any other Python programs. In summary, if one runs PyRAF in its default mode, the short-cut syntax can be used; but when PyRAF is being used from scripts or from the standard Python interpreter, one must use standard Python syntax (not CL-like syntax) to run IRAF tasks.
Even in Python mode, task and parameter names can be abbreviated and,
for the most part, the minimum matching used by IRAF still applies.
As described above, when an IRAF
task name is identical to a reserved keyword in Python,
it is necessary to prepend a 'PY' to the IRAF task name (i.e.,
use iraf.PYlambda
, not iraf.lambda
). In Python
mode, when task parameters conflict with keywords, they
must be similarly modified. The statement iraf.imcalc(in="filename")
will generate a syntax error and must be changed either to
iraf.imcalc(PYin="filename")
or to
iraf.imcalc(input="filename")
. This keyword/parameter
conflict is handled automatically in CL emulation mode.
Some of the differences between the PyRAF interpreter and the regular Python interpreter besides the availability of CL emulation mode:
PyRAF interpreter | Python default interpreter | |
---|---|---|
--> |
>>> | |
.help |
n/a | |
.exit |
EOF (control-D) or sys.exit() | |
.logfile filename |
n/a | |
.logfile filename append |
n/a | |
.logfile |
n/a | |
! command |
os.system(' command') | |
!! |
os.system('/bin/sh') |
This example mirrors the sequence for the example given above in the discussion of CL emulation (§2). In the discussion that follows we explain and illustrate some variants.
The mapping of IRAF CL syntax to Python syntax is generally quite straightforward. The most notable requirements are:
iraf.
because
they come from the iraf module. In scripts, use
to load the iraf module. Note that the first time PyRAF is imported, the normal IRAF startup process is executed (which can take a while). We are working on techniques to do fast, lightweight startups for stand-alone Python scripts that use PyRAF. At the moment the only such approach is to startup in a directory with a custom version of login.cl that defines a minimal IRAF environment.
It is also possible to import tasks and packages directly using
With this approach, packages are automatically loaded
if necessary and tasks can be used without the iraf.
prefix.
Like the IRAF CL, packages must be loaded for tasks to be accessible.
iraf.fitsio()
, not just iraf.fitsio
.
Another change is that boolean keywords cannot be set using appended
+
or -
symbols. Instead, it is necessary to use the
more verbose keyword=value
form (e.g., long=yes
in the
example above). We have defined Python variables yes
and
no
for
convenience, but you can also simply say long=1
to set the
(abbreviated) longheader
keyword to true.
Emulating pipes in Python mode is also relatively simple. If a
parameter Stdout=1
is passed to a task, the task output
is captured and returned as a list of Python strings, with one
string for each line of output. This list can then be processed
using Python's sophisticated string utilities, or it can be
passed to another task using the Stdin parameter:
Stdin
and Stdout
can also be set to a filename
or a Python filehandle object to redirect output to or from a file.
Stderr
is also available for redirection. Note the
capital 'S' in these names - it is used to eliminate possible
conflicts with task parameter names, but in the future we may
decide to simplify these names by eliminating the uppercase 'S'.
Currently there are multiple ways of setting parameters. The most familiar is simply to provide parameters as positional arguments to the task function. For example
Alternatively, one can set the same parameters using keyword syntax:
Hidden parameters can only be set in the argument list this way (analogous to IRAF). As in the IRAF CL, the parameter values are learned for non-hidden parameters (depending on the mode parameter settings) but are not learned (i.e., are not persistent) for hidden parameters.
But parameters can also be set by setting task attributes. For example:
These attribute names can be abbreviated (don't expect this behavior for most Python objects, it is special for IRAF task objects):
PyRAF is flexible about the types used to specify the parameter so long as the conversion is sensible. For example, one can specify a floating point parameter in any of the following ways:
but if the following is typed:
An error traceback results. When running in the PyRAF interpreter,
a simplified version of the traceback is shown that omits functions that
are part of the pyraf package. The .fulltraceback
command
(which can be abbreviated as can all the executive commands) will
print the entire detailed traceback; it will probably only be needed
for PyRAF system developers. Python tracebacks can initially
appear confusing, but they are very informative once you learn
to read them. The entire stack of function calls is
shown from top to bottom, with the most recently called
function (where the error occurred) listed last. The line
numbers and lines of Python code that generated the error
are also given.
One can list the parameters for a task using one of the following
commands (in addition to the usual IRAF lpar imcopy
):
For those who have encountered object-oriented programming,
iraf.imcopy
is an 'IRAF task object' that has a method named lParam
that lists task
parameters. On the other hand, iraf.lpar
is a function (in the iraf
module) that takes either an IRAF task object or a string name of a task
as a parameter. It finds the task object and invokes the
.lParam()
method.
One can start the EPAR utility for the task using a parallel set of commands:
Tasks appear as attributes of packages, with nested packages also
found. For example, if you load the stsdas
package and
the restore
subpackage, then the mem
task can
be accessed through several different means: iraf.mem
,
iraf.stsdas.mem
, or iraf.restore.mem
will all
work. Ordinarily the simple iraf.mem
is used, but
if tasks with the same name appear in different packages, it
may be necessary to add a package name to ensure the proper
version of the task is found.
One way of reducing the typing burden (interactively or in scripts, though perhaps it isn't such a good idea for scripts) is to define an alias for the iraf module after it is loaded. One can simply type:
But don't use i
for a counter variable and then
try doing the same! E.g.,
will give you the following error message
since the integer '1' has no imcopy attribute.
Questions or comments? Contact help@stsci.edu Documented updated on 2002 May 3 |