View on GitHub

IRAF Community Distribution

IRAF maintained by the community

Home | Installation | Packages | X11IRAF | PyRAF | Forum

CL scripting from Unix (Examples)

Mike Fitzpatrick wrote on Mar 07, 2000

> Any chance of a couple of example scripts ?

	I was afraid somebody was gonna ask this. But since you did...
In all the examples the only deviation I've made from my last reply is
that I'm assuming that the "arch" variable is set by the user's envir-
onment in the .cshrc file.  Doing so along with the use of a generic path
to the CL executable such as "/usr/local/bin/cl.e" means that there is
no platform dependence in the script itself.  All that is required to
re-use the scripts on a different machine is that 1) a link to the CL
binary be created and 2) the user define an 'arch' variable in their
unix environment.


Example 1:  A host DISPLAY command.
-----------------------------------

	For the first example let's write a wrapper script around the
DISPLAY command to allow images to be displayed from the command line.
A simplified version of the script would look something like:

    #!/usr/local/bin/cl.e -f

    reset stdimage = imt1024		# default environment	
    logver = "IRAF V2.11 May 1997"	# needed for IMAGES package

    images				# load needed packages
    tv
	    # Execute the command.
	    printf ("display %s\n", args) | cl()
    logout				# shut down

Note that we must define a 'stdimage' if we intend to use something other
than the default imt512.  The setting of 'logver' is required since we
will be loading the IMAGES package to get to the task.  In order to let
the script execute as fast as possible we don't define environment vars we
don't strictly need here, e.g. home$, uparm$, etc.
	The task itself is executed by simply creating a command string we
will pipe to a cl() call that executes it.  This allows us to simply pass
all the arguments on the command line to the task.  For example,

	% display dpix.imh 1
	% display dpix.imh 1 zscale-
	% display dpix.imh 1 zs- zr- z1=100 z2=1200
	% display dev\$pix.imh 1

Notice that in the last case when displaying dev$pix it was necessary to
escape the '$', otherwise the entire argument list is passed to the
DISPLAY command as-is, allowing us to retain the CL syntax for setting
parameters.  This is one reason the command is executed using the "command
mode" syntax, using the normal procedure script "program mode" would mean
that each argument would have to be broken out separately in order to
define the parameter.


Example 2: A host IMARITH or IMEXPR command.
---------------------------------------------

	The idea here is roughly the same as above:

    #!/usr/local/bin/cl.e -f

    set imdir = "HDR$pixels/" 		# default environment	
    logver = "IRAF V2.11 May 1997"	# needed for IMAGES package

    images				# load needed packages
    imutil

	    # Execute the command.
	    printf ("imarith %s\n", args) | cl()
    logout				# shut down

Note that the environment and necessary packages will be different here
so there is a little customization required for each script.  In this case
since we'll be creating an output image of some kind we'll need to define
an 'imdir' of some kind.
	Again we pass in the entire command line but with a task like this
we not only need to be careful about escaping the '$' of an IRAF logical,
but other special chars such as '*'.  For example,

	% imarith dev\$pix \* 10 newimg 

The host csh regards '*' as a special char and so it too must be escaped 
so as not to be expanded on the command line.

	The same example could be used as a wrapper for the IMEXPR command
by simply changing the command name from 'imarith' to 'imexpr' since the
rest of the script is identical.  The thing to note here however is again
the shell escapes required.  For example, the expression argument to this
task is often put in quotes on the CL command line, and those quotes need
to be passed thru to the script in order for the command to execute
properly.  To do this you would use a command such as

	% imexpr '"(a > 100 ? 0 : a)"' newimg a=dev\$pix


Example 3: A host graphics command.
-----------------------------------

	Graphics commands can also be used in #!cl scripts, but note that
in this case we need to set the terminal type so the plot appears correctly.
This can either be some hardwired value or it can set using an envget()
call on the TERM environment variable as is done in the login.cl.  In
this case it may also be desirable to set the 'stdplot' variable so the
'=' or ':.snap' hardcopy commands work as needed.  For example, a script
around IMPLOT might look something like:

    #!/iraf/iraf/bin.ssun/cl.e -f

    reset stdplot = "lw8"		# default environment
    stty xgterm				# set the terminal type

    plot				# load needed packages.
	    # Execute the command.
	    printf ("implot %s\n", args) | cl()
    logout				# shut down


Example 4: A host HELP command.
-------------------------------

	As a last example let's see write a #!cl script that parses
