This is a brief introduction to CL scripts, to show that they are not as difficult as it might seem at first sight, and that they might be useful from time to time, especially the terminal scripts.
In its simplest form, a CL script is a logical, ordered sequence of CL
commands. No variables or special syntax are used in this type of scripts.
In other words, instead of writing commands at the cl prompt,
they are written in a file and then executed.
Here is a list of some of my own (old) CL script files that I have used or am
using. Comments help understand what is going on, and sometimes also the output
of a task is recorded for future reference.
Usually a group of commands is brought to the IRAF terminal by cut-and-paste.
N.B: Modern browsers may not allow direct access to the link
below,
because
of security reasons. If so, open a new tab o window, and copy-and paste the links
below
in the new address box.
To make CL execute your procedure, do (assume your procedure is in
file procedure.cl):
cl> cl < procedure.cl
The "cl <" thing means that what is on the right-hand
side is given in input to CL.
Next step is to write a script which uses some of the CL language capabilities,
as strings, numerical variables, ifs and whiles, etc. We are still
far from writing a task-like script.
This kind of script often saves from repeating many times the same command,
just changing the value of one parameter or two each time.
Example: a user has a calibrated 2-D spectrum, and wants to dump each
spectral line on an ASCII file having the wavelength in the 1st column, the
pixel intensity in the 2nd. wspectext is the right
task; the problem is to execute it in turn for every line.
The script might be as follows:
# script to wspectext each spectral line in turn on a text file.
# change name of image and output file if necessary.
#
# use with: cl < wmacro.cl
# assign file names to string variables s1 and s2:
s1 = "ap96_"
s2 = "w0096.ms"
# start loop:
for (i=1; i <= 111; i+=1) {
j = i+4
s3 = s1//j
print (s3)
wspectext (s2//"[*,"//i//"]", s3, head-)
}
In this procedure, CL is used in the so-called program mode (or
compute mode), which takes advantage of the full syntax of CL as a
programming language, where, for instance, it can process strings and
variables.
The other mode of CL, with more limited capabilities but a simpler user
interface, is called command mode, and is the one generally used at
the cl> prompt. It minimizes the need for command
delimiters, quoted character strings, etc.
Here is a more complicate script to compute King models, and convolve them
with the PSF.
# procedure to create King models and convolve them with
# the PSF
# A oversampling factor of 9 (good for Rcore>=0.15)
# is used to properly compute pixel values.
#
# use as: Rcore=1.8 ; imname="King_180" ; suf="U" ; cl < king.cl
# (Rcore and imname must be already defined)
#
string expr, exprA, exprB, exprC
string imnameC, outf, psfim
real Tidterm, RcoS, Rtico, RtidS
set imtype = "fits"
# set variables
#
Rtico = 30 # set tidal radius = 30 * core radius
Tidterm = 1.0/sqrt(1+(Rtico*Rtico))
outf = imname//suf//".prof"
RcoS = 9.0*Rcore
RtidS = Rtico*RcoS # tidal radius
psfim = "psf.imh"
# compute King profile. The computed profile is oversampled
# 9 times (linearly), then is brought back to the original
# resolution by block-averaging
# King models must be set to 0 at R > Rtidal
#
# strings containing the matematical operations are defined, and then
# passed on to tasks imexpr and imcalc
exprA = "1.00+(((I-572.00)**2+(J-572.00)**2)/("//RcoS//"**2))"
exprB = "I*0.0+J*0.0+"//Tidterm
exprC = "(((I-572.00)**2+(J-572.00)**2) > "//RtidS**2//") ? 0.0 : a"
expr = "((1.0/sqrt(im1))-im2)**2"
imexpr(exprA,"King_A.fits",dims="1152,1152",intype="real",outtype="real")
imexpr(exprB,"King_B.fits",dims="1152,1152",intype="real",outtype="real")
imcalc("King_A.fits,King_B.fits","King_C.fits",expr)
imexpr(exprC,"King_D.fits","King_C.fits")
blkavg("King_D.fits",imname,9,9,option="average")
# normalize to total flux=1000.0
gstat(imname) # output in gstpar set
x = gstpar.sum/1000.0
imarith(imname,"/",x,imname)
# convolve with PSF (I-band, chip4)
# PSF must be normalized (sum=1)
stsdas.analysis.fourier
fconvolve(imname,psfim,imname//suf)
# remove temporary images
imdel King_A.fits,King_B.fits,King_C.fits,King_D.fits veri-
# output radial profile onto a file; sort it
pradprof(imname//suf,64.00,64.00,radius=20,center=no,list+,logx-,logy-, > outf)
sort(outf,column=1,numeric_sort=yes, > "sort.sort")
delete(outf,yes,verify=no)
rename("sort.sort",outf,field="all")
# end of script
To use this script, we should do:
cl < Rcore=1.8 ;
imname="King_180" ; suf="U" ; cl < king.cl
Description:
It is possible to write CL scripts that are similar in every aspect to
genuine IRAF tasks. Actually, a good number of native CL tasks (i.e. present
in the standard IRAF packages) are CL scripts themselves. Examples:
stsdas.analysis.gasp.regions - images.immatch.wcsmap -
stsdas.describe etc.
These new tasks have their own parameter set, share the piping and redirection
capabilities, might be run in background, etc.
Very simple example:
# DESCRIBE -- A shortcut task to see the "Description" section of a help #
# file. #
# #
# 8/91 Initial code by PAHodge and RAShaw #
# Modified for clarity (NC).
procedure example (taskname)
string taskname = "" {prompt = "Enter task name > "}
begin
string tasknm # defines tasknm as a string variable
tasknm = taskname # reassign taskname to tasknm
print ("\nDESCRIPTION for task: ", tasknm) # print 1-line header
help (tasknm, section="description") # print help
end
This IRAF task simply displays the "description" section of a help file.
Taskname is a required parameter, as is present in the task
definition. There are no hidden parameters.
Note that the taskname variable is reassigned to a new variable,
tasknm;
if they had used taskname in the following "print" and
"help" commands, IRAF would have prompted for taskname.
Another more complex example:
# script taken from the "arnica" package. Adapted to clarify various
# points (NC).
# Cleans bad pixels using bad pixel mask and 3x3 median smoothing
# CLEANED image has prefix b
#
procedure clean ( sfrm )
string sfrm { prompt="Frame name to clean" }
string smask = "arnica$badpix/bpf.fix.93jun" {prompt="Bad pixel mask"}
# Notice there is one required parameter (sfrm) and one hidden one (smask),
# which has a default value.
begin
string msk1, msk0, junk0, intermed, sf, mask
sf = sfrm
mask = smask
# Make temporary images. Names will be like this: imf+PID+letter, and will
# be placed in the directory defined by the variable tmp
intermed = mktemp ("tmp$imf")
msk0 = mktemp ("tmp$imf")
msk1 = mktemp ("tmp$imf")
junk0 = mktemp ("tmp$imf")
# Median filter to smooth out image; output on temp file "ntermed"
median ( sf, intermed, 3, 3 )
# Multiply smoothed image by mask
# Perform other mathematical operations, delete junk images, print output
# Notice how strings are concatenated.
imarith ( intermed, "*", mask, msk1 )
imarith ( sf, "*", mask, msk0 )
imarith ( sf, "-", msk0, junk0 )
imarith ( junk0, "+", msk1, "b"//sf )
imdel (junk0//","//msk0//","//msk1//","//intermed, ver-, >& "dev$null")
print (sf, ", ", "b"//sf)
end
A few comments to describe the above scripts:
To let IRAF know that these are new scripts, we do:
cl> task describe = describe.cl
cl> task clean = clean.cl
Magically, doing cl> epar clean or
cl> epar
describe will show the task parameters, which can be edited.
Now they are tasks like any other one.
if (! defpac ("proto"))
print ("Warning: package proto not loaded!")
bye
Struct variables:
A struct variable is a special one with regards to reading from files
using the "fscan" function.
Basically, there are two type of this things:
struct stru
fscan (list, s1, s2, stru)
will read the file associated to variable list, and assign the 1st string
encountered to s1, the 2nd to s2, the whole
rest of the line to variable stru. An example that contains the two structs:
procedure printfile (file_name)
string filename
struct *flist
begin
struct line
flist = filename
while (fscan(flist, line) != EOF)
print (line)
flist = ""
end
This procedure will read from file file_name (a required parameter)
and print every line in turn. flist is a list-directed struct,
line is
a simple struct. For some reasons I do not fully understand, the "struct *flist" definition
must go before the "begin" line.
It is recommended to always close the list-structured variable with flist
= "" to avoid that the associated file remain open by
mistake
(it will close if the end-of-file is encountered by fscan, but sometimes
an "if" jump might prevent fscan from reaching the file end).
More detailed information on how to write scripts, organize them in packages, write help files, etc. may be found in the Introductory User's Guide to IRAF scripts