the args list to make the command look more like a unix command.  In
this case we'll write a wrapper for the HELP command that uses '-r' and
'-p' command line options to modify the task behavior slightly.

    #!/usr/local/bin/cl.e -f

    set     home    = "/u2/fitz/"	# default environment
    set     uparm   = "home$uparm/"

    stty xgterm				# set terminal type for pager
    lists				# need LISTS for arg parsing

	# Declare local variables.
	string	arglist			# arg values
	string	command = "help"
	string  task			# options

	# Parse unix command-line args.
	arglist = mktemp ("tmp$help")
	print (args) | words ("STDIN", > arglist)
	list = arglist
	while (fscan (list, s1) != EOF) {
	    if (s1 == "-r") {  
		command = "references"
	    } else if (s1 == "-p") {  
		command = "phelp"
	    } else {
		task = s1
	    }
	    ;				# needed to fix CL grammar quirk
	}
	delete (arglist, ver-)		# clean up
	list = ""
	
	# Finally, execute the requested command on the task.
	printf ("%s %s mode='q'\n", command, task) | cl()

    logout				# shut down

For this script the default behavior is to simply call the HELP task on
the named argument (i.e. the task).  By setting the '-p' flag we can
instead call PHELP in order to page the output, or by using '-r' call
REFERENCES to do a subject search for a given keyword.
	In this case we do define a uparm$ local because we might wish to
make use of the quick-reference file normally stored there and used by the
REFERENCES task (and assuming the references.usequick param has been set
in a CL session earlier).  Again we need to define the terminal type
because we may be using the file pager.
	The LISTS.WORDS task is used to break an 'args' string such as "-p
imexamine" (i.e. we want to run "phelp imexamine") into a list of
arguments written to a temporary file.  We fscan the file to get each
argument and act accordingly to set the command to be run or the task
name.  Note there is no method here for setting specific parameters that
might be desired such as the help 'option' or 'section',  but they could
be easily added in the same way.
	To use this task it could be called as

	% help -r mask			# to find all 'mask' tasks
	% help -p imexam		# page help for IMEXAMINE

In this way we can combine several similar tasks into one. 

	The "script body" in these examples are all relatively primitive.
As long as the proper environment is defined and required packages loaded,
the body of the script can declare it own variable or tasks and be written
in much the same way as any other procedure script.  Users should note 
however that the same rules against multiply loading packages in scripts
which call scripts (and lead to "dictionary full" errors) still apply,
to be safe packages can be checked before loading using something like

    	if (!defpac ("images")) {
       	    images
	}

This example also points out a bug in the CL in which a null ';' statement
is required following an if-clause if there is no other valid statement
following the closing brace (see the arg parsing).
	Lastly, if no arguments are passed at all to any of these scripts
the normal parameter prompting will still be in effect, but the escapes
for special characters will not be required.  For example,

	% implot
	image to be plotted: dev$pix


	The earlier posting and these examples, along with revisions to
them, will be made available from our web page.  Feel free to followup with
questions and anyone who develops a handy #!cl script they'd like to 
distribute should feel free to drop if off in our /contrib directory on
iraf.noao.edu (along with a readme saying what it does) or post it to
adass.iraf.sources.

Cheers,
-Mike

Fabricio Ferrari wrote on Mar 09, 2000

Mike

I'm trying to make some contour plot superimposed to images
with disconlab/newcont/wcslabs. The strange thing about is
that whatever I do the contours and the ra/dec lines apear 
dotted in the graphs. 

More strange either is that on other machine with the same IRAF
the contours appears alright. The IRAF is exactly the same,
I have copied from one to another. 

The systems are PC/Linux (Red Hat 6.1) running iraf 2.11.3,
with the patches 3a applied.

It's nothing so simple as the uparm directives, for example.

I'm am really messed with this. Sorry for writing for such
(apparently) simple reason but I can't go further.

Thanx again. Mike

Fabricio

Mike Fitzpatrick wrote on Mar 09, 2000

Fabricio,
	The axis lines are drawn by WCLAB using the parameters specified
in the IMAGES.TV.WLPARS pset.  Try doing an 

		cl> unlearn wlpars

to reset these and you should get a solid line again.   Let me know if 
you still have problems.

Cheers,
-Mike

Stephen Walton wrote on Mar 14, 2000

I know it is far from your example, in that it doesn't set everything up
properly, but I've been meaning to mention this for some time.  Try
this:

#!/usr/local/bin/cl.e -f
set arch=".redhat"		# or whatever
show
logout

Works fine from the command line.   However, submit it as a batch or at
job and it goes into an infinite loop.  This on both Redhat 6.1 and
HP/UX 10.20.

--
Stephen Walton, Professor, Dept. of Physics & Astronomy, Cal State
Northridge
stephen.walton@csun.edu

Mike Fitzpatrick wrote on Mar 14, 2000

> I know it is far from your example, in that it doesn't set everything up
> properly, but I've been meaning to mention this for some time.  Try
> this:
> 
> #!/usr/local/bin/cl.e -f
> set arch=".redhat"              # or whatever
> show
> logout
> 
> Works fine from the command line.   However, submit it as a batch or at
> job and it goes into an infinite loop.  This on both Redhat 6.1 and
> HP/UX 10.20.

	Excellent question!  The answer lies in the fact that 'at' and
'batch' commands are executed using the Bourne shell.   For your script
you would start an at job on the command line using something like

	% at -f show.cl now + 2 hours

What happens is that the file named by the -f flag, as well as the current
environment (more or less), userid, etc, are written to a file in the
/var/spool/at directory (on linux anyway) which looks something like

	#!/bin/sh
	# atrun uid=359 gid=100
	# mail     fitz 0
	umask 22
	HOSTNAME=zippy.tuc.noao.edu; export HOSTNAME
	LOGNAME=fitz; export LOGNAME
	      :
	      :   [remainder of environment deleted]
	      :
	COLUMNS=80; export COLUMNS
	LINES=60; export LINES
	cd /tmp || {
	         echo 'Execution directory inaccessible' >&2
	         exit 1
	}
	#!/iraf/iraf/bin.redhat/cl.e -f
	
	set arch=".redhat"              # or whatever
	set clobber = yes
	show 
	logout

When it comes time for the task to be run this file is executed.  Notice
that the contents of your #!cl script are now in the middle of #!/bin/sh
script, and so the commands in your file are expected to be Bourne shell
commands.  In this case the 'set' command are recognized but 'show' is
taken to be the /usr/bin/show command if it's recognized at all.  So 
for at/batch commands the #! part of the script is never executed to start
the CL as the interpreter, it's simply taken as a comment.  Note that the
same thing happens when using #!/bin/csh scripts in at files.

	To execute a #!cl script in an at/batch command the actual file
you pass to the at command should contain e.g. only the path to the #!cl
script you want to execute (assuming it's an executable file).  Lastly, 
there are also problems with your example in having the output not be 
redirected.  This can be worked around by having the file passed to 'at'
do the redirection, but be sure to use Bourne shell syntax when doing so.

-Mike

Stephen Walton wrote on Mar 20, 2000

This is Steve Walton believe it or not, writing from home.

Mike Fitzpatrick wrote:

> I wrote:

> >
> > #!/usr/local/bin/cl.e -f
> > set arch=".redhat"              # or whatever
> > show
> > logout
> >
> > Works fine from the command line.   However, submit it as a batch or at
> > job and it goes into an infinite loop.  This on both Redhat 6.1 and
> > HP/UX 10.20.
>
>         Excellent question!  The answer lies in the fact that 'at' and
> 'batch' commands are executed using the Bourne shell.   For your script
> you would start an at job on the command line using something like
>

Mike's example of using 'at -f file.cl' deleted.  This does put the contents
of file.cl in the command file generated by at, which means that the shell
will try to execute the commands instead of the IRAF CL.  But that isn't what
I did:

>
>                To execute a #!cl script in an at/batch command the actual
> file
> you pass to the at command should contain e.g. only the path to the #!cl
> script you want to execute (assuming it's an executable file).

I think I did this:

% at now+2hours
show.cl
^D

Looking at the at-generated script, there was a list of environment variables
followed at the end by 'show.cl' on its own line.  If I did 'sh at-script'
from the command line, the command ran and printed out the IRAF environment
and exited.  But the version run by at still went into an infinite loop.  It
did work to do:

% at now+2hours
/usr/local/bin/cl.e < show.cl
^D

but that kind of defeats the purpose.

Steve Walton
stephen.walton@csun.edu

Mike Fitzpatrick wrote on Mar 21, 2000

> I think I did this:
> 
> % at now+2hours
> show.cl
> ^D
> 
> Looking at the at-generated script, there was a list of environment variables
> followed at the end by 'show.cl' on its own line.  If I did 'sh at-script'
> from the command line, the command ran and printed out the IRAF environment
> and exited.  But the version run by at still went into an infinite loop.  It
> did work to do:
> 
> % at now+2hours
> /usr/local/bin/cl.e < show.cl
> ^D
> 
> but that kind of defeats the purpose.

	I haven't quite figure out why this happens yet but it may have
something to do with the redirection of the stdin/stdout that's happening.
The same thing happens on a Sun system with a csh used to execute the
command so it's not strictly a Bourne shell problem.  In any case, using
an 'exec' command to start the script appears to work around it, e.g.

	% at now+2hours
	exec show.cl
	^D

This hasn't been tested on all platforms but seems to work under Linux at
least.

-Mike

Stephen Walton wrote on Mar 24, 2000

Mike Fitzpatrick wrote:

> The same thing happens on a Sun system with a csh used to execute the
> command so it's not strictly a Bourne shell problem.  In any case, using
> an 'exec' command to start the script appears to work around it, e.g.
> 
>         % at now+2hours
>         exec show.cl
>         ^D
> 
> This hasn't been tested on all platforms but seems to work under Linux at
> least.

I can also confirm it works on HP/UX 10.20.

--
Stephen Walton, Professor, Dept. of Physics & Astronomy, Cal State
Northridge
stephen.walton@csun.edu

Last post on Mar 24, 2000