aboutsummaryrefslogtreecommitdiff
path: root/noao/imred/quadred
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /noao/imred/quadred
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'noao/imred/quadred')
-rw-r--r--noao/imred/quadred/doc/package.hlp142
-rw-r--r--noao/imred/quadred/doc/qhistogram.hlp37
-rw-r--r--noao/imred/quadred/doc/qstatistics.hlp52
-rw-r--r--noao/imred/quadred/doc/quadformat.hlp392
-rw-r--r--noao/imred/quadred/doc/quadjoin.hlp43
-rw-r--r--noao/imred/quadred/doc/quadscale.hlp37
-rw-r--r--noao/imred/quadred/doc/quadsections.hlp81
-rw-r--r--noao/imred/quadred/doc/quadsplit.hlp49
-rw-r--r--noao/imred/quadred/mkpkg8
-rw-r--r--noao/imred/quadred/quadred.cl68
-rw-r--r--noao/imred/quadred/quadred.hd22
-rw-r--r--noao/imred/quadred/quadred.men61
-rw-r--r--noao/imred/quadred/quadred.par13
-rw-r--r--noao/imred/quadred/src/Revisions42
-rw-r--r--noao/imred/quadred/src/ccdproc/calimage.x367
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdcache.com10
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdcache.h10
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdcache.x381
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdcheck.x67
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdcmp.x23
-rw-r--r--noao/imred/quadred/src/ccdproc/ccddelete.x55
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdflag.x27
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdlog.x46
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdmean.x50
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdnscan.x38
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdproc.par43
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdproc.x106
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdred.h155
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdsection.x100
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdsubsets.x92
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdtypes.h14
-rw-r--r--noao/imred/quadred/src/ccdproc/ccdtypes.x72
-rw-r--r--noao/imred/quadred/src/ccdproc/cor.gx362
-rw-r--r--noao/imred/quadred/src/ccdproc/corinput.gx220
-rw-r--r--noao/imred/quadred/src/ccdproc/doc/ccdproc.hlp778
-rw-r--r--noao/imred/quadred/src/ccdproc/doproc.x29
-rw-r--r--noao/imred/quadred/src/ccdproc/generic/ccdred.h155
-rw-r--r--noao/imred/quadred/src/ccdproc/generic/cor.x695
-rw-r--r--noao/imred/quadred/src/ccdproc/generic/corinput.x436
-rw-r--r--noao/imred/quadred/src/ccdproc/generic/mkpkg12
-rw-r--r--noao/imred/quadred/src/ccdproc/generic/proc.x678
-rw-r--r--noao/imred/quadred/src/ccdproc/hdrmap.com4
-rw-r--r--noao/imred/quadred/src/ccdproc/hdrmap.x544
-rw-r--r--noao/imred/quadred/src/ccdproc/mkpkg78
-rw-r--r--noao/imred/quadred/src/ccdproc/proc.gx379
-rw-r--r--noao/imred/quadred/src/ccdproc/readcor.x138
-rw-r--r--noao/imred/quadred/src/ccdproc/scancor.x340
-rw-r--r--noao/imred/quadred/src/ccdproc/setdark.x155
-rw-r--r--noao/imred/quadred/src/ccdproc/setfixpix.x181
-rw-r--r--noao/imred/quadred/src/ccdproc/setflat.x146
-rw-r--r--noao/imred/quadred/src/ccdproc/setfringe.x123
-rw-r--r--noao/imred/quadred/src/ccdproc/setheader.x76
-rw-r--r--noao/imred/quadred/src/ccdproc/setillum.x132
-rw-r--r--noao/imred/quadred/src/ccdproc/setinput.x48
-rw-r--r--noao/imred/quadred/src/ccdproc/setinteract.x31
-rw-r--r--noao/imred/quadred/src/ccdproc/setoutput.x51
-rw-r--r--noao/imred/quadred/src/ccdproc/setoverscan.x344
-rw-r--r--noao/imred/quadred/src/ccdproc/setproc.x80
-rw-r--r--noao/imred/quadred/src/ccdproc/setsections.x327
-rw-r--r--noao/imred/quadred/src/ccdproc/settrim.x115
-rw-r--r--noao/imred/quadred/src/ccdproc/setzero.x141
-rw-r--r--noao/imred/quadred/src/ccdproc/t_ccdproc.x155
-rw-r--r--noao/imred/quadred/src/ccdproc/timelog.x29
-rw-r--r--noao/imred/quadred/src/ccdproc/x_quadred.x1
-rw-r--r--noao/imred/quadred/src/mkpkg4
-rw-r--r--noao/imred/quadred/src/quad/Revisions92
-rw-r--r--noao/imred/quadred/src/quad/ccd.dat27
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/cfccd_both.dat27
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f1.dat27
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f2.dat27
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/csccd.dat23
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/echccd.dat23
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/instruments.men9
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/nfccd.dat23
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/pfccd_both.dat27
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f1.dat27
-rw-r--r--noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f2.dat27
-rw-r--r--noao/imred/quadred/src/quad/ccddelete.par1
-rw-r--r--noao/imred/quadred/src/quad/ccddelete.x65
-rw-r--r--noao/imred/quadred/src/quad/ccdgetparam.par2
-rw-r--r--noao/imred/quadred/src/quad/ccdgetparam.x48
-rw-r--r--noao/imred/quadred/src/quad/ccdlog.x42
-rw-r--r--noao/imred/quadred/src/quad/ccdprcselect.par4
-rw-r--r--noao/imred/quadred/src/quad/ccdprcselect.x90
-rw-r--r--noao/imred/quadred/src/quad/ccdproc.par43
-rw-r--r--noao/imred/quadred/src/quad/ccdsection.par1
-rw-r--r--noao/imred/quadred/src/quad/ccdsection.x119
-rw-r--r--noao/imred/quadred/src/quad/ccdssselect.par4
-rw-r--r--noao/imred/quadred/src/quad/ccdssselect.x73
-rw-r--r--noao/imred/quadred/src/quad/ccdsubsets.x92
-rw-r--r--noao/imred/quadred/src/quad/ccdtypes.h14
-rw-r--r--noao/imred/quadred/src/quad/ccdtypes.x72
-rw-r--r--noao/imred/quadred/src/quad/detpars.par6
-rw-r--r--noao/imred/quadred/src/quad/doc/Geometry.fig91
-rw-r--r--noao/imred/quadred/src/quad/doc/badpiximage.hlp51
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdgeometry.hlp70
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdgroups.hlp163
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdhedit.hlp108
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdinst.hlp389
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdlist.hlp133
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdproc.hlp720
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdred.hlp98
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdred.ms787
-rw-r--r--noao/imred/quadred/src/quad/doc/ccdtypes.hlp124
-rw-r--r--noao/imred/quadred/src/quad/doc/combine.hlp1030
-rw-r--r--noao/imred/quadred/src/quad/doc/contents.ms34
-rw-r--r--noao/imred/quadred/src/quad/doc/cosmicrays.hlp220
-rw-r--r--noao/imred/quadred/src/quad/doc/darkcombine.hlp125
-rw-r--r--noao/imred/quadred/src/quad/doc/flatcombine.hlp139
-rw-r--r--noao/imred/quadred/src/quad/doc/flatfields.hlp177
-rw-r--r--noao/imred/quadred/src/quad/doc/guide.hlp715
-rw-r--r--noao/imred/quadred/src/quad/doc/guide.ms794
-rw-r--r--noao/imred/quadred/src/quad/doc/instruments.hlp248
-rw-r--r--noao/imred/quadred/src/quad/doc/mkfringecor.hlp90
-rw-r--r--noao/imred/quadred/src/quad/doc/mkillumcor.hlp92
-rw-r--r--noao/imred/quadred/src/quad/doc/mkillumflat.hlp101
-rw-r--r--noao/imred/quadred/src/quad/doc/mkskycor.hlp103
-rw-r--r--noao/imred/quadred/src/quad/doc/mkskyflat.hlp111
-rw-r--r--noao/imred/quadred/src/quad/doc/quad.hlp121
-rw-r--r--noao/imred/quadred/src/quad/doc/quadman.hlp1330
-rw-r--r--noao/imred/quadred/src/quad/doc/quadproc.hlp672
-rw-r--r--noao/imred/quadred/src/quad/doc/quadreadout.hlp19
-rw-r--r--noao/imred/quadred/src/quad/doc/setinstrument.hlp97
-rw-r--r--noao/imred/quadred/src/quad/doc/subsets.hlp97
-rw-r--r--noao/imred/quadred/src/quad/doc/zerocombine.hlp127
-rw-r--r--noao/imred/quadred/src/quad/gainmeasure.par6
-rw-r--r--noao/imred/quadred/src/quad/gainmeasure.x170
-rw-r--r--noao/imred/quadred/src/quad/hdrmap.com4
-rw-r--r--noao/imred/quadred/src/quad/hdrmap.x544
-rw-r--r--noao/imred/quadred/src/quad/irlincor.par12
-rw-r--r--noao/imred/quadred/src/quad/mkpkg56
-rw-r--r--noao/imred/quadred/src/quad/new.par8
-rw-r--r--noao/imred/quadred/src/quad/old.par2
-rw-r--r--noao/imred/quadred/src/quad/qccdproc.par43
-rw-r--r--noao/imred/quadred/src/quad/qdarkcombine.cl48
-rw-r--r--noao/imred/quadred/src/quad/qflatcombine.cl49
-rw-r--r--noao/imred/quadred/src/quad/qghdr2.x216
-rw-r--r--noao/imred/quadred/src/quad/qguser.x126
-rw-r--r--noao/imred/quadred/src/quad/qhistogram.cl58
-rw-r--r--noao/imred/quadred/src/quad/qhistogram.par17
-rw-r--r--noao/imred/quadred/src/quad/qnoproc.cl77
-rw-r--r--noao/imred/quadred/src/quad/qnoproc.par15
-rw-r--r--noao/imred/quadred/src/quad/qpcalimage.par3
-rw-r--r--noao/imred/quadred/src/quad/qpcalimage.x525
-rw-r--r--noao/imred/quadred/src/quad/qproc.cl109
-rw-r--r--noao/imred/quadred/src/quad/qproc.par15
-rw-r--r--noao/imred/quadred/src/quad/qpselect.par4
-rw-r--r--noao/imred/quadred/src/quad/qpselect.x108
-rw-r--r--noao/imred/quadred/src/quad/qsplit.gx97
-rw-r--r--noao/imred/quadred/src/quad/qsplitd.x97
-rw-r--r--noao/imred/quadred/src/quad/qspliti.x97
-rw-r--r--noao/imred/quadred/src/quad/qsplitl.x97
-rw-r--r--noao/imred/quadred/src/quad/qsplitr.x97
-rw-r--r--noao/imred/quadred/src/quad/qsplits.x97
-rw-r--r--noao/imred/quadred/src/quad/qstatistics.cl19
-rw-r--r--noao/imred/quadred/src/quad/qstatistics.par7
-rw-r--r--noao/imred/quadred/src/quad/quad.cl64
-rw-r--r--noao/imred/quadred/src/quad/quad.hd33
-rw-r--r--noao/imred/quadred/src/quad/quad.men36
-rw-r--r--noao/imred/quadred/src/quad/quad.par12
-rw-r--r--noao/imred/quadred/src/quad/quadalloc.x165
-rw-r--r--noao/imred/quadred/src/quad/quaddelete.x39
-rw-r--r--noao/imred/quadred/src/quad/quadgeom.h99
-rw-r--r--noao/imred/quadred/src/quad/quadgeom.x304
-rw-r--r--noao/imred/quadred/src/quad/quadgeomred.x165
-rw-r--r--noao/imred/quadred/src/quad/quadjoin.par4
-rw-r--r--noao/imred/quadred/src/quad/quadjoin.x638
-rw-r--r--noao/imred/quadred/src/quad/quadmap.x297
-rw-r--r--noao/imred/quadred/src/quad/quadmerge.x122
-rw-r--r--noao/imred/quadred/src/quad/quadproc.cl173
-rw-r--r--noao/imred/quadred/src/quad/quadproc.par42
-rw-r--r--noao/imred/quadred/src/quad/quadscale.par7
-rw-r--r--noao/imred/quadred/src/quad/quadscale.x159
-rw-r--r--noao/imred/quadred/src/quad/quadsections.par14
-rw-r--r--noao/imred/quadred/src/quad/quadsections.x447
-rw-r--r--noao/imred/quadred/src/quad/quadsplit.par9
-rw-r--r--noao/imred/quadred/src/quad/quadsplit.x115
-rw-r--r--noao/imred/quadred/src/quad/quadtest/artobs.cl68
-rw-r--r--noao/imred/quadred/src/quad/quadtest/artobs.par5
-rw-r--r--noao/imred/quadred/src/quad/quadtest/ccdpars.par29
-rw-r--r--noao/imred/quadred/src/quad/quadtest/logfile1
-rw-r--r--noao/imred/quadred/src/quad/quadtest/mkamp.cl166
-rw-r--r--noao/imred/quadred/src/quad/quadtest/mkimage.par10
-rw-r--r--noao/imred/quadred/src/quad/quadtest/mkquad.cl222
-rw-r--r--noao/imred/quadred/src/quad/quadtest/mkquad.par4
-rw-r--r--noao/imred/quadred/src/quad/quadtest/quadtest.cl14
-rw-r--r--noao/imred/quadred/src/quad/quadtest/quadtest.par20
-rw-r--r--noao/imred/quadred/src/quad/qzerocombine.cl48
-rw-r--r--noao/imred/quadred/src/quad/setinstrument.cl58
-rw-r--r--noao/imred/quadred/src/quad/test.x71
-rw-r--r--noao/imred/quadred/src/quad/timelog.x29
-rw-r--r--noao/imred/quadred/src/quad/x_quad.x14
192 files changed, 26427 insertions, 0 deletions
diff --git a/noao/imred/quadred/doc/package.hlp b/noao/imred/quadred/doc/package.hlp
new file mode 100644
index 00000000..ffea9446
--- /dev/null
+++ b/noao/imred/quadred/doc/package.hlp
@@ -0,0 +1,142 @@
+.help package Sep93 quadred
+.ih
+NAME
+quadred -- CCD reductions of images in multi-amp readout format
+.ih
+SYNOPSIS
+This package is a varient of \fBccdred\fR that operates on a
+multi-amplifier data format in which the various amplifier readouts are
+recorded in sections of a regular two-dimensional image. The CTIO Arcon
+dual or quad readout data is an example of this format. See help on
+\fBquadformat\fR for details. Most tasks are the same as in the
+\fBccdred\fR package. The difference is the version of \fBccdproc\fR in
+this package also works on the multi-amp format. An alternative to using
+this version of \fBccdproc\fR is \fBquadproc\fR and the alternate
+calibration combining task based on this task.
+.ih
+USAGE
+quadred
+.ih
+PARAMETERS
+The following are "package" parameters. This means that they apply to
+many of the tasks in this package.
+
+.ls pixeltype = "real real"
+Output pixel datatype and calculation datatype. When images are processed
+or created the output pixel datatype is determined by this parameter.
+The allowed types are "short" for short integer, and "real" for real
+floating point. The calculation datatypes are also short and real with a
+default of real if none is specified.
+.le
+.ls verbose = no
+Print log information to the standard output?
+.le
+.ls logfile = "logfile"
+Text log file. If no filename is specified then no log file is kept.
+.le
+.ls plotfile = ""
+Log metacode plot file for the overscan bias vector fits. If
+no filename is specified then no metacode plot file is kept.
+.le
+.ls backup = ""
+Backup prefix for backup images. If no prefix is specified then no backup
+images are kept when processing. If specified then the backup image
+has the specified prefix.
+.le
+.ls instrument = ""
+CCD instrument translation file. This is usually set with \fBsetinstrument\fR.
+.le
+.ls ssfile = "subsets"
+Subset translation file used to define the subset identifier. See
+\fBsubsets\fR for more.
+.le
+.ls graphics = "stdgraph"
+Interactive graphics output device when fitting the overscan bias vector.
+.le
+.ls cursor = ""
+Graphics cursor input. The default is the standard graphics cursor.
+.le
+.ls version = "Version 1.0 - August 22, 2001"
+Package version.
+.le
+.ih
+DESCRIPTION
+The \fBquadred\fR package contains all basic tasks necessary for the
+reduction of CCD data in single image format. This includes both single
+amplifier readout data and multi-amplifier data stored as sections in a
+single two-dimensional image. One example of this type of multi-amplifier
+data is the CTIO Arcon "dual" or "quad" readout format. The format is
+described in the help topic \fBquadformat\fR. This package is a
+combination of two earlier packages called \fBxccdred\fR and
+\fBared.quad\fR, each of which are variants of the original \fBccdred\fR
+package.
+
+The raw data contains overscan/prescan regions in the image. For multi-amp
+data there are multiple overscan/prescan regions. The first steps in
+processing the data is to use the overscan/prescan regions to determine
+the amplifier bias, subtract this bias, and trim the regions out of
+the data. Once this is done the data are just simple images. It is
+the special step of dealing with the overscan/prescan regions with
+the multi-amp format that is different from the standard \fBccdred\fR
+package.
+
+Two methods are provided for dealing with the special format. One is a
+special version of \fBccdproc\fR which processes the sections directly. If
+one uses this task then the reduction steps appear identical to using the
+\fBccdred\fR package. The other method is to use the tasks \fBquadproc\fR,
+\fBqzerocombine\fR, \fBqdarkcombine\fR, and \fBqflatcombine\fR. The latter
+calibration combining tasks are the same as the standard versions except
+they use \fBquadproc\fR instead of \fBccdproc\fR. The task \fBquadproc\fR
+operates internally by splitting the multiple regions into temporary single
+amplifier images, processing them with \fBccdproc\fR, and then joining the
+pieces back together.
+
+The recommended method is to use \fBccdproc\fR. However, the \fBquadproc\fR
+related tasks have a history of usage for CTIO data and so may also be
+used.
+
+The \fBquadred\fR package itself has several parameters which are
+common to many of the tasks in the package. When images are processed or
+new image are created the output pixel datatype is that specified by the
+parameter \fBpixeltype\fR. Note that CCD processing replaces the original
+image by the processed image so the pixel type of the CCD images may change
+during processing. It is unlikely that real images will be processed to
+short images but the reverse is quite likely. Processing images from short
+to real pixel datatypes will generally increase the amount of disk space
+required (a factor of 2 on most computers).
+
+The tasks produce log output which may be printed on the standard
+output (the terminal unless redirected) and appended to a file. The
+parameter \fIverbose\fR determines whether processing information
+is printed. This may be desirable initially, but when using background
+jobs the verbose output should be turned off. The user may look at
+the end of the log file (for example with \fBtail\fR) to determine
+the status of the processing.
+
+The package was designed to work with data from many different observatories
+and instruments. In order to accomplish this an instrument translation
+file is used to define a mapping between the package parameters and
+the particular image header format. The instrument translation file
+is specified to the package by the parameter \fIinstrument\fR. This
+parameter is generally set by the task \fBsetinstrument\fR. The other
+file used is a subset file. This is generally created and maintained
+by the package and the user need not do anything. For more sophisticated
+users see \fBinstruments\fR and \fBsubsets\fR.
+
+The package has very little graphics output. The exception is the overscan
+bias subtraction. The bias vector is logged in the metacode plot file if
+given. The plot file may be examined with the tasks in the \fBplot\fR
+package such as \fBgkimosaic\fR. When interactively fitting the overscan
+vector the graphics input and output devices must be specified. The
+defaults should apply in most cases.
+
+Because processing replaces the input image by the processed image it may
+be desired to save the original image. This may be done by specifying a
+backup prefix with the parameter \fIbackup\fR. For example, if the prefix
+is "orig" and the image is "ccd001", the backup image will be
+"origccd001". The prefix may be a directory but if so it must end with '/'
+or '$' (for logical directories) and the directory must already exist.
+.ih
+SEE ALSO
+quadformat, mscred
+.endhelp
diff --git a/noao/imred/quadred/doc/qhistogram.hlp b/noao/imred/quadred/doc/qhistogram.hlp
new file mode 100644
index 00000000..a34e412c
--- /dev/null
+++ b/noao/imred/quadred/doc/qhistogram.hlp
@@ -0,0 +1,37 @@
+.help qhistogram Aug01 noao.imred.quadred
+.ih
+NAME
+qhistogram -- Compute and print histogram for multi-amp data
+.ih
+USAGE
+qhistogram images
+.ih
+PARAMETERS
+.ls images
+List of image names in \fBquadformat\fR.
+.le
+.ls window = "datasec" (datasec|trimsec|biassec)
+Type of section to use for histogram. The choices are "datasec" for the
+amplifier section which includes the bias if any is present, "trimsec" for
+the trim section, and "biassec" for the bias section.
+.le
+
+The remaining parameters come from the \fBimhistogram\fR task.
+.ih
+DESCRIPTION
+This script tasks uses the \fBquadsections\fR task to break the
+\fBquadformat\fR data into separate sections and runs the \fBimhistogram\fR
+task on the sections. The graphics is collected onto a single page.
+.ih
+EXAMPLES
+
+1. To graph the histograms (default behavior).
+
+.nf
+ qu> qhist quad0072
+ [graph appears]
+.fi
+.ih
+SEE ALSO
+quadformat, quadsections, imhistogram
+.endhelp
diff --git a/noao/imred/quadred/doc/qstatistics.hlp b/noao/imred/quadred/doc/qstatistics.hlp
new file mode 100644
index 00000000..222ae778
--- /dev/null
+++ b/noao/imred/quadred/doc/qstatistics.hlp
@@ -0,0 +1,52 @@
+.help qstatistics Aug01 noao.imred.quadred
+.ih
+NAME
+qstatistics -- Compute and print statistics for multi-amp data
+.ih
+USAGE
+qstatistics images
+.ih
+PARAMETERS
+.ls images
+List of image names in \fBquadformat\fR.
+.le
+.ls window = "datasec" (datasec|trimsec|biassec)
+Type of section to output. The choices are "datasec" for the amplifier
+section which includes the bias if any is present, "trimsec" for the trim
+section, and "biassec" for the bias section.
+.le
+
+The remaining parameters come from the \fBimstatistics\fR task.
+.ih
+DESCRIPTION
+This script tasks uses the \fBquadsections\fR task to break the
+\fBquadformat\fR data into separate sections and runs the \fBimstatistics\fR
+task on the sections.
+.ih
+EXAMPLES
+
+1. To compute the mean and stddev of the data section.
+
+.nf
+ qu> qstat quad0072 fields=image,mean,stddev
+ # IMAGE MEAN STDDEV
+ quad0072[1:1034,1:1024] 5537. 2647.
+ quad0072[1163:2196,1:1024] 6210. 5439.
+ quad0072[1:1034,1025:2048] 5364. 2535.
+ quad0072[1163:2196,1025:2048] 5862. 1327.
+.fi
+
+2. To compute the mean and stdev of the bias section.
+
+.nf
+ qu> qstat quad0072 fields=image,mean,stddev window=biassec
+ # IMAGE MEAN STDDEV
+ quad0072[1045:1098,1:1024] 713. 1.272
+ quad0072[1099:1152,1:1024] 516.2 1.425
+ quad0072[1045:1098,1025:2048] 554.3 1.347
+ quad0072[1099:1152,1025:2048] 530.3 1.377
+.fi
+.ih
+SEE ALSO
+quadformat, quadsections, imstatistics
+.endhelp
diff --git a/noao/imred/quadred/doc/quadformat.hlp b/noao/imred/quadred/doc/quadformat.hlp
new file mode 100644
index 00000000..eb5fbfbd
--- /dev/null
+++ b/noao/imred/quadred/doc/quadformat.hlp
@@ -0,0 +1,392 @@
+.help quadformat Aug01 imred.quadred
+.ih
+NAME
+quadformat - Description of the special multi-amplifier CCD format
+.ih
+DESCRIPTION
+CCDs may be readout from multiple amplifiers at the same time to increase
+the readout speed. This produces multiple images of rectangular regions in
+the full CCD exposure. The amplifier readout images may be recorded in
+various ways. One way is as extensions in a multiextension FITS file.
+This type of format can be reduced using the MSCRED package.
+
+Another way is to paste the regions into a single two-dimensional image.
+This, along with specific keywords to describe the locations of the
+regions, constitutes the \fIquadformat\fR format described here and used by the
+QUADRED package. The term "quad" originates from the possibility of using
+four amplifiers in quadrants but the format also includes any other
+number of amplifiers.
+
+It is important to realize that this is a special format only as long as
+the overscan or prescan data is included in the image data. Once this
+information is used and removed as part of the processing the resulting
+image can be treated in the same way as a single amplifier CCD image.
+However, the image can still contain the format keywords allowing the
+regions from the different amplifiers to be identified and extracted as
+needed.
+
+The \fIquadformat\fR consists of a single 2D image for a single CCD
+exposure. The image storage format may be any standard image type such
+as imh or fits. Within the image are regions containing the CCD
+pixel data and regions containing overscan or prescan, which we will
+call bias regions, for each amplifier. The \fIquadformat\fR requires
+the bias regions to be attached to the CCD regions such that a single
+rectangular region contains both.
+
+Generally the rectangular regions are of equal size in order to sequence
+the amplifiers simultaneously. However, it is possible for the regions
+to be unequal in cases of subregion readouts with certain CCD controllers.
+The figure below illustrates a "dual" and "quad" readout with equal
+size regions.
+
+.nf
+ +-----+-+-+-----+ +-----+-+-+-----+ +----------+-+
+ | D !B|B! D | | D !B|B! D | | D !B|
+ | 3 !3|4! 4 | | 1 !1|2! 2 | | 2 !2|
+ | ! | ! | | ! | ! | | ! |
+ +-----+-+-+-----+ | ! | ! | +----------+-+
+ | D !B|B! D | | ! | ! | | D !B|
+ | 1 !1|2! 2 | | ! | ! | | 1 !1|
+ | ! | ! | | ! | ! | | ! |
+ +-----+-+-+-----+ +-----+-+-+-----+ +----------+-+
+.fi
+
+The areas labeled D are the data sections and those labeled B are the
+bias sections. The data and biases are match by the amplifier labels
+which are 1-4 in these examples. The combination of the data and
+bias sections are called the amplifier sections.
+
+The regions are identified in the header by various keywords. There is
+a header translation facility which allows for alternative keyword names.
+Below we describe the default keyword names in the absence of a translation.
+The number of regions and the amplifier labels are described by the
+string keyword AMPLIST. The value is a string of space separated
+amplifier labels. For the above four amplifier example it would be
+
+.nf
+ AMPLIST = '1 2 3 4'
+.fi
+
+For CTIO data the labels are '11 12 21 22'. Note that the labels
+are appended to rootnames so they should be relatively short.
+
+The amplifier labels are appended to various root names. The important
+ones define "section" keywords. The values are image sections that
+describe regions in an raster such as the image or the CCD. The format
+of a section follows the standard IRAF notation "[c1:c2,l1:l2]" where
+c1 and c2 are inclusive column endpoints and l1 and l2 are inclusive
+line endpoints.
+
+The various sections are defined below. The labels again show the default
+untranslated keyword roots.
+
+.ls ASEC
+The section of the image containing the amplifier readout. This is the
+combination of the data and bias regions as shown in the figures.
+.le
+.ls DSEC
+The section of the image containing the actual CCD data exclusive of
+bias data. In the figures these are the D regions.
+.le
+.ls BSEC
+The section of the image containing the bias data. In the figures these
+are the B regions.
+.le
+.ls TSEC
+The second of the image containing the useful CCD data. This defines
+a "trimming" area and lies within the data section. It may also be
+the same as the data region. During trimming the final image will only
+include the regions in the trim sections. Note that it generally does
+not make sense to trim between amplifier regions but does make sense to
+trim regions at the edges of the CCD.
+.le
+.ls CSEC
+The section of the CCD corresponding to the data section in the image.
+The CCD is considered an ideal raster (without bias regions) and a
+section corresponds to the pixels in the CCD. The CCD section must be
+the same size as the data section. It is the CCD sections that define
+how the amplifiers will be pieced together to form a single image
+after trimming the bias region.
+.le
+
+There may be other keyword root names for things such as gains which
+have the amplifier labels appended. However, none of these are used
+by the current software. Example image headers are given
+in the EXAMPLES section.
+
+There is a limitation in the current software that the regions be recorded
+without horizontal or vertical flips. In other words, where amplifiers
+from opposite corners are used some of them must be flipped by the
+data acquisition system before recording then in this \fBquadformat\fR.
+
+.ih
+EXAMPLES
+
+1. The following is an example of a full 2048x2048 CCD readout with
+four amplifiers at CTIO.
+
+.nf
+qu> imhad quad0020
+quad0020[2196,2048][ushort]: IC 1257 5290 180s
+No bad pixels, min=435., max=61973.
+Line storage mode, physdim [2304,2048], length of user area 3079 s.u.
+Created Thu 08:35:57 23-Aug-2001, Last modified Thu 08:35:57 23-Aug-2001
+Pixel file "HDR$pixels/quad0020.pix" [ok]
+'KPNO-IRAF' /
+'06-07-99' /
+IRAF-MAX= 6.197300E4 / DATA MAX
+IRAF-MIN= 4.350000E2 / DATA MIN
+IRAF-BPX= 16 / DATA BITS/PIXEL
+IRAFTYPE= 'USHORT ' / PIXEL TYPE
+OPICNUM = 123 / Original picture number
+HDR_REV = '2.000 13Feb96 (add mode and group to hdrs)' /
+IMAGETYP= 'OBJECT ' / Type of picture (object, dark, etc.)
+DETECTOR= 'Site2K_6' / Detector (CCD type, photon counter, etc.)
+PREFLASH= 0.000000 / Preflash time in secs
+CCDSUM = '1 1 ' / On chip summation (X,Y)
+DATE-OBS= '07/07/99' / Date (dd/mm/yy) of observation
+UTSHUT = '01:14:40.0' / UT of shutter open
+UT = ' 1:14:41.50' / UT of TCS coords
+OBSERVAT= 'CTIO ' / Origin of data
+TELESCOP= 'CTIO 1.5 meter telescope' / Specific system
+NAMPSYX = '2 2 ' / Num amps in y & x (eg. '2 2'=quad)
+AMPLIST = '11 21 12 22' / Readout order in y,x
+ASEC11 = '[1:1098,1:1024]' / Section read with Amp11
+CSEC11 = '[1:1034,1:1024]' / Section in full CCD for DSEC11
+DSEC11 = '[1:1034,1:1024]' / Image area in raw frame for Amp11
+TSEC11 = '[11:1034,1:1024]' / Trim section definition for Amp11
+BSEC11 = '[1045:1098,1:1024]' / Bias section definition for Amp11
+BSEC12 = '[1099:1152,1:1024]' / Bias section definition for Amp12
+ASEC12 = '[1099:2196,1:1024]' / Section read with Amp12
+CSEC12 = '[1035:2068,1:1024]' / Section in full CCD for DSEC12
+DSEC12 = '[1163:2196,1:1024]' / Image area in raw frame for Amp12
+TSEC12 = '[1163:2186,1:1024]' / Trim section definition for Amp12
+ASEC21 = '[1:1098,1025:2048]' / Section read with Amp21
+CSEC21 = '[1:1034,1025:2048]' / Section in full CCD for DSEC21
+DSEC21 = '[1:1034,1025:2048]' / Image area in raw frame for Amp21
+TSEC21 = '[11:1034,1025:2048]' / Trim section definition for Amp21
+BSEC21 = '[1045:1098,1025:2048]' / Bias section definition for Amp21
+BSEC22 = '[1099:1152,1025:2048]' / Bias section definition for Amp22
+ASEC22 = '[1099:2196,1025:2048]' / Section read with Amp22
+CSEC22 = '[1035:2068,1025:2048]' / Section in full CCD for DSEC22
+DSEC22 = '[1163:2196,1025:2048]' / Image area in raw frame for Amp22
+TSEC22 = '[1163:2186,1025:2048]' / Trim section definition for Amp22
+WAVEFILE= 'Obs Tue Jul 6 20:11:59 1999' /
+NOTE = 'WARNING: Lower amps reaching full well before ADCs saturate' /
+WAVEMODE= 'MPP OverlapXmit EarlyReset' / Waveform mode switches on
+GTRON22 = 4.100 / (e-) predicted read noise, upper right
+GTRON21 = 3.900 / (e-) predicted read noise, upper left
+GTRON12 = 4.200 / (e-) predicted read noise, lower right
+GTRON11 = 4.200 / (e-) predicted read noise, lower left
+GTGAIN22= 2.800 / (e-/ADU), predicted gain, upper right
+GTGAIN21= 3.100 / (e-/ADU) predicted gain, upper left
+GTGAIN12= 2.900 / (e-/ADU) predicted gain, lower right
+GTGAIN11= 3.200 / (e-/ADU) predicted gain, lower left
+GTINDEX = 2 / Gain selection (index into Gain Table)
+PIXELT = 29520 / (ns) unbinned pixel read time
+DCS_TIME= 7000 / (ns) Double Correlated Sample time
+RA = '17:27:10.82' / right ascension (telescope)
+DEC = '-7:06:35.40' / declination (telescope)
+EPOCH = 2000.0 / epoch of RA & DEC
+ZD = 35.9 / zenith distance (degrees)
+HA = '-01:57:23.7' / hour angle (H:M:S)
+ST = '15:29:46.00' / sidereal time
+AIRMASS = 1.234 / airmass
+EXPTIME = 180.000 / Exposure time in secs
+DARKTIME= 181.309 / Total elapsed time in secs
+OBSERVER= 'Jacoby' / Observers
+PROPID = '92' / Proposal Id
+COMMENT Globular PNe
+TELID = 'ct60' / CTIO 1.5-m Telescope
+ARCONVER= '17Oct97ver7_22' / Arcon software version
+COMMENT INSTRUMENT PARAMETERS
+INSTRUME= 'cfccd' / cassegrain direct imager
+FILTER1 = 'dia' / Filter in wheel one
+FNAME1 = 'diaphragm' / Full name of filter in wheel1
+FILTER2 = 'ocon' / Filter in wheel two
+FNAME2 = 'O cont' / Full name of filter in wheel2
+FILTERS = 'dia ocon' / Filter positions
+TELFOCUS= 57550 / Telescope focus
+XPIXSIZE= 0.432 / Pixel size in X (arcsec/pix)
+YPIXSIZE= 0.432 / Pixel size in Y (arcsec/pix)
+RECID = 'ct60.990707.011817' / NOAO Archive record ID
+.fi
+
+2. The following is a more complex readout of a region where the
+full 2Kx2K CCD is not readout and where even the regions are not the
+same size.
+
+.nf
+qu> imhead quad0013
+quad0013[1686,1538][ushort]: R sky flat 7s
+No bad pixels, min=393., max=65535.
+Line storage mode, physdim [1792,1538], length of user area 3079 s.u.
+Created Thu 08:34:00 23-Aug-2001, Last modified Thu 08:34:00 23-Aug-2001
+Pixel file "HDR$pixels/quad0013.pix" [ok]
+'KPNO-IRAF' /
+'06-07-99' /
+IRAF-MAX= 6.553500E4 / DATA MAX
+IRAF-MIN= 3.930000E2 / DATA MIN
+IRAF-BPX= 16 / DATA BITS/PIXEL
+IRAFTYPE= 'USHORT ' / PIXEL TYPE
+OPICNUM = 15 / Original picture number
+HDR_REV = '2.000 13Feb96 (add mode and group to hdrs)' /
+IMAGETYP= 'SKY FLAT' / Type of picture (object, dark, etc.)
+DETECTOR= 'Site2K_6' / Detector (CCD type, photon counter, etc.)
+PREFLASH= 0.000000 / Preflash time in secs
+CCDSUM = '1 1 ' / On chip summation (X,Y)
+DATE-OBS= '06/07/99' / Date (dd/mm/yy) of observation
+UTSHUT = '22:25:22.0' / UT of shutter open
+UT = '22:25:34.00' / UT of TCS coords
+OBSERVAT= 'CTIO ' / Origin of data
+TELESCOP= 'CTIO 1.5 meter telescope' / Specific system
+NAMPSYX = '2 2 ' / Num amps in y & x (eg. '2 2'=quad)
+AMPLIST = '11 21 12 22' / Readout order in y,x
+ASEC11 = '[1:843,1:769]' / Section read with Amp11
+CSEC11 = '[256:1034,256:1024]' / Section in full CCD for DSEC11
+DSEC11 = '[1:779,1:769]' / Image area in raw frame for Amp11
+TSEC11 = '[11:779,1:769]' / Trim section definition for Amp11
+BSEC11 = '[790:843,1:769]' / Bias section definition for Amp11
+BSEC12 = '[844:897,1:769]' / Bias section definition for Amp12
+ASEC12 = '[844:1686,1:769]' / Section read with Amp12
+CSEC12 = '[1035:1813,256:1024]' / Section in full CCD for DSEC12
+DSEC12 = '[908:1686,1:769]' / Image area in raw frame for Amp12
+TSEC12 = '[908:1418,1:769]' / Trim section definition for Amp12
+ASEC21 = '[1:843,770:1538]' / Section read with Amp21
+CSEC21 = '[256:1034,1025:1793]' / Section in full CCD for DSEC21
+DSEC21 = '[1:779,770:1538]' / Image area in raw frame for Amp21
+TSEC21 = '[11:779,770:1280]' / Trim section definition for Amp21
+BSEC21 = '[790:843,770:1538]' / Bias section definition for Amp21
+BSEC22 = '[844:897,770:1538]' / Bias section definition for Amp22
+ASEC22 = '[844:1686,770:1538]' / Section read with Amp22
+CSEC22 = '[1035:1813,1025:1793]' / Section in full CCD for DSEC22
+DSEC22 = '[908:1686,770:1538]' / Image area in raw frame for Amp22
+TSEC22 = '[908:1418,770:1280]' / Trim section definition for Amp22
+WAVEFILE= 'Obs Tue Jul 6 18:07:56 1999' /
+NOTE = 'WARNING: Lower amps reaching full well before ADCs saturate' /
+WAVEMODE= 'MPP OverlapXmit EarlyReset' / Waveform mode switches on
+GTRON22 = 4.100 / (e-) predicted read noise, upper right
+GTRON21 = 3.900 / (e-) predicted read noise, upper left
+GTRON12 = 4.200 / (e-) predicted read noise, lower right
+GTRON11 = 4.200 / (e-) predicted read noise, lower left
+GTGAIN22= 2.800 / (e-/ADU), predicted gain, upper right
+GTGAIN21= 3.100 / (e-/ADU) predicted gain, upper left
+GTGAIN12= 2.900 / (e-/ADU) predicted gain, lower right
+GTGAIN11= 3.200 / (e-/ADU) predicted gain, lower left
+GTINDEX = 2 / Gain selection (index into Gain Table)
+PIXELT = 29520 / (ns) unbinned pixel read time
+DCS_TIME= 7000 / (ns) Double Correlated Sample time
+RA = '14:53:52.67' / right ascension (telescope)
+DEC = '-19:20:10.70' / declination (telescope)
+EPOCH = 2000.0 / epoch of RA & DEC
+ZD = 32.1 / zenith distance (degrees)
+HA = '-02:13:40.3' / hour angle (H:M:S)
+ST = '12:40:10.80' / sidereal time
+AIRMASS = 1.180 / airmass
+EXPTIME = 7.000 / Exposure time in secs
+DARKTIME= 8.239 / Total elapsed time in secs
+OBSERVER= 'Jacoby' / Observers
+PROPID = '92' / Proposal Id
+COMMENT
+TELID = 'ct60' / CTIO 1.5-m Telescope
+ARCONVER= '17Oct97ver7_22' / Arcon software version
+COMMENT INSTRUMENT PARAMETERS
+INSTRUME= 'cfccd' / cassegrain direct imager
+FILTER1 = 'dia' / Filter in wheel one
+FNAME1 = 'diaphragm' / Full name of filter in wheel1
+FILTER2 = 'r' / Filter in wheel two
+FNAME2 = 'R' / Full name of filter in wheel2
+FILTERS = 'dia r' / Filter positions
+TELFOCUS= 0 / Telescope focus
+XPIXSIZE= 0.432 / Pixel size in X (arcsec/pix)
+YPIXSIZE= 0.432 / Pixel size in Y (arcsec/pix)
+RECID = 'ct60.990706.222551' / NOAO Archive record ID
+.fi
+
+3. The following is for the raw image of example 2 after it has been
+processed by CCDPROC. Note that the various bias, trim, and CCD sections are
+removed. The AMPLIST and ASEC keywords remain and may be used to split
+or evaluate the individual amplifier regions with tasks such as QUADSECTIONS,
+QUADSPLIT, and QSTATISTICS.
+
+.nf
+qu> imhead quad0013
+quad0013[1280,1280][real]: R sky flat 7s
+No bad pixels, min=unknown, max=unknown
+Line storage mode, physdim [1280,1280], length of user area 2795 s.u.
+Created Fri 13:29:40 24-Aug-2001, Last modified Fri 13:29:40 24-Aug-2001
+Pixel file "HDR$pixels/quad0013.pix" [ok]
+'KPNO-IRAF' /
+'06-07-99' /
+New copy of quad0013
+IRAF-MAX= 6.553500E4 / DATA MAX
+IRAF-MIN= 3.930000E2 / DATA MIN
+IRAF-BPX= 16 / DATA BITS/PIXEL
+IRAFTYPE= 'USHORT ' / PIXEL TYPE
+OPICNUM = 15 / Original picture number
+HDR_REV = '2.000 13Feb96 (add mode and group to hdrs)' /
+IMAGETYP= 'SKY FLAT' / Type of picture (object, dark, etc.)
+DETECTOR= 'Site2K_6' / Detector (CCD type, photon counter, etc.)
+PREFLASH= 0.000000 / Preflash time in secs
+CCDSUM = '1 1 ' / On chip summation (X,Y)
+DATE-OBS= '06/07/99' / Date (dd/mm/yy) of observation
+UTSHUT = '22:25:22.0' / UT of shutter open
+UT = '22:25:34.00' / UT of TCS coords
+OBSERVAT= 'CTIO ' / Origin of data
+TELESCOP= 'CTIO 1.5 meter telescope' / Specific system
+NAMPSYX = '2 2 ' / Num amps in y & x (eg. '2 2'=quad)
+AMPLIST = '11 21 12 22' / Readout order in y,x
+ASEC11 = '[1:769,1:769]' / Section read with Amp11
+ASEC12 = '[770:1280,1:769]' / Section read with Amp12
+ASEC21 = '[1:769,770:1280]' / Section read with Amp21
+ASEC22 = '[770:1280,770:1280]' / Section read with Amp22
+WAVEFILE= 'Obs Tue Jul 6 18:07:56 1999' /
+NOTE = 'WARNING: Lower amps reaching full well before ADCs saturate' /
+WAVEMODE= 'MPP OverlapXmit EarlyReset' / Waveform mode switches on
+GTRON22 = 4.100 / (e-) predicted read noise, upper right
+GTRON21 = 3.900 / (e-) predicted read noise, upper left
+GTRON12 = 4.200 / (e-) predicted read noise, lower right
+GTRON11 = 4.200 / (e-) predicted read noise, lower left
+GTGAIN22= 2.800 / (e-/ADU), predicted gain, upper right
+GTGAIN21= 3.100 / (e-/ADU) predicted gain, upper left
+GTGAIN12= 2.900 / (e-/ADU) predicted gain, lower right
+GTGAIN11= 3.200 / (e-/ADU) predicted gain, lower left
+GTINDEX = 2 / Gain selection (index into Gain Table)
+PIXELT = 29520 / (ns) unbinned pixel read time
+DCS_TIME= 7000 / (ns) Double Correlated Sample time
+RA = '14:53:52.67' / right ascension (telescope)
+DEC = '-19:20:10.70' / declination (telescope)
+EPOCH = 2000.0 / epoch of RA & DEC
+ZD = 32.1 / zenith distance (degrees)
+HA = '-02:13:40.3' / hour angle (H:M:S)
+ST = '12:40:10.80' / sidereal time
+AIRMASS = 1.180 / airmass
+EXPTIME = 7.000 / Exposure time in secs
+DARKTIME= 8.239 / Total elapsed time in secs
+OBSERVER= 'Jacoby' / Observers
+PROPID = '92' / Proposal Id
+COMMENT
+TELID = 'ct60' / CTIO 1.5-m Telescope
+ARCONVER= '17Oct97ver7_22' / Arcon software version
+COMMENT INSTRUMENT PARAMETERS
+INSTRUME= 'cfccd' / cassegrain direct imager
+FILTER1 = 'dia' / Filter in wheel one
+FNAME1 = 'diaphragm' / Full name of filter in wheel1
+FILTER2 = 'r' / Filter in wheel two
+FNAME2 = 'R' / Full name of filter in wheel2
+FILTERS = 'dia r' / Filter positions
+TELFOCUS= 0 / Telescope focus
+XPIXSIZE= 0.432 / Pixel size in X (arcsec/pix)
+YPIXSIZE= 0.432 / Pixel size in Y (arcsec/pix)
+RECID = 'ct60.990706.222551' / NOAO Archive record ID
+TRIM = 'Aug 24 13:29 Trim multiple overscan sections'
+OVERSCAN= 'Aug 24 13:29 Overscan is [790:843,1:769] with mean=714.3438'
+OVRSCN2 = 'Aug 24 13:29 Overscan is [790:843,770:1538] with mean=554.01'
+OVRSCN3 = 'Aug 24 13:29 Overscan is [844:897,1:769] with mean=519.7755'
+OVRSCN4 = 'Aug 24 13:29 Overscan is [844:897,770:1538] with mean=531.69'
+CCDSEC = '[266:1545,256:1535]'
+CCDMEAN = 9727.605
+CCDMEANT= 683126983
+CCDPROC = 'Aug 24 13:29 CCD processing done'
+.fi
+.endhelp
diff --git a/noao/imred/quadred/doc/quadjoin.hlp b/noao/imred/quadred/doc/quadjoin.hlp
new file mode 100644
index 00000000..2a3a075e
--- /dev/null
+++ b/noao/imred/quadred/doc/quadjoin.hlp
@@ -0,0 +1,43 @@
+.help quadjoin Aug01 noao.imred.quadred
+.ih
+NAME
+quadjoin -- Split quadformat data into single amplifier images
+.ih
+USAGE
+quadjoin input
+.ih
+PARAMETERS
+.ls input
+Root name of images to be joined. Extensions based on the AMPLIST
+keyword are applied to the root name. This task does not
+allow a list of input root names.
+.le
+.ls output = ""
+Output image name. If one is not given then the input root name is used.
+.le
+.ls delete = no
+Delete subimages on completion?
+.le
+.ih
+DESCRIPTION
+Images in split "quadformat" (see help topic \fBquadformat\fR and
+\fBquadsplit\fR) are rejoined into "quadformat". The input images
+have a common root name and then an extension given by the amplifier
+labels in the AMPLIST keyword are added. The output name may be specified
+or the input root name may be used.
+.ih
+EXAMPLES
+1. To join a split set of images:
+
+.nf
+ qu> dir quad0072*
+ quad0072.11.imh quad0072.21.imh
+ quad0072.12.imh quad0072.22.imh
+ qu> quadjoin quad0072 delete+
+ qu> dir quad0072*
+ quad0072.imh
+.fi
+.ih
+SEE ALSO
+quadformat, quadsplit
+.endhelp
diff --git a/noao/imred/quadred/doc/quadscale.hlp b/noao/imred/quadred/doc/quadscale.hlp
new file mode 100644
index 00000000..7493bcf6
--- /dev/null
+++ b/noao/imred/quadred/doc/quadscale.hlp
@@ -0,0 +1,37 @@
+.help quadscale Aug01 noao.imred.quadred
+.ih
+NAME
+quadscale -- Scale amplifier sections by separate gains
+.ih
+USAGE
+quadscale input output
+.ih
+PARAMETERS
+.ls input
+Input image in \fBquadformat\fR to be scaled.
+.le
+.ls output
+Output scaled image in \fBquadformat\fR.
+.le
+.ls gain11 = 1., gain12 = 1., gain21 = 1., gain22 = 1.
+Gain factors for each quadrant.
+.le
+.ls operation = "multiply" (multiply|divide)
+The operation to apply with the gains.
+.le
+.ih
+DESCRIPTION
+This task multiplies or divides by gain factors for each amplifier in
+\fBquadformat\fR.
+.ih
+EXAMPLES
+
+1. To multiply by different gain factors.
+
+.nf
+ qu> quadscale quad0072 test gain11=1.2 gain12=1.3 gain21=1.4
+.fi
+.ih
+SEE ALSO
+quadformat
+.endhelp
diff --git a/noao/imred/quadred/doc/quadsections.hlp b/noao/imred/quadred/doc/quadsections.hlp
new file mode 100644
index 00000000..2735e3d5
--- /dev/null
+++ b/noao/imred/quadred/doc/quadsections.hlp
@@ -0,0 +1,81 @@
+.help quadsections Aug01 noao.imred.quadred
+.ih
+NAME
+quadsections -- Create image sections
+.ih
+USAGE
+quadsplit images
+.ih
+PARAMETERS
+.ls images
+List of image names for images in \fBquadformat\fR.
+.le
+.ls window = "datasec" (datasec|trimsec|biassec)
+Type of section to output. The choices are "datasec" for the amplifier
+section which includes the bias if any is present, "trimsec" for the trim
+section, and "biassec" for the bias section.
+.le
+.ls section = ""
+Section to be overlapped. The output sections will be the parts of the
+amplifier windows which are included within this section.
+.le
+.ls template = ""
+Template for producing the output. The template replaces occurs of
+$I with the image name, $S with the section, and $A with the amplifier
+label. If none is specified then the default template "$I$S\\n" is
+used which produces the image name with section separated by new-lines.
+The special characters "\n" is the new-line and the extra "\" is
+required to pass the new-line through to the formatting routine.
+.le
+.ih
+DESCRIPTION
+Images in "quadformat" (see help topic \fBquadformat\fR) are broken down
+in sections and written to the standard output in a specified format.
+.ih
+EXAMPLES
+1. To print the default data sections.
+
+.nf
+ qu> quadsec quad0072
+ quad0072[1:1034,1:1024]
+ quad0072[1163:2196,1:1024]
+ quad0072[1:1034,1025:2048]
+ quad0072[1163:2196,1025:2048]
+.fi
+
+3. To apply an overlap section.
+
+.nf
+ qu> quadsec quad0072 section=[1000:2000,1000:2000]
+ quad0072[1000:1034,1000:1024]
+ quad0072[1163:2000,1000:1024]
+ quad0072[1000:1034,1025:2000]
+ quad0072[1163:2000,1025:2000]
+.fi
+
+2. To print the trim sections.
+
+.nf
+ qu> quadsec quad0072 window=trimsec
+ quad0072[11:1034,1:1024]
+ quad0072[1163:2186,1:1024]
+ quad0072[11:1034,1025:2048]
+ quad0072[1163:2186,1025:2048]
+.fi
+
+
+4. To make a custom output.
+
+.nf
+ qu> quadsec quad0072 template="image=$I, section=$S, amplifier=$A\\n"
+ image=quad0072, section=[1:1034,1:1024], amplifier=11
+ image=quad0072, section=[1163:2196,1:1024], amplifier=12
+ image=quad0072, section=[1:1034,1025:2048], amplifier=21
+ image=quad0072, section=[1163:2196,1025:2048], amplifier=22
+ qu> quadsec quad0072 template="$I.$A,"
+ quad0072.11,quad0072.12,quad0072.21,quad0072.22,
+.fi
+.ih
+SEE ALSO
+quadformat
+.endhelp
diff --git a/noao/imred/quadred/doc/quadsplit.hlp b/noao/imred/quadred/doc/quadsplit.hlp
new file mode 100644
index 00000000..4a0adf66
--- /dev/null
+++ b/noao/imred/quadred/doc/quadsplit.hlp
@@ -0,0 +1,49 @@
+.help quadsplit Aug01 noao.imred.quadred
+.ih
+NAME
+quadsplit -- Split quadformat data into single amplifier images
+.ih
+USAGE
+quadsplit input
+.ih
+PARAMETERS
+.ls input
+Image name of \fIquadformat\fR image to be split. This task does not
+allow a list of input names.
+.le
+.ls output = ""
+Output root name to which the AMPLIST amplifier identifiers will be
+appended to form the split images. If no output name is given then
+the input name is used as the root name.
+.le
+.ls clobber = yes
+Clobber any existing images?
+.le
+.ih
+DESCRIPTION
+Images in "quadformat" (see help topic \fBquadformat\fR) are separated
+into images containing data from only one amplifier. The output images
+have a common root name and then an extension given by the amplifier
+labels in the AMPLIST keyword. The output root name may be specified
+or default to the input name.
+
+In addition to producing the individual images keywords, are added that
+are understood by the standard \fBccdproc\fR task for single amplifier
+CCD reductions.
+
+The task \fBquadjoin\fR may be used to rejoin images that were split
+by this task.
+.ih
+EXAMPLES
+1. To spit an image:
+
+.nf
+ qu> quadsplit quad0072
+ qu> dir quad0072*
+ quad0072.11.imh quad0072.21.imh quad0072.imh
+ quad0072.12.imh quad0072.22.imh
+.fi
+.ih
+SEE ALSO
+quadformat, quadjoin
+.endhelp
diff --git a/noao/imred/quadred/mkpkg b/noao/imred/quadred/mkpkg
new file mode 100644
index 00000000..3a55a03a
--- /dev/null
+++ b/noao/imred/quadred/mkpkg
@@ -0,0 +1,8 @@
+# Make the package.
+
+$call update@src
+$exit
+
+update:
+ $call update@src
+ ;
diff --git a/noao/imred/quadred/quadred.cl b/noao/imred/quadred/quadred.cl
new file mode 100644
index 00000000..74592010
--- /dev/null
+++ b/noao/imred/quadred/quadred.cl
@@ -0,0 +1,68 @@
+#{ QUADRED -- QUAD CCD Reduction Package
+
+set ccddb = "ccdred$ccddb/"
+
+package quadred
+
+# Special version of CCDPROC.
+
+set quadsrc = "quadred$src/ccdproc/"
+
+task ccdproc = quadsrc$x_quadred.e
+task qccdproc = quad$x_ccdred.e
+
+# Task from the CTIO QUAD package.
+
+set quad = "quadred$src/quad/"
+
+task quadsplit,
+ quadjoin,
+ quadscale,
+ quadsections,
+ ccddelete,
+ ccdprcselect,
+ ccdssselect,
+ ccdsection,
+ qpcalimage,
+ qpselect,
+ gainmeasure,
+ ccdgetparam = "quad$x_quad.e"
+
+task quadproc = "quad$quadproc.cl"
+task qproc = "quad$qproc.cl"
+task qnoproc = "quad$qnoproc.cl"
+task qstatistics = "quad$qstatistics.cl"
+task qhistogram = "quad$qhistogram.cl"
+
+task setinstrument = "quad$setinstrument.cl"
+
+hidetask ccdgetparam, ccddelete, ccdprcselect, ccdssselect, ccdsection
+hidetask qpcalimage, qpselect, qproc, qnoproc, qccdproc
+
+# Special versions which run quadproc rather than ccdproc
+task qdarkcombine = quad$qdarkcombine.cl
+task qflatcombine = quad$qflatcombine.cl
+task qzerocombine = quad$qzerocombine.cl
+
+
+# Tasks from the standard CCDRED package.
+
+task badpiximage,
+ ccdgroups,
+ ccdhedit,
+ ccdinstrument,
+ ccdlist,
+ ccdmask,
+ combine,
+ mkfringecor,
+ mkillumcor,
+ mkillumflat,
+ mkskycor,
+ mkskyflat = ccdred$x_ccdred.e
+
+task darkcombine = ccdred$darkcombine.cl
+task flatcombine = ccdred$flatcombine.cl
+#task setinstrument = ccdred$setinstrument.cl
+task zerocombine = ccdred$zerocombine.cl
+
+clbye()
diff --git a/noao/imred/quadred/quadred.hd b/noao/imred/quadred/quadred.hd
new file mode 100644
index 00000000..b542fec9
--- /dev/null
+++ b/noao/imred/quadred/quadred.hd
@@ -0,0 +1,22 @@
+# Help directory for the QUADRED package.
+
+$doc = "./doc/"
+$cdoc = "./src/ccdproc/doc/"
+$qdoc = "./src/quad/doc/"
+
+package hlp=doc$quad.hlp
+quadformat hlp=doc$quadformat.hlp
+quadsplit hlp=doc$quadsplit.hlp
+quadjoin hlp=doc$quadjoin.hlp
+quadsections hlp=doc$quadsections.hlp
+qstatistics hlp=doc$qstatistics.hlp
+qhistogram hlp=doc$qhistogram.hlp
+quadscale hlp=doc$quadscale.hlp
+
+ccdproc hlp=cdoc$ccdproc.hlp
+
+quadproc hlp=qdoc$quadproc.hlp
+#quadreadout hlp=qdoc$quadreadout.hlp
+#quadman hlp=qdoc$quadman.hlp
+
+revisions sys=Revisions
diff --git a/noao/imred/quadred/quadred.men b/noao/imred/quadred/quadred.men
new file mode 100644
index 00000000..6a0225a5
--- /dev/null
+++ b/noao/imred/quadred/quadred.men
@@ -0,0 +1,61 @@
+ SPECIAL VERSION OF CCDRED PACKAGE FOR MULTI-AMPLIFIER CCD IMAGES
+
+The package has a special quad version of CCDPROC that processes
+multi-amplifier CCD images in a particular format. See help topic
+"quadformat" for a description of the format. The task QUADPROC is
+largely obsoleted by the quad version of CCDPROC but may be used by
+those familiar with the ARED.QUAD package or to use features in the
+standard CCDPROC that are not in the quad version. Those features
+include line-by-line overscan functions.
+
+
+ STANDARD CCDRED TASKS
+
+ badpiximage - Create a bad pixel mask image from a bad pixel file
+ ccdgroups - Group CCD images into image lists
+ ccdhedit - CCD image header editor
+ ccdinstrument - Review and edit instrument translation files
+ ccdlist - List CCD processing information
+ ccdmask - Make a bad pixel mask from CCD data
+ ccdproc - Process CCD images (including quadformat data)
+ combine - Combine CCD images
+ darkcombine - Combine and process dark count images
+ flatcombine - Combine and process flat field images
+ mkfringecor - Make fringe correction images from sky images
+ mkillumcor - Make flat field illumination correction images
+ mkillumflat - Make illumination corrected flat fields
+ mkskycor - Make sky illumination correction images
+ mkskyflat - Make sky corrected flat field images
+ setinstrument - Set instrument parameters
+ zerocombine - Combine and process zero level images
+
+ SPECIAL TASKS FOR MULTI-AMPLIFIER CCD IMAGES IN QUADFORMAT
+
+ gainmeasure - Measure gains in quadformat images
+ quadscale - Scale sections by gain factors
+ qstatistics - Calculate image statistics for multi-amplifier CCD images
+ quadsections - Produce image section list for sections of quadformat images
+ qhistogram - Make histogram of multi-amplifier CCD image
+ quadsplit - Split quadformat data into individual single amplifier images
+ quadjoin - Rejoin single amplifier images produced by quadsplit
+
+ ALTERNATIVE TASKS
+
+ quadproc - Process multi-amplifier CCD images (see also ccdproc)
+ qdarkcombine - Combine and process dark count images using quadproc
+ qflatcombine - Combine and process flat field images using quadproc
+ qzerocombine - Combine and process zero level images using quadproc
+
+ There is no separate help for the quadproc versions of the combining
+ tasks. See the help for the standard versions.
+
+ ADDITIONAL HELP TOPICS
+
+ package - Package parameters and overview
+ quadformat - Format for multi-amplifier CCD images
+ ccdgeometry - Discussion of CCD coordinate/geometry keywords
+ ccdtypes - Description of the CCD image types
+ flatfields - Discussion of CCD flat field calibrations
+ guide - Introductory guide to using the CCDRED package
+ instruments - Instrument specific data files
+ subsets - Description of CCD subsets
diff --git a/noao/imred/quadred/quadred.par b/noao/imred/quadred/quadred.par
new file mode 100644
index 00000000..05c8d112
--- /dev/null
+++ b/noao/imred/quadred/quadred.par
@@ -0,0 +1,13 @@
+# QUADRED package parameter file
+
+proctask,s,h,"ccdproc","ccdproc|quadproc",,Processing task
+pixeltype,s,h,"real real",,,Output and calculation pixel datatypes
+verbose,b,h,no,,,Print log information to the standard output?
+logfile,f,h,"logfile",,,Text log file
+plotfile,f,h,"",,,Log metacode plot file
+backup,s,h,"",,,Backup directory or prefix
+instrument,s,h,"",,,CCD instrument file
+ssfile,s,h,"subsets",,,Subset translation file
+graphics,s,h,"stdgraph",,,Interactive graphics output device
+cursor,*gcur,h,"",,,Graphics cursor input
+version,s,h,"V1.0: August 22, 2001"
diff --git a/noao/imred/quadred/src/Revisions b/noao/imred/quadred/src/Revisions
new file mode 100644
index 00000000..bbdfcc7d
--- /dev/null
+++ b/noao/imred/quadred/src/Revisions
@@ -0,0 +1,42 @@
+.help revisions Jun88 noao.imred.quadred
+.nf
+
+ccdproc/ccdcache.x
+ The 'bufs' pointer was declared as TY_REAL instead of TY_SHORT (5/4/13)
+
+quad/qproc.cl
+quad/quad.cl
+quad/quadjoin.x
+quad/quadproc.cl
+quad/setinstrument.cl
+quad/qccdproc.par +
+../quadred.cl
+../quadred.men
+ When using quadproc the latest CCDPROC is used with the alias QCCDPROC.
+ This is to allow using the line-by-line overscan function. Other features
+ in CCDPROC would also be available. It was too hard to update the
+ quad version of CCDPROC. (3/12/08, Valdes)
+
+=====
+V2.14
+=====
+
+=======
+V2.12.1
+=======
+
+quad/qproc.cl
+ For some reason the quadsplit call was commented out. So when quadproc
+ is run the pieces are not split and then the quadjoin call results in
+ a divide by zero error. The call was uncommented. Due to my lack
+ of understanding with QUAD and that multipiece CCDPROC is used which
+ does not support trims, the quadsplit with trimming is not used.
+ (7/5/02, Valdes)
+
+=====
+V2.12
+=====
+
+New package consisting of XCCDRED and ARED.QUAD was added.
+
+.endhelp
diff --git a/noao/imred/quadred/src/ccdproc/calimage.x b/noao/imred/quadred/src/ccdproc/calimage.x
new file mode 100644
index 00000000..8a6007c1
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/calimage.x
@@ -0,0 +1,367 @@
+include <error.h>
+include <imset.h>
+include "ccdtypes.h"
+
+define SZ_SUBSET 16 # Maximum size of subset string
+define IMAGE Memc[$1+($2-1)*SZ_FNAME] # Image string
+define SUBSET Memc[$1+($2-1)*SZ_SUBSET] # Subset string
+
+# CAL_IMAGE -- Return a calibration image for a specified input image.
+# CAL_OPEN -- Open the calibration image list.
+# CAL_CLOSE -- Close the calibration image list.
+# CAL_LIST -- Add images to the calibration image list.
+#
+# The open procedure is called first to get the calibration image
+# lists and add them to an internal list. Calibration images from the
+# input list are also added so that calibration images may be specified
+# either from the calibration image list parameters or in the input image list.
+# Existence errors and duplicate calibration images are ignored.
+# Validity checks are made when the calibration images are requested.
+#
+# During processing the calibration image names are requested for each input
+# image. The calibration image list is searched for a calibration image of
+# the right type and subset. If more than one is found the first one is
+# returned and a warning given for the others. The warning is only issued
+# once. If no calibration image is found then an error is returned.
+#
+# The calibration image list must be closed at the end of processing the
+# input images.
+
+
+# CAL_IMAGE -- Return a calibration image of a particular type.
+# Search the calibration list for the first calibration image of the desired
+# type and subset. Print a warning if there is more than one possible
+# calibration image and return an error if there is no calibration image.
+
+procedure cal_image (im, ccdtype, nscan, image, maxchars)
+
+pointer im # Image to be processed
+int ccdtype # Callibration CCD image type desired
+int nscan # Number of scan rows desired
+char image[maxchars] # Calibration image (returned)
+int maxchars # Maximum number chars in image name
+
+int i, m, n
+pointer sp, subset, str
+bool strne(), ccd_cmp()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subsets
+pointer nscans # Pointer to array of calibration nscan values
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, nscans, images, nimages
+
+begin
+ call smark (sp)
+ call salloc (subset, SZ_SUBSET, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ m = 0
+ n = 0
+ switch (ccdtype) {
+ case ZERO, DARK:
+ do i = 1, nimages {
+ if (Memi[ccdtypes+i-1] != ccdtype)
+ next
+ n = n + 1
+ if (n == 1) {
+ m = i
+ } else {
+ if (Memi[nscans+i-1] == Memi[nscans+m-1]) {
+# call eprintf (
+# "Warning: Extra calibration image %s ignored\n")
+# call pargstr (IMAGE(images,i))
+
+ # Reset the image type to eliminate further warnings.
+ Memi[ccdtypes+i-1] = UNKNOWN
+ } else if (Memi[nscans+m-1] != nscan &&
+ (Memi[nscans+i-1] == nscan ||
+ Memi[nscans+i-1] == 1)) {
+ m = i
+ }
+ }
+ }
+ case FLAT, ILLUM, FRINGE:
+ call ccdsubset (im, Memc[subset], SZ_SUBSET)
+
+ do i = 1, nimages {
+ if (Memi[ccdtypes+i-1] != ccdtype)
+ next
+ if (strne (SUBSET(subsets,i), Memc[subset]))
+ next
+ n = n + 1
+ if (n == 1) {
+ m = i
+ } else {
+ if (Memi[nscans+i-1] == Memi[nscans+m-1]) {
+# call eprintf (
+# "Warning: Extra calibration image %s ignored\n")
+# call pargstr (IMAGE(images,i))
+
+ # Reset the image type to eliminate further warnings.
+ Memi[ccdtypes+i-1] = UNKNOWN
+ } else if (Memi[nscans+m-1] != nscan &&
+ (Memi[nscans+i-1] == nscan ||
+ Memi[nscans+i-1] == 1)) {
+ m = i
+ }
+ }
+ }
+ }
+
+ # If no calibration image is found then it is an error.
+ if (m == 0) {
+ switch (ccdtype) {
+ case ZERO:
+ call error (0, "No zero level calibration image found")
+ case DARK:
+ call error (0, "No dark count calibration image found")
+ case FLAT:
+ call sprintf (Memc[str], SZ_LINE,
+ "No flat field calibration image of subset %s found")
+ call pargstr (Memc[subset])
+ call error (0, Memc[str])
+ case ILLUM:
+ call sprintf (Memc[str], SZ_LINE,
+ "No illumination calibration image of subset %s found")
+ call pargstr (Memc[subset])
+ call error (0, Memc[str])
+ case FRINGE:
+ call sprintf (Memc[str], SZ_LINE,
+ "No fringe calibration image of subset %s found")
+ call pargstr (Memc[subset])
+ call error (0, Memc[str])
+ }
+ }
+
+ call strcpy (IMAGE(images,m), image, maxchars)
+ if (nscan != Memi[nscans+m-1]) {
+ if (nscan != 1 && Memi[nscans+m-1] == 1)
+ call cal_scan (nscan, image, maxchars)
+ else {
+ call sprintf (Memc[str], SZ_LINE,
+ "Cannot find or create calibration with nscan of %d")
+ call pargi (nscan)
+ call error (0, Memc[str])
+ }
+ }
+
+ # Check that the input image is not the same as the calibration image.
+ call imstats (im, IM_IMAGENAME, Memc[str], SZ_LINE)
+ if (ccd_cmp (Memc[str], IMAGE(images,m))) {
+ call sprintf (Memc[str], SZ_LINE,
+ "Calibration image %s is the same as the input image")
+ call pargstr (image)
+ call error (0, Memc[str])
+ }
+
+ call sfree (sp)
+end
+
+
+# CAL_OPEN -- Create a list of calibration images from the input image list
+# and the calibration image lists.
+
+procedure cal_open (list)
+
+int list # List of input images
+int list1 # List of calibration images
+
+pointer sp, str
+int ccdtype, strdic(), imtopenp()
+bool clgetb()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subset numbers
+pointer nscans # Pointer to array of calibration nscan values
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, nscans, images, nimages
+
+errchk cal_list
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call clgstr ("ccdtype", Memc[str], SZ_LINE)
+ call xt_stripwhite (Memc[str])
+ if (Memc[str] == EOS)
+ ccdtype = NONE
+ else
+ ccdtype = strdic (Memc[str], Memc[str], SZ_LINE, CCDTYPES)
+
+ # Add calibration images to list.
+ nimages = 0
+ if (ccdtype != ZERO && clgetb ("zerocor")) {
+ list1 = imtopenp ("zero")
+ call cal_list (list1, ZERO)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && clgetb ("darkcor")) {
+ list1 = imtopenp ("dark")
+ call cal_list (list1, DARK)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && ccdtype != FLAT &&
+ clgetb ("flatcor")) {
+ list1 = imtopenp ("flat")
+ call cal_list (list1, FLAT)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && ccdtype != FLAT &&
+ ccdtype != ILLUM && clgetb ("illumcor")) {
+ list1 = imtopenp ("illum")
+ call cal_list (list1, ILLUM)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && ccdtype != FLAT &&
+ ccdtype != FRINGE && clgetb ("fringecor")) {
+ list1 = imtopenp ("fringe")
+ call cal_list (list1, FRINGE)
+ call imtclose (list1)
+ }
+ if (list != NULL) {
+ call cal_list (list, UNKNOWN)
+ call imtrew (list)
+ }
+
+ call sfree (sp)
+end
+
+
+# CAL_CLOSE -- Free memory from the internal calibration image list.
+
+procedure cal_close ()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subset
+pointer nscans # Pointer to array of calibration nscan values
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, nscans, images, nimages
+
+begin
+ if (nimages > 0) {
+ call mfree (ccdtypes, TY_INT)
+ call mfree (subsets, TY_CHAR)
+ call mfree (nscans, TY_INT)
+ call mfree (images, TY_CHAR)
+ }
+end
+
+
+# CAL_LIST -- Add calibration images to an internal list.
+# Map each image and get the CCD image type and subset.
+# If the ccdtype is given as a procedure argument this overrides the
+# image header type. For the calibration images add the type, subset,
+# and image name to dynamic arrays. Ignore duplicate names.
+
+procedure cal_list (list, listtype)
+
+pointer list # Image list
+int listtype # CCD type of image in list.
+ # Overrides header type if not UNKNOWN.
+
+int i, ccdtype, ccdtypei(), ccdnscan(), imtgetim()
+pointer sp, image, im, immap()
+bool streq()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subsets
+pointer nscans # Pointer to array of calibration nscan values
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, nscans, images, nimages
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+
+ while (imtgetim (list, Memc[image], SZ_FNAME) != EOF) {
+ # Open the image. If an explicit type is given it is an
+ # error if the image can't be opened.
+ iferr (im = immap (Memc[image], READ_ONLY, 0)) {
+ if (listtype == UNKNOWN)
+ next
+ else
+ call erract (EA_ERROR)
+ }
+
+ # Override image header CCD type if a list type is given.
+ if (listtype == UNKNOWN)
+ ccdtype = ccdtypei (im)
+ else
+ ccdtype = listtype
+
+ switch (ccdtype) {
+ case ZERO, DARK, FLAT, ILLUM, FRINGE:
+ # Check for duplication.
+ for (i=1; i<=nimages; i=i+1)
+ if (streq (Memc[image], IMAGE(images,i)))
+ break
+ if (i <= nimages)
+ break
+
+ # Allocate memory for a new image.
+ if (i == 1) {
+ call malloc (ccdtypes, i, TY_INT)
+ call malloc (subsets, i * SZ_SUBSET, TY_CHAR)
+ call malloc (nscans, i, TY_INT)
+ call malloc (images, i * SZ_FNAME, TY_CHAR)
+ } else {
+ call realloc (ccdtypes, i, TY_INT)
+ call realloc (subsets, i * SZ_FNAME, TY_CHAR)
+ call realloc (nscans, i, TY_INT)
+ call realloc (images, i * SZ_FNAME, TY_CHAR)
+ }
+
+ # Enter the ccdtype, subset, and image name.
+ Memi[ccdtypes+i-1] = ccdtype
+ Memi[nscans+i-1] = ccdnscan (im, ccdtype)
+ call ccdsubset (im, SUBSET(subsets,i), SZ_SUBSET-1)
+ call strcpy (Memc[image], IMAGE(images,i), SZ_FNAME-1)
+ nimages = i
+ }
+ call imunmap (im)
+ }
+ call sfree (sp)
+end
+
+
+# CAL_SCAN -- Generate name for scan corrected calibration image.
+
+procedure cal_scan (nscan, image, maxchar)
+
+int nscan #I Number of scan lines
+char image[maxchar] #U Input root name, output scan name
+int maxchar #I Maximum number of chars in image name
+
+bool clgetb()
+pointer sp, root, ext
+
+begin
+ # Check if this operation is desired.
+ if (!clgetb ("scancor") || nscan == 1)
+ return
+
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (ext, SZ_FNAME, TY_CHAR)
+
+ call xt_imroot (image, Memc[root], SZ_FNAME)
+ call xt_imext (image, Memc[ext], SZ_FNAME)
+ if (IS_INDEFI (nscan)) {
+ call sprintf (image, maxchar, "%s.1d%s")
+ call pargstr (Memc[root])
+ call pargstr (Memc[ext])
+ } else {
+ call sprintf (image, maxchar, "%s.%d%s")
+ call pargstr (Memc[root])
+ call pargi (nscan)
+ call pargstr (Memc[ext])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdcache.com b/noao/imred/quadred/src/ccdproc/ccdcache.com
new file mode 100644
index 00000000..91ffae12
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdcache.com
@@ -0,0 +1,10 @@
+# Common data defining the cached images and data.
+
+int ccd_ncache # Number of images cached
+int ccd_maxcache # Maximum size of cache
+int ccd_szcache # Current size of cache
+int ccd_oldsize # Original memory size
+int ccd_pcache # Pointer to image cache structures
+
+common /ccdcache_com/ ccd_ncache, ccd_maxcache, ccd_szcache, ccd_oldsize,
+ ccd_pcache
diff --git a/noao/imred/quadred/src/ccdproc/ccdcache.h b/noao/imred/quadred/src/ccdproc/ccdcache.h
new file mode 100644
index 00000000..f7de3a2c
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdcache.h
@@ -0,0 +1,10 @@
+# Definition for image cache structure.
+
+define CCD_LENCACHE 6
+
+define CCD_IM Memi[$1] # IMIO pointer
+define CCD_NACCESS Memi[$1+1] # Number of accesses requested
+define CCD_SZDATA Memi[$1+2] # Size of data in cache in chars
+define CCD_DATA Memi[$1+3] # Pointer to data cache
+define CCD_BUFR Memi[$1+4] # Pointer to real image line
+define CCD_BUFS Memi[$1+5] # Pointer to short image line
diff --git a/noao/imred/quadred/src/ccdproc/ccdcache.x b/noao/imred/quadred/src/ccdproc/ccdcache.x
new file mode 100644
index 00000000..78f84ace
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdcache.x
@@ -0,0 +1,381 @@
+include <imhdr.h>
+include <imset.h>
+include <mach.h>
+include "ccdcache.h"
+
+.help ccdcache Jun87
+.nf ---------------------------------------------------------------------
+The purpose of the CCD image caching package is to minimize image mapping
+time, to prevent multiple mapping of the same image, and to keep entire
+calibration images in memory for extended periods to minimize disk
+I/O. It is selected by specifying a maximum caching size based on the
+available memory. When there is not enough memory for caching (or by
+setting the size to 0) then standard IMIO is used. When there is
+enough memory then as many images as will fit into the specified cache
+size are kept in memory. Images are also kept mapped until explicitly
+flushed or the entire package is closed.
+
+This is a special purpose interface intended only for the CCDRED package.
+It has the following restrictions.
+
+ 1. Images must be processed to be cached.
+ 2. Images must be 2 dimensional to be cached
+ 3. Images must be real or short to be cached.
+ 4. Images must be read_only to be cached.
+ 5. Cached images remain in memory until they are displaced,
+ flushed, or the package is closed.
+
+The package consists of the following procedures.
+
+ ccd_open ()
+ im = ccd_cache (image)
+ ptr = ccd_glr (im, col1, col2, line)
+ ptr = ccd_gls (im, col1, col2, line)
+ ccd_unmap (im)
+ ccd_flush (im)
+ ccd_close ()
+
+
+CCD_OPEN: Initialize the image cache. Called at the beginning.
+CCD_CLOSE: Flush the image cache and restore memory. Called at the end.
+
+CCD_CACHE: Open an image and save the IMIO pointer. If the image has been
+opened previously it need not be opened again. If image data caching
+is specified the image data may be read it into memory. In order for
+image data caching to occur the the image has to have been processed,
+be two dimensional, be real or short, and the total cache memory not
+be exceeded. If an error occurs in reading the image into memory
+the data is not cached.
+
+CCD_UNMAP: The image access number is decremented but the image
+is not closed against the event it will be used again.
+
+CCD_FLUSH: The image is closed and flushed from the cache.
+
+CCD_GLR, CCD_GLS: Get a real or short image line. If the image data is cached
+then a pointer to the line is quickly returned. If the data is not cached then
+IMIO is used to get the pointer.
+.endhelp ---------------------------------------------------------------------
+
+
+
+# CCD_CACHE -- Open an image and possibly cache it in memory.
+
+pointer procedure ccd_cache (image, ccdtype)
+
+char image[ARB] # Image to be opened
+int ccdtype # Image type
+
+int i, nc, nl, nbytes
+pointer sp, str, pcache, pcache1, im
+
+int sizeof()
+pointer immap(), imgs2r(), imgs2s()
+bool streq(), ccdcheck()
+errchk immap, imgs2r, imgs2s
+
+include "ccdcache.com"
+
+define done_ 99
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Check if the image is cached.
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ im = CCD_IM(pcache)
+ call imstats (im, IM_IMAGENAME, Memc[str], SZ_LINE)
+ if (streq (image, Memc[str]))
+ break
+ }
+
+ # If the image is not cached open it and allocate memory.
+ if (i > ccd_ncache) {
+ im = immap (image, READ_ONLY, 0)
+ ccd_ncache = i
+ call realloc (ccd_pcache, ccd_ncache, TY_INT)
+ call malloc (pcache, CCD_LENCACHE, TY_STRUCT)
+ Memi[ccd_pcache+i-1] = pcache
+ CCD_IM(pcache) = im
+ CCD_NACCESS(pcache) = 0
+ CCD_SZDATA(pcache) = 0
+ CCD_DATA(pcache) = NULL
+ CCD_BUFR(pcache) = NULL
+ CCD_BUFS(pcache) = NULL
+ }
+
+ # If not caching the image data or if the image data has already
+ # been cached we are done.
+ if ((ccd_maxcache == 0) || (CCD_SZDATA(pcache) > 0))
+ goto done_
+
+ # Don't cache unprocessed calibration image data.
+ # This is the only really CCDRED specific code.
+ if (ccdcheck (im, ccdtype))
+ goto done_
+
+ # Check image is 2D and a supported pixel type.
+ if (IM_NDIM(im) != 2)
+ goto done_
+ if ((IM_PIXTYPE(im) != TY_REAL) && (IM_PIXTYPE(im) !=TY_SHORT))
+ goto done_
+
+ # Compute the size of the image data.
+ nc = IM_LEN(im,1)
+ nl = IM_LEN(im,2)
+ nbytes = nc * nl * sizeof (IM_PIXTYPE(im)) * SZB_CHAR
+
+ # Free memory not in use.
+ if (ccd_szcache + nbytes > ccd_maxcache) {
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache1 = Memi[ccd_pcache+i-1]
+ if (CCD_NACCESS(pcache1) == 0) {
+ if (CCD_SZDATA(pcache1) > 0) {
+ ccd_szcache = ccd_szcache - CCD_SZDATA(pcache1)
+ CCD_SZDATA(pcache1) = 0
+ CCD_DATA(pcache1) = NULL
+ call mfree (CCD_BUFR(pcache1), TY_REAL)
+ call mfree (CCD_BUFS(pcache1), TY_SHORT)
+ call imseti (CCD_IM(pcache1), IM_CANCEL, YES)
+ if (ccd_szcache + nbytes > ccd_maxcache)
+ break
+ }
+ }
+ }
+ }
+ if (ccd_szcache + nbytes > ccd_maxcache)
+ goto done_
+
+ # Cache the image data
+ iferr {
+ switch (IM_PIXTYPE (im)) {
+ case TY_SHORT:
+ CCD_DATA(pcache) = imgs2s (im, 1, nc, 1, nl)
+ case TY_REAL:
+ CCD_DATA(pcache) = imgs2r (im, 1, nc, 1, nl)
+ }
+ ccd_szcache = ccd_szcache + nbytes
+ CCD_SZDATA(pcache) = nbytes
+ } then {
+ call imunmap (im)
+ im = immap (image, READ_ONLY, 0)
+ CCD_IM(pcache) = im
+ CCD_SZDATA(pcache) = 0
+ }
+
+done_
+ CCD_NACCESS(pcache) = CCD_NACCESS(pcache) + 1
+ call sfree (sp)
+ return (im)
+end
+
+
+# CCD_OPEN -- Initialize the CCD image cache.
+
+procedure ccd_open (max_cache)
+
+int max_cache # Maximum cache size in bytes
+
+int max_size, begmem()
+include "ccdcache.com"
+
+begin
+ ccd_ncache = 0
+ ccd_maxcache = max_cache
+ ccd_szcache = 0
+ call malloc (ccd_pcache, 1, TY_INT)
+
+ # Ask for the maximum physical memory.
+ if (ccd_maxcache > 0) {
+ ccd_oldsize = begmem (0, ccd_oldsize, max_size)
+ call fixmem (max_size)
+ }
+end
+
+
+# CCD_UNMAP -- Unmap an image.
+# Don't actually unmap the image since it may be opened again.
+
+procedure ccd_unmap (im)
+
+pointer im # IMIO pointer
+
+int i
+pointer pcache
+include "ccdcache.com"
+
+begin
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ if (CCD_IM(pcache) == im) {
+ CCD_NACCESS(pcache) = CCD_NACCESS(pcache) - 1
+ return
+ }
+ }
+
+ call imunmap (im)
+end
+
+
+# CCD_FLUSH -- Close image and flush from cache.
+
+procedure ccd_flush (im)
+
+pointer im # IMIO pointer
+
+int i
+pointer pcache
+include "ccdcache.com"
+
+begin
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ if (CCD_IM(pcache) == im) {
+ ccd_ncache = ccd_ncache - 1
+ ccd_szcache = ccd_szcache - CCD_SZDATA(pcache)
+ call mfree (CCD_BUFR(pcache), TY_REAL)
+ call mfree (CCD_BUFS(pcache), TY_SHORT)
+ call mfree (pcache, TY_STRUCT)
+ for (; i<=ccd_ncache; i=i+1)
+ Memi[ccd_pcache+i-1] = Memi[ccd_pcache+i]
+ break
+ }
+ }
+
+ call imunmap (im)
+end
+
+
+# CCD_CLOSE -- Close the image cache.
+
+procedure ccd_close ()
+
+int i
+pointer pcache
+include "ccdcache.com"
+
+begin
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ call imunmap (CCD_IM(pcache))
+ call mfree (CCD_BUFR(pcache), TY_REAL)
+ call mfree (CCD_BUFS(pcache), TY_SHORT)
+ call mfree (pcache, TY_STRUCT)
+ }
+ call mfree (ccd_pcache, TY_INT)
+
+ # Restore memory.
+ call fixmem (ccd_oldsize)
+end
+
+
+# CCD_GLR -- Get a line of real data from the image.
+# If the image data is cached this is fast (particularly if the datatype
+# matches). If the image data is not cached then use IMIO.
+
+pointer procedure ccd_glr (im, col1, col2, line)
+
+pointer im # IMIO pointer
+int col1, col2 # Columns
+int line # Line
+
+int i
+pointer pcache, data, bufr, imgs2r()
+errchk malloc
+include "ccdcache.com"
+
+begin
+ # Quick test for cached data.
+ if (ccd_maxcache == 0)
+ return (imgs2r (im, col1, col2, line, line))
+
+ # Return cached data.
+ if (IM_PIXTYPE(im) == TY_REAL) {
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ if (CCD_IM(pcache) == im) {
+ if (CCD_SZDATA(pcache) > 0)
+ return (CCD_DATA(pcache)+(line-1)*IM_LEN(im,1)+col1-1)
+ else
+ break
+ }
+ }
+ } else {
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ if (CCD_IM(pcache) == im) {
+ if (CCD_SZDATA(pcache) > 0) {
+ data = CCD_DATA(pcache)+(line-1)*IM_LEN(im,1)+col1-1
+ bufr = CCD_BUFR(pcache)
+ if (bufr == NULL) {
+ call malloc (bufr, IM_LEN(im,1), TY_REAL)
+ CCD_BUFR(pcache) = bufr
+ }
+ call achtsr (Mems[data], Memr[bufr], IM_LEN(im,1))
+ return (bufr)
+ } else
+ break
+ }
+ }
+ }
+
+ # Return uncached data.
+ return (imgs2r (im, col1, col2, line, line))
+end
+
+
+# CCD_GLS -- Get a line of short data from the image.
+# If the image data is cached this is fast (particularly if the datatype
+# matches). If the image data is not cached then use IMIO.
+
+pointer procedure ccd_gls (im, col1, col2, line)
+
+pointer im # IMIO pointer
+int col1, col2 # Columns
+int line # Line
+
+int i
+pointer pcache, data, bufs, imgs2s()
+errchk malloc
+include "ccdcache.com"
+
+begin
+ # Quick test for cached data.
+ if (ccd_maxcache == 0)
+ return (imgs2s (im, col1, col2, line, line))
+
+ # Return cached data.
+ if (IM_PIXTYPE(im) == TY_SHORT) {
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ if (CCD_IM(pcache) == im) {
+ if (CCD_SZDATA(pcache) > 0)
+ return (CCD_DATA(pcache)+(line-1)*IM_LEN(im,1)+col1-1)
+ else
+ break
+ }
+ }
+ } else {
+ for (i=1; i<=ccd_ncache; i=i+1) {
+ pcache = Memi[ccd_pcache+i-1]
+ if (CCD_IM(pcache) == im) {
+ if (CCD_SZDATA(pcache) > 0) {
+ data = CCD_DATA(pcache)+(line-1)*IM_LEN(im,1)+col1-1
+ bufs = CCD_BUFS(pcache)
+ if (bufs == NULL) {
+ call malloc (bufs, IM_LEN(im,1), TY_SHORT)
+ CCD_BUFS(pcache) = bufs
+ }
+ call achtrs (Memr[data], Mems[bufs], IM_LEN(im,1))
+ return (bufs)
+ } else
+ break
+ }
+ }
+ }
+
+ # Return uncached data.
+ return (imgs2s (im, col1, col2, line, line))
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdcheck.x b/noao/imred/quadred/src/ccdproc/ccdcheck.x
new file mode 100644
index 00000000..0dde14f9
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdcheck.x
@@ -0,0 +1,67 @@
+include <imhdr.h>
+include "ccdtypes.h"
+
+# CCDCHECK -- Check processing status.
+
+bool procedure ccdcheck (im, ccdtype)
+
+pointer im # IMIO pointer
+int ccdtype # CCD type
+
+real ccdmean, hdmgetr()
+bool clgetb(), ccdflag()
+long time
+int hdmgeti()
+
+begin
+ if (clgetb ("trim") && !ccdflag (im, "trim"))
+ return (true)
+ if (clgetb ("fixpix") && !ccdflag (im, "fixpix"))
+ return (true)
+ if (clgetb ("overscan") && !ccdflag (im, "overscan"))
+ return (true)
+
+ switch (ccdtype) {
+ case ZERO:
+ if (clgetb ("readcor") && !ccdflag (im, "readcor"))
+ return (true)
+ case DARK:
+ if (clgetb ("zerocor") && !ccdflag (im, "zerocor"))
+ return (true)
+ case FLAT:
+ if (clgetb ("zerocor") && !ccdflag (im, "zerocor"))
+ return (true)
+ if (clgetb ("darkcor") && !ccdflag (im, "darkcor"))
+ return (true)
+ if (clgetb ("scancor") && !ccdflag (im, "scancor"))
+ return (true)
+ iferr (ccdmean = hdmgetr (im, "ccdmean"))
+ return (true)
+ iferr (time = hdmgeti (im, "ccdmeant"))
+ time = IM_MTIME(im)
+ if (time < IM_MTIME(im))
+ return (true)
+ case ILLUM:
+ if (clgetb ("zerocor") && !ccdflag (im, "zerocor"))
+ return (true)
+ if (clgetb ("darkcor") && !ccdflag (im, "darkcor"))
+ return (true)
+ if (clgetb ("flatcor") && !ccdflag (im, "flatcor"))
+ return (true)
+ iferr (ccdmean = hdmgetr (im, "ccdmean"))
+ return (true)
+ default:
+ if (clgetb ("zerocor") && !ccdflag (im, "zerocor"))
+ return (true)
+ if (clgetb ("darkcor") && !ccdflag (im, "darkcor"))
+ return (true)
+ if (clgetb ("flatcor") && !ccdflag (im, "flatcor"))
+ return (true)
+ if (clgetb ("illumcor") && !ccdflag (im, "illumcor"))
+ return (true)
+ if (clgetb ("fringecor") && !ccdflag (im, "fringcor"))
+ return (true)
+ }
+
+ return (false)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdcmp.x b/noao/imred/quadred/src/ccdproc/ccdcmp.x
new file mode 100644
index 00000000..a2687934
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdcmp.x
@@ -0,0 +1,23 @@
+# CCD_CMP -- Compare two image names with extensions ignored.
+
+bool procedure ccd_cmp (image1, image2)
+
+char image1[ARB] # First image
+char image2[ARB] # Second image
+
+int i, j, strmatch(), strlen(), strncmp()
+bool streq()
+
+begin
+ if (streq (image1, image2))
+ return (true)
+
+ i = max (strmatch (image1, ".imh"), strmatch (image1, ".hhh"))
+ if (i == 0)
+ i = strlen (image1)
+ j = max (strmatch (image2, ".imh"), strmatch (image2, ".hhh"))
+ if (j == 0)
+ j = strlen (image2)
+
+ return (strncmp (image1, image2, max (i, j)) == 0)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccddelete.x b/noao/imred/quadred/src/ccdproc/ccddelete.x
new file mode 100644
index 00000000..90931135
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccddelete.x
@@ -0,0 +1,55 @@
+# CCDDELETE -- Delete an image by renaming it to a backup image.
+#
+# 1. Get the backup prefix which may be a path name.
+# 2. If no prefix is specified then delete the image without a backup.
+# 3. If there is a prefix then make a backup image name.
+# Rename the image to the backup image name.
+#
+# The backup image name is formed by prepending the backup prefix to the
+# image name. If a previous backup exist append integers to the backup
+# prefix until a nonexistant image name is created.
+
+procedure ccddelete (image)
+
+char image[ARB] # Image to delete (backup)
+
+int i, imaccess()
+pointer sp, prefix, backup
+errchk imdelete, imrename
+
+begin
+ call smark (sp)
+ call salloc (prefix, SZ_FNAME, TY_CHAR)
+ call salloc (backup, SZ_FNAME, TY_CHAR)
+
+ # Get the backup prefix.
+ call clgstr ("backup", Memc[prefix], SZ_FNAME)
+ call xt_stripwhite (Memc[prefix])
+
+ # If there is no prefix then simply delete the image.
+ if (Memc[prefix] == EOS)
+ call imdelete (image)
+
+ # Otherwise create a backup image name which does not exist and
+ # rename the image to the backup image.
+
+ else {
+ i = 0
+ repeat {
+ if (i == 0) {
+ call sprintf (Memc[backup], SZ_FNAME, "%s%s")
+ call pargstr (Memc[prefix])
+ call pargstr (image)
+ } else {
+ call sprintf (Memc[backup], SZ_FNAME, "%s%d%s")
+ call pargstr (Memc[prefix])
+ call pargi (i)
+ call pargstr (image)
+ }
+ i = i + 1
+ } until (imaccess (Memc[backup], READ_ONLY) == NO)
+ call imrename (image, Memc[backup])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdflag.x b/noao/imred/quadred/src/ccdproc/ccdflag.x
new file mode 100644
index 00000000..427365d2
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdflag.x
@@ -0,0 +1,27 @@
+# CCDFLAG -- Determine if a CCD processing flag is set. This is less than
+# obvious because of the need to use the default value to indicate a
+# false flag.
+
+bool procedure ccdflag (im, name)
+
+pointer im # IMIO pointer
+char name[ARB] # CCD flag name
+
+bool flag, strne()
+pointer sp, str1, str2
+
+begin
+ call smark (sp)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+
+ # Get the flag string value and the default value.
+ # The flag is true if the value and the default do not match.
+
+ call hdmgstr (im, name, Memc[str1], SZ_LINE)
+ call hdmgdef (name, Memc[str2], SZ_LINE)
+ flag = strne (Memc[str1], Memc[str2])
+
+ call sfree (sp)
+ return (flag)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdlog.x b/noao/imred/quadred/src/ccdproc/ccdlog.x
new file mode 100644
index 00000000..48453704
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdlog.x
@@ -0,0 +1,46 @@
+include <imhdr.h>
+include <imset.h>
+
+# CCDLOG -- Log information about the processing with the image name.
+#
+# 1. If the package "verbose" parameter is set print the string preceded
+# by the image name.
+# 2. If the package "logfile" parameter is not null append the string,
+# preceded by the image name, to the file.
+
+procedure ccdlog (im, str)
+
+pointer im # IMIO pointer
+char str[ARB] # Log string
+
+int fd, open()
+bool clgetb()
+pointer sp, fname
+errchk open
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+
+ # Write to the standard error output if "verbose".
+ if (clgetb ("verbose")) {
+ call imstats (im, IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call eprintf ("%s: %s\n")
+ call pargstr (Memc[fname])
+ call pargstr (str)
+ }
+
+ # Append to the "logfile" if not null.
+ call clgstr ("logfile", Memc[fname], SZ_FNAME)
+ call xt_stripwhite (Memc[fname])
+ if (Memc[fname] != EOS) {
+ fd = open (Memc[fname], APPEND, TEXT_FILE)
+ call imstats (im, IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call fprintf (fd, "%s: %s\n")
+ call pargstr (Memc[fname])
+ call pargstr (str)
+ call close (fd)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdmean.x b/noao/imred/quadred/src/ccdproc/ccdmean.x
new file mode 100644
index 00000000..d38ea97b
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdmean.x
@@ -0,0 +1,50 @@
+include <imhdr.h>
+
+
+# CCDMEAN -- Compute mean and add to header if needed.
+
+procedure ccdmean (input)
+
+char input[ARB] # Input image
+
+int i, nc, nl, hdmgeti()
+long time, clktime()
+bool clgetb()
+real mean, hdmgetr(), asumr()
+pointer in, immap(), imgl2r()
+errchk immap
+
+begin
+ # Check if this operation has been done.
+
+ in = immap (input, READ_WRITE, 0)
+ ifnoerr (mean = hdmgetr (in, "ccdmean")) {
+ iferr (time = hdmgeti (in, "ccdmeant"))
+ time = IM_MTIME(in)
+ if (time >= IM_MTIME(in)) {
+ call imunmap (in)
+ return
+ }
+ }
+
+ if (clgetb ("noproc")) {
+ call eprintf (
+ " [TO BE DONE] Compute mean of image\n")
+ call pargstr (input)
+ call imunmap (in)
+ return
+ }
+
+ # Compute and record the mean.
+ nc = IM_LEN(in,1)
+ nl = IM_LEN(in,2)
+ mean = 0.
+ do i = 1, nl
+ mean = mean + asumr (Memr[imgl2r(in,i)], nc)
+ mean = mean / (nc * nl)
+ time = clktime (long(0))
+ call hdmputr (in, "ccdmean", mean)
+ call hdmputi (in, "ccdmeant", int (time))
+
+ call imunmap (in)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdnscan.x b/noao/imred/quadred/src/ccdproc/ccdnscan.x
new file mode 100644
index 00000000..3a9fbeba
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdnscan.x
@@ -0,0 +1,38 @@
+include "ccdtypes.h"
+
+
+# CCDNSCAN -- Return the number CCD scan rows.
+#
+# If not found in the header return the "nscan" parameter for objects and
+# 1 for calibration images.
+
+int procedure ccdnscan (im, ccdtype)
+
+pointer im #I Image
+int ccdtype #I CCD type
+int nscan #O Number of scan lines
+
+bool clgetb()
+char type, clgetc()
+int hdmgeti(), clgeti()
+
+begin
+ iferr (nscan = hdmgeti (im, "nscanrow")) {
+ switch (ccdtype) {
+ case ZERO, DARK, FLAT, ILLUM, FRINGE:
+ nscan = 1
+ default:
+ type = clgetc ("scantype")
+ if (type == 's')
+ nscan = clgeti ("nscan")
+ else {
+ if (clgetb ("scancor"))
+ nscan = INDEFI
+ else
+ nscan = 1
+ }
+ }
+ }
+
+ return (nscan)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdproc.par b/noao/imred/quadred/src/ccdproc/ccdproc.par
new file mode 100644
index 00000000..f20207a7
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdproc.par
@@ -0,0 +1,43 @@
+images,s,a,"",,,List of CCD images to correct
+ccdtype,s,h,"",,,CCD image type to correct
+max_cache,i,h,0,0,,Maximum image caching memory (in Mbytes)
+noproc,b,h,no,,,"List processing steps only?
+"
+fixpix,b,h,yes,,,Fix bad CCD lines and columns?
+overscan,b,h,yes,,,Apply overscan strip correction?
+trim,b,h,yes,,,Trim the image?
+zerocor,b,h,yes,,,Apply zero level correction?
+darkcor,b,h,no,,,Apply dark count correction?
+flatcor,b,h,yes,,,Apply flat field correction?
+illumcor,b,h,no,,,Apply illumination correction?
+fringecor,b,h,no,,,Apply fringe correction?
+readcor,b,h,no,,,Convert zero level image to readout correction?
+scancor,b,h,no,,,"Convert flat field image to scan correction?
+"
+readaxis,s,h,"line","column|line",, Read out axis (column|line)
+fixfile,s,h,"",,,File describing the bad lines and columns
+biassec,s,h,"",,,Overscan strip image section
+trimsec,s,h,"",,,Trim data section
+zero,s,h,"",,,Zero level calibration image
+dark,s,h,"",,,Dark count calibration image
+flat,s,h,"",,,Flat field images
+illum,s,h,"",,,Illumination correction images
+fringe,s,h,"",,,Fringe correction images
+minreplace,r,h,1.,,,Minimum flat field value
+scantype,s,h,"shortscan","shortscan|longscan",,Scan type (shortscan|longscan)
+nscan,i,h,1,1,,"Number of short scan lines
+"
+interactive,b,h,no,,,Fit overscan interactively?
+function,s,h,"legendre",,,Fitting function
+order,i,h,1,1,,Number of polynomial terms or spline pieces
+sample,s,h,"*",,,Sample points to fit
+naverage,i,h,1,,,Number of sample points to combine
+niterate,i,h,1,0,,Number of rejection iterations
+low_reject,r,h,3.,0.,,Low sigma rejection factor
+high_reject,r,h,3.,0.,,High sigma rejection factor
+grow,r,h,0.,0.,,"Rejection growing radius
+"
+verbose,b,h,)_.verbose,,,Print log information to the standard output?
+logfile,f,h,)_.logfile,,,Text log file
+backup,s,h,)_.backup,,,Backup directory or prefix
+output,s,h,"",,,Not used
diff --git a/noao/imred/quadred/src/ccdproc/ccdproc.x b/noao/imred/quadred/src/ccdproc/ccdproc.x
new file mode 100644
index 00000000..1b2a133c
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdproc.x
@@ -0,0 +1,106 @@
+include <error.h>
+include "ccdred.h"
+include "ccdtypes.h"
+
+# CCDPROC -- Process a CCD image of a specified CCD image type.
+#
+# The input image is corrected for bad pixels, overscan levels, zero
+# levels, dark counts, flat field, illumination, and fringing. It may also
+# be trimmed. The checking of whether to apply each correction, getting the
+# required parameters, and logging the operations is left to separate
+# procedures, one for each correction. The actual processing is done by
+# a specialized procedure designed to be very efficient. These
+# procedures may also process calibration images if necessary.
+# The specified image type overrides the image type in the image header.
+# There are two data type paths; one for short data types and one for
+# all other data types (usually real).
+
+procedure ccdproc (input, ccdtype)
+
+char input[ARB] # CCD image to process
+int ccdtype # CCD type of image (independent of header).
+
+pointer sp, output, str, in, out, ccd, immap()
+errchk immap, set_output, ccddelete
+errchk set_fixpix, set_zero, set_dark, set_flat, set_illum, set_fringe
+
+begin
+ call smark (sp)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Map the image, make a working output image and set the processing
+ # parameters.
+
+ in = immap (input, READ_ONLY, 0)
+ call mktemp ("tmp", Memc[output], SZ_FNAME)
+ call set_output (in, out, Memc[output])
+ call set_proc (in, out, ccd)
+ call set_sections (ccd)
+ call set_trim (ccd)
+ call set_fixpix (ccd)
+ call set_overscan (ccd)
+
+ # Set processing appropriate for the various image types.
+ switch (ccdtype) {
+ case ZERO:
+ case DARK:
+ call set_zero (ccd)
+ case FLAT:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ CORS(ccd, FINDMEAN) = YES
+ CORS(ccd, MINREP) = YES
+ case ILLUM:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ call set_flat (ccd)
+ case OBJECT, COMP:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ call set_flat (ccd)
+ call set_illum (ccd)
+ call set_fringe (ccd)
+ default:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ call set_flat (ccd)
+ call set_illum (ccd)
+ call set_fringe (ccd)
+ CORS(ccd, FINDMEAN) = YES
+ }
+
+ # Do the processing if the COR flag is set.
+ if (COR(ccd) == YES) {
+ call doproc (ccd)
+ call set_header (ccd)
+
+ # Replace the input by the output image.
+ call imunmap (in)
+ call imunmap (out)
+ iferr (call ccddelete (input)) {
+ call imdelete (Memc[output])
+ call error (1,
+ "Can't delete or make backup of original image")
+ }
+ call imrename (Memc[output], input)
+ } else {
+ # Delete the temporary output image leaving the input unchanged.
+ call imunmap (in)
+ iferr (call imunmap (out))
+ ;
+ iferr (call imdelete (Memc[output]))
+ ;
+ }
+ call free_proc (ccd)
+
+ # Do special processing for calibration images.
+ switch (ccdtype) {
+ case ZERO:
+ call readcor (input)
+ case FLAT:
+ call ccdmean (input)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdred.h b/noao/imred/quadred/src/ccdproc/ccdred.h
new file mode 100644
index 00000000..ef41f592
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdred.h
@@ -0,0 +1,155 @@
+# CCDRED Data Structures and Definitions
+
+# The CCD structure: This structure is used to communicate processing
+# parameters between the package procedures. It contains pointers to
+# data, calibration image IMIO pointers, scaling parameters, and the
+# correction flags. The corrections flags indicate which processing
+# operations are to be performed. The subsection parameters do not
+# include a step size. A step size is assumed. If arbitrary subsampling
+# is desired this would be the next generalization.
+
+define LEN_CCD 75 # Length of CCD structure
+
+# CCD data coordinates
+define CCD_C1 Memi[$1] # CCD starting column
+define CCD_C2 Memi[$1+1] # CCD ending column
+define CCD_L1 Memi[$1+2] # CCD starting line
+define CCD_L2 Memi[$1+3] # CCD ending line
+
+# Input data
+define IN_IM Memi[$1+4] # Input image pointer
+define IN_C1 Memi[$1+5] # Input data starting column
+define IN_C2 Memi[$1+6] # Input data ending column
+define IN_L1 Memi[$1+7] # Input data starting line
+define IN_L2 Memi[$1+8] # Input data ending line
+define IN_NSEC Memi[$1+71] # Number of input pieces
+define IN_SEC Memi[$1+72] # Pointer to sections (c1,c2,l1,l2)xn
+
+# Output data
+define OUT_IM Memi[$1+9] # Output image pointer
+define OUT_C1 Memi[$1+10] # Output data starting column
+define OUT_C2 Memi[$1+11] # Output data ending column
+define OUT_L1 Memi[$1+12] # Output data starting line
+define OUT_L2 Memi[$1+13] # Output data ending line
+define OUT_SEC Memi[$1+73] # Pointer to sections (c1,c2,l1,l2)xn
+
+# Zero level data
+define ZERO_IM Memi[$1+14] # Zero level image pointer
+define ZERO_C1 Memi[$1+15] # Zero level data starting column
+define ZERO_C2 Memi[$1+16] # Zero level data ending column
+define ZERO_L1 Memi[$1+17] # Zero level data starting line
+define ZERO_L2 Memi[$1+18] # Zero level data ending line
+
+# Dark count data
+define DARK_IM Memi[$1+19] # Dark count image pointer
+define DARK_C1 Memi[$1+20] # Dark count data starting column
+define DARK_C2 Memi[$1+21] # Dark count data ending column
+define DARK_L1 Memi[$1+22] # Dark count data starting line
+define DARK_L2 Memi[$1+23] # Dark count data ending line
+
+# Flat field data
+define FLAT_IM Memi[$1+24] # Flat field image pointer
+define FLAT_C1 Memi[$1+25] # Flat field data starting column
+define FLAT_C2 Memi[$1+26] # Flat field data ending column
+define FLAT_L1 Memi[$1+27] # Flat field data starting line
+define FLAT_L2 Memi[$1+28] # Flat field data ending line
+
+# Illumination data
+define ILLUM_IM Memi[$1+29] # Illumination image pointer
+define ILLUM_C1 Memi[$1+30] # Illumination data starting column
+define ILLUM_C2 Memi[$1+31] # Illumination data ending column
+define ILLUM_L1 Memi[$1+32] # Illumination data starting line
+define ILLUM_L2 Memi[$1+33] # Illumination data ending line
+
+# Fringe data
+define FRINGE_IM Memi[$1+34] # Fringe image pointer
+define FRINGE_C1 Memi[$1+35] # Fringe data starting column
+define FRINGE_C2 Memi[$1+36] # Fringe data ending column
+define FRINGE_L1 Memi[$1+37] # Fringe data starting line
+define FRINGE_L2 Memi[$1+38] # Fringe data ending line
+
+# Trim section
+define TRIM_C1 Memi[$1+39] # Trim starting column
+define TRIM_C2 Memi[$1+40] # Trim ending column
+define TRIM_L1 Memi[$1+41] # Trim starting line
+define TRIM_L2 Memi[$1+42] # Trim ending line
+
+# Bias section
+define BIAS_C1 Memi[$1+43] # Bias starting column
+define BIAS_C2 Memi[$1+44] # Bias ending column
+define BIAS_L1 Memi[$1+45] # Bias starting line
+define BIAS_L2 Memi[$1+46] # Bias ending line
+define BIAS_SEC Memi[$1+74] # Multiple bias sections
+
+define READAXIS Memi[$1+47] # Read out axis (1=cols, 2=lines)
+define CALCTYPE Memi[$1+48] # Calculation data type
+define NBADCOLS Memi[$1+49] # Number of column interpolation regions
+define BADCOLS Memi[$1+50] # Pointer to col interpolation regions
+define NBADLINES Memi[$1+51] # Number of line interpolation regions
+define BADLINES Memi[$1+52] # Pointer to line interpolation regions
+define OVERSCAN_VEC Memi[$1+53] # Pointer to overscan vector
+define DARKSCALE Memr[P2R($1+54)] # Dark count scale factor
+define FRINGESCALE Memr[P2R($1+55)] # Fringe scale factor
+define FLATSCALE Memr[P2R($1+56)] # Flat field scale factor
+define ILLUMSCALE Memr[P2R($1+57)] # Illumination scale factor
+define MINREPLACE Memr[P2R($1+58)] # Minimum replacement value
+define MEAN Memr[P2R($1+59)] # Mean of output image
+define COR Memi[$1+60] # Overall correction flag
+define CORS Memi[$1+61+($2-1)] # Individual correction flags
+
+# Individual components of input, output, and bias section pieces.
+define IN_SC1 Memi[IN_SEC($1)+4*$2-4]
+define IN_SC2 Memi[IN_SEC($1)+4*$2-3]
+define IN_SL1 Memi[IN_SEC($1)+4*$2-2]
+define IN_SL2 Memi[IN_SEC($1)+4*$2-1]
+define OUT_SC1 Memi[OUT_SEC($1)+4*$2-4]
+define OUT_SC2 Memi[OUT_SEC($1)+4*$2-3]
+define OUT_SL1 Memi[OUT_SEC($1)+4*$2-2]
+define OUT_SL2 Memi[OUT_SEC($1)+4*$2-1]
+define BIAS_SC1 Memi[BIAS_SEC($1)+4*$2-4]
+define BIAS_SC2 Memi[BIAS_SEC($1)+4*$2-3]
+define BIAS_SL1 Memi[BIAS_SEC($1)+4*$2-2]
+define BIAS_SL2 Memi[BIAS_SEC($1)+4*$2-1]
+
+# The correction array contains the following elements with array indices
+# given by the macro definitions.
+
+define NCORS 10 # Number of corrections
+
+define FIXPIX 1 # Fix bad pixels
+define TRIM 2 # Trim image
+define OVERSCAN 3 # Apply overscan correction
+define ZEROCOR 4 # Apply zero level correction
+define DARKCOR 5 # Apply dark count correction
+define FLATCOR 6 # Apply flat field correction
+define ILLUMCOR 7 # Apply illumination correction
+define FRINGECOR 8 # Apply fringe correction
+define FINDMEAN 9 # Find the mean of the output image
+define MINREP 10 # Check and replace minimum value
+
+# The following definitions identify the correction values in the correction
+# array. They are defined in terms of bit fields so that it is possible to
+# add corrections to form unique combination corrections. Some of
+# these combinations are implemented as compound operations for efficiency.
+
+define O 001B # overscan
+define Z 002B # zero level
+define D 004B # dark count
+define F 010B # flat field
+define I 020B # Illumination
+define Q 040B # Fringe
+
+# The following correction combinations are recognized.
+
+define ZO 003B # zero level + overscan
+define DO 005B # dark count + overscan
+define DZ 006B # dark count + zero level
+define DZO 007B # dark count + zero level + overscan
+define FO 011B # flat field + overscan
+define FZ 012B # flat field + zero level
+define FZO 013B # flat field + zero level + overscan
+define FD 014B # flat field + dark count
+define FDO 015B # flat field + dark count + overscan
+define FDZ 016B # flat field + dark count + zero level
+define FDZO 017B # flat field + dark count + zero level + overscan
+define QI 060B # fringe + illumination
diff --git a/noao/imred/quadred/src/ccdproc/ccdsection.x b/noao/imred/quadred/src/ccdproc/ccdsection.x
new file mode 100644
index 00000000..aced216a
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdsection.x
@@ -0,0 +1,100 @@
+include <ctype.h>
+
+# CCD_SECTION -- Parse a 2D image section into its elements.
+# 1. The default values must be set by the caller.
+# 2. A null image section is OK.
+# 3. The first nonwhitespace character must be '['.
+# 4. The last interpreted character must be ']'.
+#
+# This procedure should be replaced with an IMIO procedure at some
+# point.
+
+procedure ccd_section (section, x1, x2, xstep, y1, y2, ystep)
+
+char section[ARB] # Image section
+int x1, x2, xstep # X image section parameters
+int y1, y2, ystep # X image section parameters
+
+int i, ip, a, b, c, temp, ctoi()
+define error_ 99
+
+begin
+ # Decode the section string.
+ ip = 1
+ while (IS_WHITE(section[ip]))
+ ip = ip + 1
+ if (section[ip] == '[')
+ ip = ip + 1
+ else if (section[ip] == EOS)
+ return
+ else
+ goto error_
+
+ do i = 1, 2 {
+ while (IS_WHITE(section[ip]))
+ ip = ip + 1
+
+ # Default values
+ if (i == 1) {
+ a = x1
+ b = x2
+ c = xstep
+ } else {
+ a = y1
+ b = y2
+ c = ystep
+ }
+
+ # Get a:b:c. Allow notation such as "-*:c"
+ # (or even "-:c") where the step is obviously negative.
+
+ if (ctoi (section, ip, temp) > 0) { # a
+ a = temp
+ if (section[ip] == ':') {
+ ip = ip + 1
+ if (ctoi (section, ip, b) == 0) # a:b
+ goto error_
+ } else
+ b = a
+ } else if (section[ip] == '-') { # -*
+ temp = a
+ a = b
+ b = temp
+ ip = ip + 1
+ if (section[ip] == '*')
+ ip = ip + 1
+ } else if (section[ip] == '*') # *
+ ip = ip + 1
+ if (section[ip] == ':') { # ..:step
+ ip = ip + 1
+ if (ctoi (section, ip, c) == 0)
+ goto error_
+ else if (c == 0)
+ goto error_
+ }
+ if (a > b && c > 0)
+ c = -c
+
+ if (i == 1) {
+ x1 = a
+ x2 = b
+ xstep = c
+ } else {
+ y1 = a
+ y2 = b
+ ystep = c
+ }
+
+ while (IS_WHITE(section[ip]))
+ ip = ip + 1
+ if (section[ip] == ',')
+ ip = ip + 1
+ }
+
+ if (section[ip] != ']')
+ goto error_
+
+ return
+error_
+ call error (0, "Error in image section specification")
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdsubsets.x b/noao/imred/quadred/src/ccdproc/ccdsubsets.x
new file mode 100644
index 00000000..6152897f
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdsubsets.x
@@ -0,0 +1,92 @@
+# CCDSUBSET -- Return the CCD subset identifier.
+#
+# 1. Get the subset string and search the subset record file for the ID string.
+# 2. If the subset string is not in the record file define a default ID string
+# based on the first word of the subset string. If the first word is not
+# unique append a integer to the first word until it is unique.
+# 3. Add the new subset string and identifier to the record file.
+# 4. Since the ID string is used to generate image names replace all
+# nonimage name characters with '_'.
+#
+# It is an error if the record file cannot be created or written when needed.
+
+procedure ccdsubset (im, subset, sz_name)
+
+pointer im # Image
+char subset[sz_name] # CCD subset identifier
+int sz_name # Size of subset string
+
+bool streq()
+int i, fd, ctowrd(), open(), fscan()
+pointer sp, fname, str1, str2, subset1, subset2, subset3
+errchk open
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+ call salloc (subset1, SZ_LINE, TY_CHAR)
+ call salloc (subset2, SZ_LINE, TY_CHAR)
+ call salloc (subset3, SZ_LINE, TY_CHAR)
+
+ # Get the subset record file and the subset string.
+ call clgstr ("ssfile", Memc[fname], SZ_LINE)
+ call hdmgstr (im, "subset", Memc[str1], SZ_LINE)
+
+ # The default subset identifier is the first word of the subset string.
+ i = 1
+ i = ctowrd (Memc[str1], i, Memc[subset1], SZ_LINE)
+
+ # A null subset string is ok. If not null check for conflict
+ # with previous subset IDs.
+ if (Memc[str1] != EOS) {
+ call strcpy (Memc[subset1], Memc[subset3], SZ_LINE)
+
+ # Search the subset record file for the same subset string.
+ # If found use the ID string. If the subset ID has been
+ # used for another subset string then increment an integer
+ # suffix to the default ID and check the list again.
+
+ i = 1
+ ifnoerr (fd = open (Memc[fname], READ_ONLY, TEXT_FILE)) {
+ while (fscan (fd) != EOF) {
+ call gargwrd (Memc[str2], SZ_LINE)
+ call gargwrd (Memc[subset2], SZ_LINE)
+ if (streq (Memc[str1], Memc[str2])) {
+ i = 0
+ call strcpy (Memc[subset2], Memc[subset1], SZ_LINE)
+ break
+ } if (streq (Memc[subset1], Memc[subset2])) {
+ call sprintf (Memc[subset1], SZ_LINE, "%s%d")
+ call pargstr (Memc[subset3])
+ call pargi (i)
+ i = i + 1
+ call seek (fd, BOF)
+ }
+ }
+ call close (fd)
+ }
+
+ # If the subset is not in the record file add it.
+ if (i > 0) {
+ fd = open (Memc[fname], APPEND, TEXT_FILE)
+ call fprintf (fd, "'%s'\t%s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[subset1])
+ call close (fd)
+ }
+ }
+
+ # Set the subset ID string and replace magic characters by '_'
+ # since the subset ID is used in forming image names.
+
+ call strcpy (Memc[subset1], subset, sz_name)
+ for (i=1; subset[i]!=EOS; i=i+1)
+ switch (subset[i]) {
+ case '-','+','?','*','[',']',' ','\t':
+ subset[i] = '_'
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/ccdtypes.h b/noao/imred/quadred/src/ccdproc/ccdtypes.h
new file mode 100644
index 00000000..0d5d4caf
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdtypes.h
@@ -0,0 +1,14 @@
+# Standard CCD image types.
+
+define CCDTYPES "|object|zero|dark|flat|illum|fringe|other|comp|"
+
+define NONE -1
+define UNKNOWN 0
+define OBJECT 1
+define ZERO 2
+define DARK 3
+define FLAT 4
+define ILLUM 5
+define FRINGE 6
+define OTHER 7
+define COMP 8
diff --git a/noao/imred/quadred/src/ccdproc/ccdtypes.x b/noao/imred/quadred/src/ccdproc/ccdtypes.x
new file mode 100644
index 00000000..bf6d29e2
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/ccdtypes.x
@@ -0,0 +1,72 @@
+include "ccdtypes.h"
+
+# CCDTYPES -- Return the CCD type name string.
+# CCDTYPEI -- Return the CCD type code.
+
+
+# CCDTYPES -- Return the CCD type name string.
+
+procedure ccdtypes (im, name, sz_name)
+
+pointer im # Image
+char name[sz_name] # CCD type name
+int sz_name # Size of name string
+
+int strdic()
+pointer sp, str
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the image type string. If none then return "none".
+ # Otherwise get the corresponding package image type string.
+ # If the image type is unknown return "unknown" otherwise return
+ # the package name.
+
+ call hdmgstr (im, "imagetyp", Memc[str], SZ_LINE)
+ if (Memc[str] == EOS) {
+ call strcpy ("none", name, sz_name)
+ } else {
+ call hdmname (Memc[str], name, sz_name)
+ if (name[1] == EOS)
+ call strcpy (Memc[str], name, sz_name)
+ if (strdic (name, name, sz_name, CCDTYPES) == UNKNOWN)
+ call strcpy ("unknown", name, sz_name)
+ }
+
+ call sfree (sp)
+end
+
+
+# CCDTYPEI -- Return the CCD type code.
+
+int procedure ccdtypei (im)
+
+pointer im # Image
+int ccdtype # CCD type (returned)
+
+pointer sp, str1, str2
+int strdic()
+
+begin
+ call smark (sp)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+
+ # Get the image type and if there is none then return the NONE code.
+ call hdmgstr (im, "imagetyp", Memc[str1], SZ_LINE)
+ if (Memc[str1] == EOS) {
+ ccdtype = NONE
+
+ # Otherwise get the package type and convert to an image type code.
+ } else {
+ call hdmname (Memc[str1], Memc[str2], SZ_LINE)
+ if (Memc[str2] == EOS)
+ call strcpy (Memc[str1], Memc[str2], SZ_LINE)
+ ccdtype = strdic (Memc[str2], Memc[str2], SZ_LINE, CCDTYPES)
+ }
+
+ call sfree (sp)
+ return (ccdtype)
+end
diff --git a/noao/imred/quadred/src/ccdproc/cor.gx b/noao/imred/quadred/src/ccdproc/cor.gx
new file mode 100644
index 00000000..189f9437
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/cor.gx
@@ -0,0 +1,362 @@
+include "ccdred.h"
+
+
+.help cor Feb87 noao.imred.ccdred
+.nf ----------------------------------------------------------------------------
+cor -- Process CCD image lines
+
+These procedures are the heart of the CCD processing. They do the desired
+set of processing operations on the image line data as efficiently as
+possible. They are called by the PROC procedures. There are four procedures
+one for each readout axis and one for short and real image data.
+Some sets of operations are coded as single compound operations for efficiency.
+To keep the number of combinations managable only the most common
+combinations are coded as compound operations. The combinations
+consist of any set of line overscan, column overscan, zero level, dark
+count, and flat field and any set of illumination and fringe
+correction. The corrections are applied in place to the output vector.
+
+The column readout procedure is more complicated in order to handle
+zero level and flat field corrections specified as one dimensional
+readout corrections instead of two dimensional calibration images.
+Column readout format is probably extremely rare and the 1D readout
+corrections are used only for special types of data.
+.ih
+SEE ALSO
+proc, ccdred.h
+.endhelp -----------------------------------------------------------------------
+
+$for (sr)
+# COR1 -- Correct image lines with readout axis 1 (lines).
+
+procedure cor1$t (cors, out, overscan, zero, dark, flat, illum,
+ fringe, n, darkscale, flatscale, illumscale, frgscale)
+
+int cors[ARB] # Correction flags
+PIXEL out[n] # Output data
+real overscan # Overscan value
+PIXEL zero[n] # Zero level correction
+PIXEL dark[n] # Dark count correction
+PIXEL flat[n] # Flat field correction
+PIXEL illum[n] # Illumination correction
+PIXEL fringe[n] # Fringe correction
+int n # Number of pixels
+real darkscale # Dark count scale factor
+real flatscale # Flat field scale factor
+real illumscale # Illumination scale factor
+real frgscale # Fringe scale factor
+
+int i, op
+
+begin
+ op = cors[OVERSCAN] + cors[ZEROCOR] + cors[DARKCOR] + cors[FLATCOR]
+ switch (op) {
+ case O: # overscan
+ do i = 1, n
+ out[i] = out[i] - overscan
+ case Z: # zero level
+ do i = 1, n
+ out[i] = out[i] - zero[i]
+
+ case ZO: # zero level + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - zero[i]
+
+ case D: # dark count
+ do i = 1, n
+ out[i] = out[i] - darkscale * dark[i]
+ case DO: # dark count + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - darkscale * dark[i]
+ case DZ: # dark count + zero level
+ do i = 1, n
+ out[i] = out[i] - zero[i] - darkscale * dark[i]
+ case DZO: # dark count + zero level + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - zero[i] - darkscale * dark[i]
+
+ case F: # flat field
+ do i = 1, n
+ out[i] = out[i] * flatscale / flat[i]
+ case FO: # flat field + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan) * flatscale / flat[i]
+ case FZ: # flat field + zero level
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatscale / flat[i]
+ case FZO: # flat field + zero level + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - zero[i]) * flatscale /
+ flat[i]
+ case FD: # flat field + dark count
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatscale / flat[i]
+ case FDO: # flat field + dark count + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - darkscale * dark[i]) *
+ flatscale / flat[i]
+ case FDZ: # flat field + dark count + zero level
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ case FDZO: # flat field + dark count + zero level + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - zero[i] -
+ darkscale * dark[i]) * flatscale / flat[i]
+ }
+
+ # Often these operations will not be performed so test for no
+ # correction rather than go through the switch.
+
+ op = cors[ILLUMCOR] + cors[FRINGECOR]
+ if (op != 0) {
+ switch (op) {
+ case I: # illumination
+ do i = 1, n
+ out[i] = out[i] * illumscale / illum[i]
+ case Q: # fringe
+ do i = 1, n
+ out[i] = out[i] - frgscale * fringe[i]
+ case QI: # fringe + illumination
+ do i = 1, n
+ out[i] = out[i]*illumscale/illum[i] - frgscale*fringe[i]
+ }
+ }
+end
+
+
+# COR2 -- Correct lines for readout axis 2 (columns). This procedure is
+# more complex than when the readout is along the image lines because the
+# zero level and/or flat field corrections may be single readout column
+# vectors.
+
+procedure cor2$t (line, cors, out, overscan, zero, dark, flat, illum,
+ fringe, n, zeroim, flatim, darkscale, flatscale, illumscale, frgscale)
+
+int line # Line to be corrected
+int cors[ARB] # Correction flags
+PIXEL out[n] # Output data
+real overscan[n] # Overscan value
+PIXEL zero[n] # Zero level correction
+PIXEL dark[n] # Dark count correction
+PIXEL flat[n] # Flat field correction
+PIXEL illum[n] # Illumination correction
+PIXEL fringe[n] # Fringe correction
+int n # Number of pixels
+pointer zeroim # Zero level IMIO pointer (NULL if 1D vector)
+pointer flatim # Flat field IMIO pointer (NULL if 1D vector)
+real darkscale # Dark count scale factor
+real flatscale # Flat field scale factor
+real illumscale # Illumination scale factor
+real frgscale # Fringe scale factor
+
+PIXEL zeroval
+real flatval
+int i, op
+
+begin
+ op = cors[OVERSCAN] + cors[ZEROCOR] + cors[DARKCOR] + cors[FLATCOR]
+ switch (op) {
+ case O: # overscan
+ do i = 1, n
+ out[i] = out[i] - overscan[i]
+ case Z: # zero level
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - zero[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - zeroval
+ }
+
+ case ZO: # zero level + overscan
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zero[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zeroval
+ }
+
+ case D: # dark count
+ do i = 1, n
+ out[i] = out[i] - darkscale * dark[i]
+ case DO: # dark count + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - darkscale * dark[i]
+ case DZ: # dark count + zero level
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - zero[i] - darkscale * dark[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - zeroval - darkscale * dark[i]
+ }
+ case DZO: # dark count + zero level + overscan
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]
+ }
+
+ case F: # flat field
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = out[i] * flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = out[i] * flatval
+ }
+ case FO: # flat field + overscan
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i]) * flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i]) * flatval
+ }
+ case FZ: # flat field + zero level
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval) * flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval) * flatval
+ }
+ }
+ case FZO: # flat field + zero level + overscan
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i]) *
+ flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval) *
+ flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval) * flatval
+ }
+ }
+ case FD: # flat field + dark count
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatscale/flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatval
+ }
+ case FDO: # flat field + dark count + overscan
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - darkscale * dark[i]) *
+ flatval
+ }
+ case FDZ: # flat field + dark count + zero level
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval - darkscale * dark[i]) *
+ flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval - darkscale * dark[i]) *
+ flatval
+ }
+ }
+ case FDZO: # flat field + dark count + zero level + overscan
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]) * flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]) * flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]) * flatval
+ }
+ }
+ }
+
+ # Often these operations will not be performed so test for no
+ # correction rather than go through the switch.
+
+ op = cors[ILLUMCOR] + cors[FRINGECOR]
+ if (op != 0) {
+ switch (op) {
+ case I: # illumination
+ do i = 1, n
+ out[i] = out[i] * illumscale / illum[i]
+ case Q: # fringe
+ do i = 1, n
+ out[i] = out[i] - frgscale * fringe[i]
+ case QI: # fringe + illumination
+ do i = 1, n
+ out[i] = out[i]*illumscale/illum[i] - frgscale*fringe[i]
+ }
+ }
+end
+$endfor
diff --git a/noao/imred/quadred/src/ccdproc/corinput.gx b/noao/imred/quadred/src/ccdproc/corinput.gx
new file mode 100644
index 00000000..241cc34d
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/corinput.gx
@@ -0,0 +1,220 @@
+include <imhdr.h>
+include "ccdred.h"
+
+$for (sr)
+# CORINPUT -- Get an input image line, fix the bad pixels, and trim.
+# Return the corrected input line in the output array.
+
+procedure corinput$t (in, line, ccd, output, ncols)
+
+pointer in # Input IMIO pointer
+int line # Corrected output line
+pointer ccd # CCD pointer
+PIXEL output[ncols] # Output data (returned)
+int ncols # Number of output columns
+
+int i, inline
+pointer inbuf, imgl2$t()
+
+begin
+ # Determine the input line in terms of the trimmed output line.
+ if (IN_SEC(ccd) == NULL)
+ inline = IN_L1(ccd) + line - 1
+ else {
+ do i = 1, IN_NSEC(ccd) {
+ if (line < OUT_SL1(ccd,i) || line > OUT_SL2(ccd,i))
+ next
+ inline = IN_SL1(ccd,i) + line - OUT_SL1(ccd,i)
+ break
+ }
+ }
+
+ # If there are bad lines call a procedure to fix them. Otherwise
+ # read the image line directly.
+
+ if (NBADLINES(ccd) != 0)
+ call lfix$t (in, inline, Mems[BADLINES(ccd)], IM_LEN(in,1),
+ IM_LEN(in,2), NBADLINES(ccd), inbuf)
+ else
+ inbuf = imgl2$t (in, inline)
+
+ # IF there are bad columns call a procedure to fix them.
+ if (NBADCOLS(ccd) != 0)
+ call cfix$t (inline, Mems[BADCOLS(ccd)], IM_LEN(in,1),
+ IM_LEN(in,2), NBADCOLS(ccd), Mem$t[inbuf])
+
+ # Move the pixels to the output line.
+ if (IN_SEC(ccd) == NULL)
+ call amov$t (Mem$t[inbuf+IN_C1(ccd)-OUT_C1(ccd)], output, ncols)
+ else {
+ do i = 1, IN_NSEC(ccd) {
+ if (inline < IN_SL1(ccd,i) || inline > IN_SL2(ccd,i))
+ next
+ call amov$t (Mem$t[inbuf+IN_SC1(ccd,i)-OUT_C1(ccd)],
+ output[OUT_SC1(ccd,i)], OUT_SC2(ccd,i)-OUT_SC1(ccd,i)+1)
+ }
+ }
+end
+
+
+# CFIX -- Interpolate across bad columns defined in the bad column array.
+
+procedure cfix$t (line, badcols, ncols, nlines, nbadcols, data)
+
+int line # Line to be fixed
+short badcols[2, nlines, nbadcols] # Bad column array
+int ncols # Number of columns
+int nlines # Number of lines
+int nbadcols # Number of bad column regions
+PIXEL data[ncols] # Data to be fixed
+
+PIXEL val
+real del
+int i, j, col1, col2
+
+begin
+ do i = 1, nbadcols {
+ col1 = badcols[1, line, i]
+ if (col1 == 0) # No bad columns
+ return
+ col2 = badcols[2, line, i]
+ if (col1 == 1) { # Bad first column
+ val = data[col2+1]
+ do j = col1, col2
+ data[j] = val
+ } else if (col2 == ncols) { # Bad last column
+ val = data[col1-1]
+ do j = col1, col2
+ data[j] = val
+ } else { # Interpolate
+ del = (data[col2+1] - data[col1-1]) / (col2 - col1 + 2)
+ val = data[col1-1] + del
+ do j = col1, col2
+ data[j] = val + (j - col1) * del
+ }
+ }
+end
+
+
+# LFIX -- Get image line and replace bad pixels by interpolation from
+# neighboring lines. Internal buffers are used to keep the last fixed
+# line and the next good line. They are allocated with LFIXINIT and
+# freed with LFIXFREE.
+
+procedure lfix$t (im, line, badlines, ncols, nlines, nbadlines, data)
+
+pointer im # IMIO pointer
+int line # Line to be obtained and fixed
+short badlines[2,nlines,nbadlines] # Bad line region array
+int ncols # Number of columns in image
+int nlines # Number of lines in images
+int nbadlines # Number of bad line regions
+pointer data # Data line pointer (returned)
+
+real wt1, wt2
+int i, nextgood, lastgood, col1, col2
+pointer imgl2$t()
+
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ # If this line has bad pixels replace them. Otherwise just
+ # read the line.
+
+ if (badlines[1, line, 1] != 0) {
+ # Save the last line which has already been fixed.
+ if (line != 1)
+ call amov$t (Mem$t[data], Mem$t[lastbuf], ncols)
+
+ # Determine the next line with no bad line pixels. Note that
+ # this requirement is overly strict since the bad columns
+ # may not be the same in neighboring lines.
+
+ nextgood = 0
+ do i = line+1, nlines {
+ if (badlines[1, i, 1] == 0) {
+ nextgood = i
+ break
+ }
+ }
+
+ # If the next good line is not the same as previously
+ # read the data line and store it in a buffer.
+
+ if ((nextgood != lastgood) && (nextgood != 0)) {
+ data = imgl2$t (im, nextgood)
+ call amov$t (Mem$t[data], Mem$t[nextbuf], ncols)
+ lastgood = nextgood
+ }
+
+ # Get the data line.
+ data = imgl2$t (im, line)
+
+ # Interpolate the bad columns. At the ends of the image use
+ # extension otherwise use linear interpolation.
+
+ if (line == 1) { # First line is bad
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i]
+ call amov$t (Mem$t[nextbuf+col1], Mem$t[data+col1],
+ col2-col1)
+ }
+ } else if (nextgood == 0) { # Last line is bad
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i]
+ call amov$t (Mem$t[lastbuf+col1], Mem$t[data+col1],
+ col2-col1)
+ }
+ } else { # Interpolate
+ wt1 = 1. / (nextgood - line + 1)
+ wt2 = 1. - wt1
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i] - 1
+ call awsu$t (Mem$t[nextbuf+col1], Mem$t[lastbuf+col1],
+ Mem$t[data+col1], col2-col1+1, wt1, wt2)
+ }
+ }
+ } else
+ data = imgl2$t (im, line)
+end
+
+
+# LFIXINIT -- Allocate internal buffers.
+
+procedure lfixinit$t (im)
+
+pointer im # IMIO pointer
+
+int lastgood
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ call malloc (lastbuf, IM_LEN(im,1), TY_PIXEL)
+ call malloc (nextbuf, IM_LEN(im,1), TY_PIXEL)
+ lastgood=0
+end
+
+# LFIXFREE -- Free memory when the last line has been obtained.
+
+procedure lfixfree$t ()
+
+int lastgood
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ call mfree (lastbuf, TY_PIXEL)
+ call mfree (nextbuf, TY_PIXEL)
+end
+$endfor
diff --git a/noao/imred/quadred/src/ccdproc/doc/ccdproc.hlp b/noao/imred/quadred/src/ccdproc/doc/ccdproc.hlp
new file mode 100644
index 00000000..e942a299
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/doc/ccdproc.hlp
@@ -0,0 +1,778 @@
+.help ccdproc Aug01 noao.imred.quadred
+.ih
+NAME
+ccdproc -- Process CCD images
+.ih
+SYNOPSIS
+This is the main processing task for CCD data in single image or
+\fBquadformat\fR image formats.
+.ih
+USAGE
+ccdproc images
+.ih
+PARAMETERS
+.ls images
+List of input CCD images to process. The list may include processed
+images and calibration images.
+.le
+.ls output = ""
+List of output images. If no list is given then the processing will replace
+the input images with the processed images. If a list is given it must
+match the input image list. \fINote that any dependent calibration images
+still be processed in-place with optional backup.\fR
+.le
+.ls ccdtype = ""
+CCD image type to select from the input image list. If no type is given
+then all input images will be selected. The recognized types are described
+in \fBccdtypes\fR.
+.le
+.ls max_cache = 0
+Maximum image caching memory (in Mbytes). If there is sufficient memory
+the calibration images, such as zero level, dark count, and flat fields,
+will be cached in memory when processing many input images. This
+reduces the disk I/O and makes the task run a little faster. If the
+value is zero image caching is not used.
+.le
+.ls noproc = no
+List processing steps only?
+.le
+
+.ce
+PROCESSING SWITCHES
+.ls fixpix = yes
+Fix bad CCD lines and columns by linear interpolation from neighboring
+lines and columns? If yes then a bad pixel mask, image, or file must be
+specified.
+.le
+.ls overscan = yes
+Apply overscan or prescan bias correction? If yes then the overscan
+image section and the readout axis must be specified.
+.le
+.ls trim = yes
+Trim the image of the overscan region and bad edge lines and columns?
+If yes then the trim section must be specified.
+.le
+.ls zerocor = yes
+Apply zero level correction? If yes a zero level image must be specified.
+.le
+.ls darkcor = yes
+Apply dark count correction? If yes a dark count image must be specified.
+.le
+.ls flatcor = yes
+Apply flat field correction? If yes flat field images must be specified.
+.le
+.ls illumcor = no
+Apply iillumination correction? If yes iillumination images must be specified.
+.le
+.ls fringecor = no
+Apply fringe correction? If yes fringe images must be specified.
+.le
+.ls readcor = no
+Convert zero level images to readout correction images? If yes then
+zero level images are averaged across the readout axis to form one
+dimensional zero level readout correction images.
+.le
+.ls scancor = no
+Convert zero level, dark count and flat field images to scan mode flat
+field images? If yes then the form of scan mode correction is specified by
+the parameter \fIscantype\fR.
+.le
+
+.ce
+PROCESSING PARAMETERS
+.ls readaxis = "line"
+Read out axis specified as "line" or "column".
+.le
+.ls fixfile
+Bad pixel mask, image, or file. If "image" is specified then the name is
+specified in the image header or instrument translation file. If "BPM" is
+specified then the standard BPM image header keyword defines a bad pixel
+mask. A bad pixel mask is a compact format (".pl" extension) with zero
+values indicating good pixels and non-zero values indicating bad pixels. A
+bad pixel image is a regular image in which zero values are good pixels and
+non-zero values are bad pixels. A bad pixel file specifies bad pixels or
+rectangular bad pixel regions as described later. The direction of
+interpolation is determined by the mask value with a value of two
+interpolating across columns, a value of three interpolating across lines,
+and any other non-zero value interpolating along the narrowest dimension.
+.le
+.ls biassec
+Overscan bias strip image section. If "image" is specified then the overscan
+bias section is specified in the image header or instrument translation file.
+Only the part of the bias section along the readout axis is used. The
+length of the bias region fit is defined by the trim section. If one
+wants to limit the region of the overscan used in the fit to be less
+than that of the trim section then the sample region parameter,
+\fIsample\fR, should be used. It is an error if no section or the
+whole image is specified.
+.le
+.ls trimsec
+Image section for trimming. If "image" is specified then the trim image
+section is specified in the image header or instrument translation file.
+However, for \fIquadformat\fR data this parameter is not used and the trim
+sections are assumed to be in the image header.
+.le
+.ls zero = ""
+Zero level calibration image. The zero level image may be one or two
+dimensional. The CCD image type and subset are not checked for these
+images and they take precedence over any zero level calibration images
+given in the input list.
+.le
+.ls dark = ""
+Dark count calibration image. The CCD image type and subset are not checked
+for these images and they take precedence over any dark count calibration
+images given in the input list.
+.le
+.ls flat = ""
+Flat field calibration images. The flat field images may be one or
+two dimensional. The CCD image type is not checked for these
+images and they take precedence over any flat field calibration images given
+in the input list. The flat field image with the same subset as the
+input image being processed is selected.
+.le
+.ls illum = ""
+Iillumination correction images. The CCD image type is not checked for these
+images and they take precedence over any iillumination correction images given
+in the input list. The iillumination image with the same subset as the
+input image being processed is selected.
+.le
+.ls fringe = ""
+Fringe correction images. The CCD image type is not checked for these
+images and they take precedence over any fringe correction images given
+in the input list. The fringe image with the same subset as the
+input image being processed is selected.
+.le
+.ls minreplace = 1.
+When processing flat fields, pixel values below this value (after
+all other processing such as overscan, zero, and dark corrections) are
+replaced by this value. This allows flat fields processed by \fBccdproc\fR
+to be certain to avoid divide by zero problems when applied to object
+images.
+.le
+.ls scantype = "shortscan"
+Type of scan format used in creating the CCD images. The modes are:
+.ls "shortscan"
+The CCD is scanned over a number of lines and then read out as a regular
+two dimensional image. In this mode unscanned zero level, dark count and
+flat fields are numerically scanned to form scanned flat fields comparable
+to the observations.
+.le
+.ls "longscan"
+In this mode the CCD is clocked and read out continuously to form a long
+strip. Flat fields are averaged across the readout axis to
+form a one dimensional flat field readout correction image. This assumes
+that all recorded image lines are clocked over the entire active area of the
+CCD.
+.le
+.le
+.ls nscan
+Number of object scan readout lines used in short scan mode. This parameter
+is used when the scan type is "shortscan" and the number of scan lines
+cannot be determined from the object image header (using the keyword
+nscanrows or it's translation).
+.le
+
+
+.ce
+OVERSCAN FITTING PARAMETERS
+
+There are two types of overscan (or prescan) determinations. One determines
+a independent overscan value for each line and is only available for a
+\fIreadaxis\fR of 1. The other averages the overscan along the readout
+direction to make an overscan vector, fits a smoothing function to the vector,
+and then evaluate and then evaluates the smooth function at each readout
+line or column. The line-by-line determination only uses the
+\fIfunction\fR parameter and the smoothing determinations uses all
+the following parameters.
+
+.ls function = "legendre"
+Line-by-line determination of the overscan is specified by:
+
+.nf
+ mean - the mean of the biassec columns at each line
+ median - the median of the biassec columns at each line
+ minmax - the mean at each line with the min and max excluded
+.fi
+
+The smoothed overscan vector may be fit by one of the functions:
+
+.nf
+ legendre - legendre polynomial
+ chebyshev - chebyshev polynomial
+ spline1 - linear spline
+ spline3 - cubic spline
+.fi
+.le
+.ls order = 1
+Number of polynomial terms or spline pieces in the overscan fit.
+.le
+.ls sample = "*"
+Sample points to use in the overscan fit. The string "*" specified all
+points otherwise an \fBicfit\fR range string is used.
+.le
+.ls naverage = 1
+Number of points to average or median to form fitting points. Positive
+numbers specify averages and negative numbers specify medians.
+.le
+.ls niterate = 1
+Number of rejection iterations to remove deviant points from the overscan fit.
+If 0 then no points are rejected.
+.le
+.ls low_reject = 3., high_reject = 3.
+Low and high sigma rejection factors for rejecting deviant points from the
+overscan fit.
+.le
+.ls grow = 0.
+One dimensional growing radius for rejection of neighbors to deviant points.
+.le
+.ls interactive = no
+Fit the overscan vector interactively? If yes and the overscan function type
+is one of the \fBicfit\fR types then the average overscan vector is fit
+interactively using the \fBicfit\fR package. If no then the fitting parameters
+given below are used.
+.le
+
+The parameters \fIverbose\fR, \fIlogfile\fR, and \fIbackup\fR default to
+the package parameters but may be specified to override the package
+values. This is used by the \fBquadproc\fR script task. These parameters
+are described in the help topic "quadred.package".
+.ih
+DESCRIPTION
+\fBCcdproc\fR processes CCD images to correct and calibrate for
+detector defects, readout bias, zero level bias, dark counts,
+response, iillumination, and fringing. It also trims unwanted
+lines and columns and changes the pixel datatype. It is efficient
+and easy to use; all one has to do is set the parameters and then
+begin processing the images. The task takes care of most of the
+record keeping and automatically does the prerequisite processing
+of calibration images. Beneath this simplicity there is much that
+is going on. In this section a simple description of the usage is
+given. The following sections present more detailed discussions
+on the different operations performed and the order and logic
+of the processing steps. For a user's guide to the \fBccdred\fR
+package see \fBguide\fR. Much of the ease of use derives from using
+information in the image header. If this information is missing
+see section 13.
+
+One begins by setting the task parameters. There are many parameters
+but they may be easily reviewed and modified using the task \fBeparam\fR.
+The input CCD images to be processed are given as an image list.
+Previously processed images are ignored and calibration images are
+recognized, provided the CCD image types are in the image header (see
+\fBinstruments\fR and \fBccdtypes\fR). Therefore it is permissible to
+use simple image templates such as "*.imh". The \fIccdtype\fR parameter
+may be used to select only certain types of CCD images to process
+(see \fBccdtypes\fR).
+
+The processing operations are selected by boolean (yes/no) parameters.
+Because calibration images are recognized and processed appropriately,
+the processing operations for object images should be set.
+Any combination of operations may be specified and the operations are
+performed simultaneously. While it is possible to do operations in
+separate steps this is much less efficient. Two of the operation
+parameters apply only to zero level and flat field images. These
+are used for certain types of CCDs and modes of operation.
+
+The processing steps selected have related parameters which must be
+set. These are things like image sections defining the overscan and
+trim regions and calibration images. There are a number of parameters
+used for fitting the overscan or prescan bias section. These are
+parameters used by the standard IRAF curve fitting package \fBicfit\fR.
+The parameters are described in more detail in the following sections.
+
+In addition to the task parameters there are package parameters
+which affect \fBccdproc\fR. These include the instrument and subset
+files, the text and plot log files, the output pixel datatype,
+the amount of memory available for calibration image caching,
+the verbose parameter for logging to the terminal, and the backup
+prefix. These are described in \fBccdred\fR.
+
+Calibration images are specified by task parameters and/or in the
+input image list. If more than one calibration image is specified
+then the first one encountered is used and a warning is issued for the
+extra images. Calibration images specified by
+task parameters take precedence over calibration images in the input list.
+These images also need not have a CCD image type parameter since the task
+parameter identifies the type of calibration image. This method is
+best if there is only one calibration image for all images
+to be processed. This is almost always true for zero level and dark
+count images. If no calibration image is specified by task parameter
+then calibration images in the input image list are identified and
+used. This requires that the images have CCD image types recognized
+by the package. This method is useful if one may simply say "*.imh"
+as the image list to process all images or if the images are broken
+up into groups, in "@" files for example, each with their own calibration
+frames.
+
+When an input image is processed the task first determines the processing
+parameters and calibration images. If a requested operation has been
+done it is skipped and if all requested operations have been completed then
+no processing takes place. When it determines that a calibration image
+is required it checks for the image from the task parameter and then
+for a calibration image of the proper type in the input list.
+
+Having
+selected a calibration image it checks if it has been processed by
+looking for the image header flag CCDPROC. If it is not present then
+the calibration image is processed. When any image has been processed
+the CCDPROC flag is added. For images processed directly by \fBccdproc\fR
+the individual processing flags are checked even if the CCDPROC flag is
+present. However, the automatic processing of the calibration images is
+only done if the CCDPROC flag is absent! This is to make the task more
+efficient by not having to check every flag for every calibration image
+for every input image. Thus, if additional processing
+steps are added after images have been partially reduced then input images
+will be processed for the new steps but calibration images will not be
+processed automatically.
+
+After the calibration images have been identified, and processed if
+necessary, the images may be cached in memory. This is done when there
+are more than two input images (it is actually less efficient to
+cache the calibration images for one or two input images) and the parameter
+\fImax_cache\fR is greater than zero. When caching, as many calibration
+images as allowed by the specified memory are read into memory and
+kept there for all the input images. Cached images are, therefore,
+only read once from disk which reduces the amount of disk I/O. This
+makes a modest decrease in the execution time. It is not dramatic
+because the actual processing is fairly CPU intensive.
+
+Once the processing parameters and calibration images have been determined
+the input image is processed for all the desired operations in one step;
+i.e. there are no intermediate results or images. This makes the task
+efficient. If a matching list of output images is given then the processed
+image is written to the specified output image name. If no output image
+list is given then the corrected image is output as a temporary image until
+the entire image has been processed. When the image has been completely
+processed then the original image is deleted (or renamed using the
+specified backup prefix) and the corrected image replaces the original
+image. Using a temporary image protects the data in the event of an abort
+or computer failure. Keeping the original image name eliminates much of
+the record keeping and the need to generate new image names.
+.sh
+1. Fixpix
+Regions of bad lines and columns may be replaced by linear
+interpolation from neighboring lines and columns when the parameter
+\fIfixpix\fR is set. This algorithm is the same as used in the
+task \fBfixpix\fR. The bad pixels may be specified by a pixel mask,
+an image, or a text file. For the mask or image, values of zero indicate
+good pixels and other values indicate bad pixels to be replaced.
+
+The text file consists of lines with four fields, the starting and
+ending columns and the starting and ending lines. Any number of
+regions may be specified. Comment lines beginning with the character
+'#' may be included. The description applies directly to the input
+image (before trimming) so different files are needed for previously
+trimmed or subsection readouts. The data in this file is internally
+turned into the same description as a bad pixel mask with values of
+two for regions which are narrower or equal across the columns and
+a value of three for regions narrower across lines.
+
+The direction of interpolation is determined from the values in the
+mask, image, or the converted text file. A value of two interpolates
+across columns, a value of three interpolates across lines, and any
+other value interpolates across the narrowest dimension of bad pixels
+and using column interpolation if the two dimensions are equal.
+
+The bad pixel description may be specified explicitly with the parameter
+\fIfixfile\fR or indirectly if the parameter has the value "image". In the
+latter case the instrument file must contain the name of the file.
+.sh
+2. Overscan
+If an overscan or prescan correction is specified (\fIoverscan\fR
+parameter) then the image section (\fIbiassec\fR parameter) defines
+the overscan region.
+
+There are two types of overscan (or prescan) determinations. One determines
+a independent overscan value for each line and is only available for a
+\fIreadaxis\fR of 1. The other averages the overscan along the readout
+direction to make an overscan vector, fits a smoothing function to the vector,
+and then evaluate and then evaluates the smooth function at each readout
+line or column.
+
+The line-by-line determination provides an mean, median, or
+mean with the minimum and maximum values excluded. The median
+is lowest value of the middle two when the number of overscan columns
+is even rather than the mean.
+
+The smoothed overscan vector determination uses the \fBicfit\fR options
+including interactive fitting. The fitting function is generally either a
+constant (polynomial of 1 term) or a high order function which fits the
+large scale shape of the overscan vector. Bad pixel rejection is also
+available to eliminate cosmic ray events. The function fitting may be done
+interactively using the standard \fBicfit\fR iteractive graphical curve
+fitting tool. Regardless of whether the fit is done interactively, the
+overscan vector and the fit may be recorded for later review in a metacode
+plot file named by the parameter \fIccdred.plotfile\fR. The mean value of
+the bias function is also recorded in the image header and log file.
+.sh
+3. Trim
+When the parameter \fItrim\fR is set the input image will be trimmed to
+the image section given by the parameter \fItrimsec\fR. This trim
+should, of course, be the same as that used for the calibration images.
+.sh
+4. Zerocor
+After the readout bias is subtracted, as defined by the overscan or prescan
+region, there may still be a zero level bias. This level may be two
+dimensional or one dimensional (the same for every readout line). A
+zero level calibration is obtained by taking zero length exposures;
+generally many are taken and combined. To apply this zero
+level calibration the parameter \fIzerocor\fR is set. In addition if
+the zero level bias is only readout dependent then the parameter \fIreadcor\fR
+is set to reduce two dimensional zero level images to one dimensional
+images. The zero level images may be specified by the parameter \fIzero\fR
+or given in the input image list (provided the CCD image type is defined).
+
+When the zero level image is needed to correct an input image it is checked
+to see if it has been processed and, if not, it is processed automatically.
+Processing of zero level images consists of bad pixel replacement,
+overscan correction, trimming, and averaging to one dimension if the
+readout correction is specified.
+.sh
+5. Darkcor
+Dark counts are subtracted by scaling a dark count calibration image to
+the same exposure time as the input image and subtracting. The
+exposure time used is the dark time which may be different than the
+actual integration or exposure time. A dark count calibration image is
+obtained by taking a very long exposure with the shutter closed; i.e.
+an exposure with no light reaching the detector. The dark count
+correction is selected with the parameter \fIdarkcor\fR and the dark
+count calibration image is specified either with the parameter
+\fIdark\fR or as one of the input images. The dark count image is
+automatically processed as needed. Processing of dark count images
+consists of bad pixel replacement, overscan and zero level correction,
+and trimming.
+.sh
+6. Flatcor
+The relative detector pixel response is calibrated by dividing by a
+scaled flat field calibration image. A flat field image is obtained by
+exposure to a spatially uniform source of light such as an lamp or
+twilight sky. Flat field images may be corrected for the spectral
+signature in spectroscopic images (see \fBresponse\fR and
+\fBapnormalize\fR), or for iillumination effects (see \fBmkillumflat\fR
+or \fBmkskyflat\fR). For more on flat fields and iillumination corrections
+see \fBflatfields\fR. The flat field response is dependent on the
+wavelength of light so if different filters or spectroscopic wavelength
+coverage are used a flat field calibration for each one is required.
+The different flat fields are automatically selected by a subset
+parameter (see \fBsubsets\fR).
+
+Flat field calibration is selected with the parameter \fBflatcor\fR
+and the flat field images are specified with the parameter \fBflat\fR
+or as part of the input image list. The appropriate subset is automatically
+selected for each input image processed. The flat field image is
+automatically processed as needed. Processing consists of bad pixel
+replacement, overscan subtraction, zero level subtraction, dark count
+subtraction, and trimming. Also if a scan mode is used and the
+parameter \fIscancor\fR is specified then a scan mode correction is
+applied (see below). The processing also computes the mean of the
+flat field image which is used later to scale the flat field before
+division into the input image. For scan mode flat fields the ramp
+part is included in computing the mean which will affect the level
+of images processed with this flat field. Note that there is no check for
+division by zero in the interest of efficiency. If division by zero
+does occur a fatal error will occur. The flat field can be fixed by
+replacing small values using a task such as \fBimreplace\fR or
+during processing using the \fIminreplace\fR parameter. Note that the
+\fIminreplace\fR parameter only applies to flat fields processed by
+\fBccdproc\fR.
+.sh
+7. Illumcor
+CCD images processed through the flat field calibration may not be
+completely flat (in the absence of objects). In particular, a blank
+sky image may still show gradients. This residual nonflatness is called
+the iillumination pattern. It may be introduced even if the detector is
+uniformly illuminated by the sky because the flat field lamp
+iillumination may be nonuniform. The iillumination pattern is found from a
+blank sky, or even object image, by heavily smoothing and rejecting
+objects using sigma clipping. The iillumination calibration image is
+divided into the data being processed to remove the iillumination
+pattern. The iillumination pattern is a function of the subset so there
+must be an iillumination correction image for each subset to be
+processed. The tasks \fBmkillumcor\fR and \fBmkskycor\fR are used to
+create the iillumination correction images. For more on iillumination
+corrections see \fBflatfields\fR.
+
+An alternative to treating the iillumination correction as a separate
+operation is to combine the flat field and iillumination correction
+into a corrected flat field image before processing the object
+images. This will save some processing time but does require creating
+the flat field first rather than correcting the images at the same
+time or later. There are two methods, removing the large scale
+shape of the flat field and combining a blank sky image iillumination
+with the flat field. These methods are discussed further in the
+tasks which create them; \fBmkillumcor\fR and \fBmkskycor\fR.
+.sh
+8. Fringecor
+There may be a fringe pattern in the images due to the night sky lines.
+To remove this fringe pattern a blank sky image is heavily smoothed
+to produce an iillumination image which is then subtracted from the
+original sky image. The residual fringe pattern is scaled to the
+exposure time of the image to be fringe corrected and then subtracted.
+Because the intensity of the night sky lines varies with time an
+additional scaling factor may be given in the image header.
+The fringe pattern is a function of the subset so there must be
+a fringe correction image for each subset to be processed.
+The task \fBmkfringecor\fR is used to create the fringe correction images.
+.sh
+9. Readcor
+If a zero level correction is desired (\fIzerocor\fR parameter)
+and the parameter \fIreadcor\fR is yes then a single zero level
+correction vector is applied to each readout line or column. Use of a
+readout correction rather than a two dimensional zero level image
+depends on the nature of the detector or if the CCD is operated in
+longscan mode (see below). The readout correction is specified by a
+one dimensional image (\fIzero\fR parameter) and the readout axis
+(\fIreadaxis\fR parameter). If the zero level image is two dimensional
+then it is automatically processed to a one dimensional image by
+averaging across the readout axis. Note that this modifies the zero
+level calibration image.
+.sh
+10. Scancor
+CCD detectors may be operated in several modes in astronomical
+applications. The most common is as a direct imager where each pixel
+integrates one point in the sky or spectrum. However, the design of most CCD's
+allows the sky to be scanned across the CCD while shifting the
+accumulating signal at the same rate. \fBCcdproc\fR provides for two
+scanning modes called "shortscan" and "longscan". The type of scan
+mode is set with the parameter \fIscanmode\fR.
+
+In "shortscan" mode the detector is scanned over a specified number of
+lines (not necessarily at sideral rates). The lines that scroll off the
+detector during the integration are thrown away. At the end of the
+integration the detector is read out in the same way as an unscanned
+observation. The advantage of this mode is that the small scale, zero
+level, dark count and flat field responses are averaged in one dimension
+over the number of lines scanned. A zero level, dark count or flat field may be
+observed in the same way in which case there is no difference in the
+processing from unscanned imaging and the parameter \fIscancor\fR may be
+no. If it is yes, though, checking is done to insure that the calibration
+image used has the same number of scan lines as the object being
+processed. However, one obtains an increase in the statistical accuracy of
+if they are not scanned during the observation but
+digitally scanned during the processing. In shortscan mode with
+\fIscancor\fR set to yes, zero level, dark count and flat field images are
+digitally scanned, if needed, by the same number of scan lines as the
+object. The number of scan lines is determined from the object image
+header using the keyword nscanrow (or it's translation). If not found the
+object is assumed to have been scanned with the value given by the
+\fInscan\fR parameter. Zero, dark and flat calibration images are assumed
+to be unscanned if the header keyword is not found.
+
+If a scanned zero level, dark count or flat field image is not found
+matching the object then one may be created from the unscanned calibration
+image. The image will have the root name of the unscanned image with an
+extension of the number of scan rows; i.e. Flat1.32 is created from Flat1
+with a digital scanning of 32 lines.
+
+In "longscan" mode the detector is continuously read out to produce an
+arbitrarily long strip. Provided data which has not passed over the entire
+detector is thrown away, the zero level, dark count, and flat field
+corrections will be one dimensional. If \fIscancor\fR is specified and the
+scan mode is "longscan" then a one dimensional zero level, dark count, and
+flat field correction will be applied.
+.sh
+11. Processing Steps
+The following describes the steps taken by the task. This detailed
+outline provides the most detailed specification of the task.
+
+.ls 5 (1)
+An image to be processed is first checked that it is of the specified
+CCD image type. If it is not the desired type then go on to the next image.
+.le
+.ls (2)
+A temporary output image is created of the specified pixel data type
+(\fBccdred.pixeltype\fR). The header parameters are copied from the
+input image.
+.le
+.ls (3)
+If trimming is specified and the image has not been trimmed previously,
+the trim section is determined.
+.le
+.ls (4)
+If bad pixel replacement is specified and this has not been done
+previously, the bad pixel file is determined either from the task
+parameter or the instrument translation file. The bad pixel regions
+are read. If the image has been trimmed previously and the bad pixel
+file contains the word "untrimmed" then the bad pixel coordinates are
+translated to those of the trimmed image.
+.le
+.ls (5)
+If an overscan correction is specified and this correction has not been
+applied, the overscan section is averaged along the readout axis. If
+trimming is to be done the overscan section is trimmed to the same
+limits. A function is fit either interactively or noninteractively to
+the overscan vector. The function is used to produce the overscan
+vector to be subtracted from the image. This is done in real
+arithmetic.
+.le
+.ls (6)
+If the image is a zero level image go to processing step 12.
+If a zero level correction is desired and this correction has not been
+performed, find the zero level calibration image. If the zero level
+calibration image has not been processed it is processed at this point.
+This is done by going to processing step 1 for this image. After the
+calibration image has been processed, processing of the input image
+continues from this point.
+The processed calibration image may be
+cached in memory if it has not been previously and if there is enough memory.
+.le
+.ls (7)
+If the image is a dark count image go to processing step 12.
+If a dark count correction is desired and this correction has not been
+performed, find the dark count calibration image. If the dark count
+calibration image has not been processed it is processed at this point.
+This is done by going to processing step 1 for this image. After the
+calibration image has been processed, processing of the input image
+continues from this point. The ratio of the input image dark time
+to the dark count image dark time is determined to be multiplied with
+each pixel of the dark count image before subtracting from the input
+image.
+The processed calibration image may be
+cached in memory if it has not been previously and if there is enough memory.
+.le
+.ls (8)
+If the image is a flat field image go to processing step 12. If a flat
+field correction is desired and this correction has not been performed,
+find the flat field calibration image of the appropriate subset. If
+the flat field calibration image has not been processed it is processed
+at this point. This is done by going to processing step 1 for this
+image. After the calibration image has been processed, processing of
+the input image continues from this point. The mean of the image
+is determined from the image header to be used for scaling. If no
+mean is found then a unit scaling is used.
+The processed calibration image may be
+cached in memory if it has not been previously and if there is enough memory.
+.le
+.ls (9)
+If the image is an iillumination image go to processing step 12. If an
+iillumination correction is desired and this correction has not been performed,
+find the iillumination calibration image of the appropriate subset.
+The iillumination image must have the "mkillum" processing flag or the
+\fBccdproc\fR will abort with an error. The mean of the image
+is determined from the image header to be used for scaling. If no
+mean is found then a unit scaling is used. The processed calibration
+image may be
+cached in memory if it has not been previously and there is enough memory.
+.le
+.ls (10)
+If the image is a fringe image go to processing step 12. If a fringe
+correction is desired and this correction has not been performed,
+find the fringe calibration image of the appropriate subset.
+The iillumination image must have the "mkfringe" processing flag or the
+\fBccdproc\fR will abort with an error. The ratio of the input
+image exposure time to the fringe image exposure time is determined.
+If there is a fringe scaling in the image header then this factor
+is multiplied by the exposure time ratio. This factor is used
+for scaling. The processed calibration image may be
+cached in memory if it has not been previously and there is enough memory.
+.le
+.ls (11)
+If there are no processing operations flagged, delete the temporary output
+image, which has been opened but not used, and go to 14.
+.le
+.ls (12)
+The input image is processed line by line with trimmed lines ignored.
+A line of the input image is read. Bad pixel replacement and trimming
+is applied to the image. Image lines from the calibration images
+are read from disk or the image cache. If the calibration is one
+dimensional (such as a readout zero
+level correction or a longscan flat field correction) then the image
+vector is read only once. Note that IRAF image I/O is buffered for
+efficiency and accessing a line at a time does not mean that image
+lines are read from disk a line at a time. Given the input line, the
+calibration images, the overscan vector, and the various scale factors
+a special data path for each combination of corrections is used to
+perform all the processing in the most efficient manner. If the
+image is a flat field any pixels less than the \fIminreplace\fR
+parameter are replaced by that minimum value. Also a mean is
+computed for the flat field and stored as the CCDMEAN keyword and
+the time, in a internal format, when this value was calculated is stored
+in the CCDMEANT keyword. The time is checked against the image modify
+time to determine if the value is valid or needs to be recomputed.
+.le
+.ls (13)
+The input image is deleted or renamed to a backup image. The temporary
+output image is renamed to the input image name.
+.le
+.ls (14)
+If the image is a zero level image and the readout correction is specified
+then it is averaged to a one dimensional readout correction.
+.le
+.ls (15)
+If the image is a zero level, dark count, or flat field image and the scan
+mode correction is specified then the correction is applied. For shortscan
+mode a modified two dimensional image is produced while for longscan mode a
+one dimensional average image is produced.
+.le
+.ls (16)
+The processing is completed and either the next input image is processed
+beginning at step 1 or, if it is a calibration image which is being
+processed for an input image, control returns to the step which initiated
+the calibration image processing.
+.le
+.sh
+12. Processing Arithmetic
+The \fBccdproc\fR task has two data paths, one for real image pixel datatypes
+and one for short integer pixel datatype. In addition internal arithmetic
+is based on the rules of FORTRAN. For efficiency there is
+no checking for division by zero in the flat field calibration.
+The following rules describe the processing arithmetic and data paths.
+
+.ls (1)
+If the input, output, or any calibration image is of type real the
+real data path is used. This means all image data is converted to
+real on input. If all the images are of type short all input data
+is kept as short integers. Thus, if all the images are of the same type
+there is no datatype conversion on input resulting in greater
+image I/O efficiency.
+.le
+.ls (2)
+In the real data path the processing arithmetic is always real and,
+if the output image is of short pixel datatype, the result
+is truncated.
+.le
+.ls (3)
+The overscan vector and the scale factors for dark count, flat field,
+iillumination, and fringe calibrations are always of type real. Therefore,
+in the short data path any processing which includes these operations
+will be coerced to real arithmetic and the result truncated at the end
+of the computation.
+.le
+.sh
+13. In the Absence of Image Header Information
+The tasks in the \fBccdred\fR package are most convenient to use when
+the CCD image type, subset, and exposure time are contained in the
+image header. The ability to redefine which header parameters contain
+this information makes it possible to use the package at many different
+observatories (see \fBinstruments\fR). However, in the absence of any
+image header information the tasks may still be used effectively.
+There are two ways to proceed. One way is to use \fBccdhedit\fR
+to place the information in the image header.
+
+The second way is to specify the processing operations more explicitly
+than is needed when the header information is present. The parameter
+\fIccdtype\fR is set to "" or to "none". The calibration images are
+specified explicitly by task parameter since they cannot be recognized
+in the input list. Only one subset at a time may be processed.
+
+If dark count and fringe corrections are to be applied the exposure
+times must be added to all the images. Alternatively, the dark count
+and fringe images may be scaled explicitly for each input image. This
+works because the exposure times default to 1 if they are not given in
+the image header.
+.ih
+EXAMPLES
+The user's \fBguide\fR presents a tutorial in the use of this task.
+
+1. In general all that needs to be done is to set the task parameters
+and enter
+
+ cl> ccdproc *.imh &
+
+This will run in the background and process all images which have not
+been processed previously.
+.ih
+SEE ALSO
+package, quadformat, instruments, ccdtypes, flatfields, icfit, ccdred,
+guide, mkillumcor, mkskycor, mkfringecor
+.endhelp
diff --git a/noao/imred/quadred/src/ccdproc/doproc.x b/noao/imred/quadred/src/ccdproc/doproc.x
new file mode 100644
index 00000000..909c6f12
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/doproc.x
@@ -0,0 +1,29 @@
+include "ccdred.h"
+
+# DOPROC -- Call the appropriate processing procedure.
+#
+# There are four data type paths depending on the readout axis and
+# the calculation data type.
+
+procedure doproc (ccd)
+
+pointer ccd # CCD processing structure
+
+begin
+ switch (READAXIS (ccd)) {
+ case 1:
+ switch (CALCTYPE (ccd)) {
+ case TY_SHORT:
+ call proc1s (ccd)
+ default:
+ call proc1r (ccd)
+ }
+ case 2:
+ switch (CALCTYPE (ccd)) {
+ case TY_SHORT:
+ call proc2s (ccd)
+ default:
+ call proc2r (ccd)
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/ccdproc/generic/ccdred.h b/noao/imred/quadred/src/ccdproc/generic/ccdred.h
new file mode 100644
index 00000000..ef41f592
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/generic/ccdred.h
@@ -0,0 +1,155 @@
+# CCDRED Data Structures and Definitions
+
+# The CCD structure: This structure is used to communicate processing
+# parameters between the package procedures. It contains pointers to
+# data, calibration image IMIO pointers, scaling parameters, and the
+# correction flags. The corrections flags indicate which processing
+# operations are to be performed. The subsection parameters do not
+# include a step size. A step size is assumed. If arbitrary subsampling
+# is desired this would be the next generalization.
+
+define LEN_CCD 75 # Length of CCD structure
+
+# CCD data coordinates
+define CCD_C1 Memi[$1] # CCD starting column
+define CCD_C2 Memi[$1+1] # CCD ending column
+define CCD_L1 Memi[$1+2] # CCD starting line
+define CCD_L2 Memi[$1+3] # CCD ending line
+
+# Input data
+define IN_IM Memi[$1+4] # Input image pointer
+define IN_C1 Memi[$1+5] # Input data starting column
+define IN_C2 Memi[$1+6] # Input data ending column
+define IN_L1 Memi[$1+7] # Input data starting line
+define IN_L2 Memi[$1+8] # Input data ending line
+define IN_NSEC Memi[$1+71] # Number of input pieces
+define IN_SEC Memi[$1+72] # Pointer to sections (c1,c2,l1,l2)xn
+
+# Output data
+define OUT_IM Memi[$1+9] # Output image pointer
+define OUT_C1 Memi[$1+10] # Output data starting column
+define OUT_C2 Memi[$1+11] # Output data ending column
+define OUT_L1 Memi[$1+12] # Output data starting line
+define OUT_L2 Memi[$1+13] # Output data ending line
+define OUT_SEC Memi[$1+73] # Pointer to sections (c1,c2,l1,l2)xn
+
+# Zero level data
+define ZERO_IM Memi[$1+14] # Zero level image pointer
+define ZERO_C1 Memi[$1+15] # Zero level data starting column
+define ZERO_C2 Memi[$1+16] # Zero level data ending column
+define ZERO_L1 Memi[$1+17] # Zero level data starting line
+define ZERO_L2 Memi[$1+18] # Zero level data ending line
+
+# Dark count data
+define DARK_IM Memi[$1+19] # Dark count image pointer
+define DARK_C1 Memi[$1+20] # Dark count data starting column
+define DARK_C2 Memi[$1+21] # Dark count data ending column
+define DARK_L1 Memi[$1+22] # Dark count data starting line
+define DARK_L2 Memi[$1+23] # Dark count data ending line
+
+# Flat field data
+define FLAT_IM Memi[$1+24] # Flat field image pointer
+define FLAT_C1 Memi[$1+25] # Flat field data starting column
+define FLAT_C2 Memi[$1+26] # Flat field data ending column
+define FLAT_L1 Memi[$1+27] # Flat field data starting line
+define FLAT_L2 Memi[$1+28] # Flat field data ending line
+
+# Illumination data
+define ILLUM_IM Memi[$1+29] # Illumination image pointer
+define ILLUM_C1 Memi[$1+30] # Illumination data starting column
+define ILLUM_C2 Memi[$1+31] # Illumination data ending column
+define ILLUM_L1 Memi[$1+32] # Illumination data starting line
+define ILLUM_L2 Memi[$1+33] # Illumination data ending line
+
+# Fringe data
+define FRINGE_IM Memi[$1+34] # Fringe image pointer
+define FRINGE_C1 Memi[$1+35] # Fringe data starting column
+define FRINGE_C2 Memi[$1+36] # Fringe data ending column
+define FRINGE_L1 Memi[$1+37] # Fringe data starting line
+define FRINGE_L2 Memi[$1+38] # Fringe data ending line
+
+# Trim section
+define TRIM_C1 Memi[$1+39] # Trim starting column
+define TRIM_C2 Memi[$1+40] # Trim ending column
+define TRIM_L1 Memi[$1+41] # Trim starting line
+define TRIM_L2 Memi[$1+42] # Trim ending line
+
+# Bias section
+define BIAS_C1 Memi[$1+43] # Bias starting column
+define BIAS_C2 Memi[$1+44] # Bias ending column
+define BIAS_L1 Memi[$1+45] # Bias starting line
+define BIAS_L2 Memi[$1+46] # Bias ending line
+define BIAS_SEC Memi[$1+74] # Multiple bias sections
+
+define READAXIS Memi[$1+47] # Read out axis (1=cols, 2=lines)
+define CALCTYPE Memi[$1+48] # Calculation data type
+define NBADCOLS Memi[$1+49] # Number of column interpolation regions
+define BADCOLS Memi[$1+50] # Pointer to col interpolation regions
+define NBADLINES Memi[$1+51] # Number of line interpolation regions
+define BADLINES Memi[$1+52] # Pointer to line interpolation regions
+define OVERSCAN_VEC Memi[$1+53] # Pointer to overscan vector
+define DARKSCALE Memr[P2R($1+54)] # Dark count scale factor
+define FRINGESCALE Memr[P2R($1+55)] # Fringe scale factor
+define FLATSCALE Memr[P2R($1+56)] # Flat field scale factor
+define ILLUMSCALE Memr[P2R($1+57)] # Illumination scale factor
+define MINREPLACE Memr[P2R($1+58)] # Minimum replacement value
+define MEAN Memr[P2R($1+59)] # Mean of output image
+define COR Memi[$1+60] # Overall correction flag
+define CORS Memi[$1+61+($2-1)] # Individual correction flags
+
+# Individual components of input, output, and bias section pieces.
+define IN_SC1 Memi[IN_SEC($1)+4*$2-4]
+define IN_SC2 Memi[IN_SEC($1)+4*$2-3]
+define IN_SL1 Memi[IN_SEC($1)+4*$2-2]
+define IN_SL2 Memi[IN_SEC($1)+4*$2-1]
+define OUT_SC1 Memi[OUT_SEC($1)+4*$2-4]
+define OUT_SC2 Memi[OUT_SEC($1)+4*$2-3]
+define OUT_SL1 Memi[OUT_SEC($1)+4*$2-2]
+define OUT_SL2 Memi[OUT_SEC($1)+4*$2-1]
+define BIAS_SC1 Memi[BIAS_SEC($1)+4*$2-4]
+define BIAS_SC2 Memi[BIAS_SEC($1)+4*$2-3]
+define BIAS_SL1 Memi[BIAS_SEC($1)+4*$2-2]
+define BIAS_SL2 Memi[BIAS_SEC($1)+4*$2-1]
+
+# The correction array contains the following elements with array indices
+# given by the macro definitions.
+
+define NCORS 10 # Number of corrections
+
+define FIXPIX 1 # Fix bad pixels
+define TRIM 2 # Trim image
+define OVERSCAN 3 # Apply overscan correction
+define ZEROCOR 4 # Apply zero level correction
+define DARKCOR 5 # Apply dark count correction
+define FLATCOR 6 # Apply flat field correction
+define ILLUMCOR 7 # Apply illumination correction
+define FRINGECOR 8 # Apply fringe correction
+define FINDMEAN 9 # Find the mean of the output image
+define MINREP 10 # Check and replace minimum value
+
+# The following definitions identify the correction values in the correction
+# array. They are defined in terms of bit fields so that it is possible to
+# add corrections to form unique combination corrections. Some of
+# these combinations are implemented as compound operations for efficiency.
+
+define O 001B # overscan
+define Z 002B # zero level
+define D 004B # dark count
+define F 010B # flat field
+define I 020B # Illumination
+define Q 040B # Fringe
+
+# The following correction combinations are recognized.
+
+define ZO 003B # zero level + overscan
+define DO 005B # dark count + overscan
+define DZ 006B # dark count + zero level
+define DZO 007B # dark count + zero level + overscan
+define FO 011B # flat field + overscan
+define FZ 012B # flat field + zero level
+define FZO 013B # flat field + zero level + overscan
+define FD 014B # flat field + dark count
+define FDO 015B # flat field + dark count + overscan
+define FDZ 016B # flat field + dark count + zero level
+define FDZO 017B # flat field + dark count + zero level + overscan
+define QI 060B # fringe + illumination
diff --git a/noao/imred/quadred/src/ccdproc/generic/cor.x b/noao/imred/quadred/src/ccdproc/generic/cor.x
new file mode 100644
index 00000000..0dc21310
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/generic/cor.x
@@ -0,0 +1,695 @@
+include "ccdred.h"
+
+
+.help cor Feb87 noao.imred.ccdred
+.nf ----------------------------------------------------------------------------
+cor -- Process CCD image lines
+
+These procedures are the heart of the CCD processing. They do the desired
+set of processing operations on the image line data as efficiently as
+possible. They are called by the PROC procedures. There are four procedures
+one for each readout axis and one for short and real image data.
+Some sets of operations are coded as single compound operations for efficiency.
+To keep the number of combinations managable only the most common
+combinations are coded as compound operations. The combinations
+consist of any set of line overscan, column overscan, zero level, dark
+count, and flat field and any set of illumination and fringe
+correction. The corrections are applied in place to the output vector.
+
+The column readout procedure is more complicated in order to handle
+zero level and flat field corrections specified as one dimensional
+readout corrections instead of two dimensional calibration images.
+Column readout format is probably extremely rare and the 1D readout
+corrections are used only for special types of data.
+.ih
+SEE ALSO
+proc, ccdred.h
+.endhelp -----------------------------------------------------------------------
+
+
+# COR1 -- Correct image lines with readout axis 1 (lines).
+
+procedure cor1s (cors, out, overscan, zero, dark, flat, illum,
+ fringe, n, darkscale, flatscale, illumscale, frgscale)
+
+int cors[ARB] # Correction flags
+short out[n] # Output data
+real overscan # Overscan value
+short zero[n] # Zero level correction
+short dark[n] # Dark count correction
+short flat[n] # Flat field correction
+short illum[n] # Illumination correction
+short fringe[n] # Fringe correction
+int n # Number of pixels
+real darkscale # Dark count scale factor
+real flatscale # Flat field scale factor
+real illumscale # Illumination scale factor
+real frgscale # Fringe scale factor
+
+int i, op
+
+begin
+ op = cors[OVERSCAN] + cors[ZEROCOR] + cors[DARKCOR] + cors[FLATCOR]
+ switch (op) {
+ case O: # overscan
+ do i = 1, n
+ out[i] = out[i] - overscan
+ case Z: # zero level
+ do i = 1, n
+ out[i] = out[i] - zero[i]
+
+ case ZO: # zero level + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - zero[i]
+
+ case D: # dark count
+ do i = 1, n
+ out[i] = out[i] - darkscale * dark[i]
+ case DO: # dark count + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - darkscale * dark[i]
+ case DZ: # dark count + zero level
+ do i = 1, n
+ out[i] = out[i] - zero[i] - darkscale * dark[i]
+ case DZO: # dark count + zero level + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - zero[i] - darkscale * dark[i]
+
+ case F: # flat field
+ do i = 1, n
+ out[i] = out[i] * flatscale / flat[i]
+ case FO: # flat field + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan) * flatscale / flat[i]
+ case FZ: # flat field + zero level
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatscale / flat[i]
+ case FZO: # flat field + zero level + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - zero[i]) * flatscale /
+ flat[i]
+ case FD: # flat field + dark count
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatscale / flat[i]
+ case FDO: # flat field + dark count + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - darkscale * dark[i]) *
+ flatscale / flat[i]
+ case FDZ: # flat field + dark count + zero level
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ case FDZO: # flat field + dark count + zero level + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - zero[i] -
+ darkscale * dark[i]) * flatscale / flat[i]
+ }
+
+ # Often these operations will not be performed so test for no
+ # correction rather than go through the switch.
+
+ op = cors[ILLUMCOR] + cors[FRINGECOR]
+ if (op != 0) {
+ switch (op) {
+ case I: # illumination
+ do i = 1, n
+ out[i] = out[i] * illumscale / illum[i]
+ case Q: # fringe
+ do i = 1, n
+ out[i] = out[i] - frgscale * fringe[i]
+ case QI: # fringe + illumination
+ do i = 1, n
+ out[i] = out[i]*illumscale/illum[i] - frgscale*fringe[i]
+ }
+ }
+end
+
+
+# COR2 -- Correct lines for readout axis 2 (columns). This procedure is
+# more complex than when the readout is along the image lines because the
+# zero level and/or flat field corrections may be single readout column
+# vectors.
+
+procedure cor2s (line, cors, out, overscan, zero, dark, flat, illum,
+ fringe, n, zeroim, flatim, darkscale, flatscale, illumscale, frgscale)
+
+int line # Line to be corrected
+int cors[ARB] # Correction flags
+short out[n] # Output data
+real overscan[n] # Overscan value
+short zero[n] # Zero level correction
+short dark[n] # Dark count correction
+short flat[n] # Flat field correction
+short illum[n] # Illumination correction
+short fringe[n] # Fringe correction
+int n # Number of pixels
+pointer zeroim # Zero level IMIO pointer (NULL if 1D vector)
+pointer flatim # Flat field IMIO pointer (NULL if 1D vector)
+real darkscale # Dark count scale factor
+real flatscale # Flat field scale factor
+real illumscale # Illumination scale factor
+real frgscale # Fringe scale factor
+
+short zeroval
+real flatval
+int i, op
+
+begin
+ op = cors[OVERSCAN] + cors[ZEROCOR] + cors[DARKCOR] + cors[FLATCOR]
+ switch (op) {
+ case O: # overscan
+ do i = 1, n
+ out[i] = out[i] - overscan[i]
+ case Z: # zero level
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - zero[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - zeroval
+ }
+
+ case ZO: # zero level + overscan
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zero[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zeroval
+ }
+
+ case D: # dark count
+ do i = 1, n
+ out[i] = out[i] - darkscale * dark[i]
+ case DO: # dark count + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - darkscale * dark[i]
+ case DZ: # dark count + zero level
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - zero[i] - darkscale * dark[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - zeroval - darkscale * dark[i]
+ }
+ case DZO: # dark count + zero level + overscan
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]
+ }
+
+ case F: # flat field
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = out[i] * flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = out[i] * flatval
+ }
+ case FO: # flat field + overscan
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i]) * flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i]) * flatval
+ }
+ case FZ: # flat field + zero level
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval) * flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval) * flatval
+ }
+ }
+ case FZO: # flat field + zero level + overscan
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i]) *
+ flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval) *
+ flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval) * flatval
+ }
+ }
+ case FD: # flat field + dark count
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatscale/flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatval
+ }
+ case FDO: # flat field + dark count + overscan
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - darkscale * dark[i]) *
+ flatval
+ }
+ case FDZ: # flat field + dark count + zero level
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval - darkscale * dark[i]) *
+ flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval - darkscale * dark[i]) *
+ flatval
+ }
+ }
+ case FDZO: # flat field + dark count + zero level + overscan
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]) * flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]) * flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]) * flatval
+ }
+ }
+ }
+
+ # Often these operations will not be performed so test for no
+ # correction rather than go through the switch.
+
+ op = cors[ILLUMCOR] + cors[FRINGECOR]
+ if (op != 0) {
+ switch (op) {
+ case I: # illumination
+ do i = 1, n
+ out[i] = out[i] * illumscale / illum[i]
+ case Q: # fringe
+ do i = 1, n
+ out[i] = out[i] - frgscale * fringe[i]
+ case QI: # fringe + illumination
+ do i = 1, n
+ out[i] = out[i]*illumscale/illum[i] - frgscale*fringe[i]
+ }
+ }
+end
+
+# COR1 -- Correct image lines with readout axis 1 (lines).
+
+procedure cor1r (cors, out, overscan, zero, dark, flat, illum,
+ fringe, n, darkscale, flatscale, illumscale, frgscale)
+
+int cors[ARB] # Correction flags
+real out[n] # Output data
+real overscan # Overscan value
+real zero[n] # Zero level correction
+real dark[n] # Dark count correction
+real flat[n] # Flat field correction
+real illum[n] # Illumination correction
+real fringe[n] # Fringe correction
+int n # Number of pixels
+real darkscale # Dark count scale factor
+real flatscale # Flat field scale factor
+real illumscale # Illumination scale factor
+real frgscale # Fringe scale factor
+
+int i, op
+
+begin
+ op = cors[OVERSCAN] + cors[ZEROCOR] + cors[DARKCOR] + cors[FLATCOR]
+ switch (op) {
+ case O: # overscan
+ do i = 1, n
+ out[i] = out[i] - overscan
+ case Z: # zero level
+ do i = 1, n
+ out[i] = out[i] - zero[i]
+
+ case ZO: # zero level + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - zero[i]
+
+ case D: # dark count
+ do i = 1, n
+ out[i] = out[i] - darkscale * dark[i]
+ case DO: # dark count + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - darkscale * dark[i]
+ case DZ: # dark count + zero level
+ do i = 1, n
+ out[i] = out[i] - zero[i] - darkscale * dark[i]
+ case DZO: # dark count + zero level + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan - zero[i] - darkscale * dark[i]
+
+ case F: # flat field
+ do i = 1, n
+ out[i] = out[i] * flatscale / flat[i]
+ case FO: # flat field + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan) * flatscale / flat[i]
+ case FZ: # flat field + zero level
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatscale / flat[i]
+ case FZO: # flat field + zero level + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - zero[i]) * flatscale /
+ flat[i]
+ case FD: # flat field + dark count
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatscale / flat[i]
+ case FDO: # flat field + dark count + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - darkscale * dark[i]) *
+ flatscale / flat[i]
+ case FDZ: # flat field + dark count + zero level
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ case FDZO: # flat field + dark count + zero level + overscan
+ do i = 1, n
+ out[i] = (out[i] - overscan - zero[i] -
+ darkscale * dark[i]) * flatscale / flat[i]
+ }
+
+ # Often these operations will not be performed so test for no
+ # correction rather than go through the switch.
+
+ op = cors[ILLUMCOR] + cors[FRINGECOR]
+ if (op != 0) {
+ switch (op) {
+ case I: # illumination
+ do i = 1, n
+ out[i] = out[i] * illumscale / illum[i]
+ case Q: # fringe
+ do i = 1, n
+ out[i] = out[i] - frgscale * fringe[i]
+ case QI: # fringe + illumination
+ do i = 1, n
+ out[i] = out[i]*illumscale/illum[i] - frgscale*fringe[i]
+ }
+ }
+end
+
+
+# COR2 -- Correct lines for readout axis 2 (columns). This procedure is
+# more complex than when the readout is along the image lines because the
+# zero level and/or flat field corrections may be single readout column
+# vectors.
+
+procedure cor2r (line, cors, out, overscan, zero, dark, flat, illum,
+ fringe, n, zeroim, flatim, darkscale, flatscale, illumscale, frgscale)
+
+int line # Line to be corrected
+int cors[ARB] # Correction flags
+real out[n] # Output data
+real overscan[n] # Overscan value
+real zero[n] # Zero level correction
+real dark[n] # Dark count correction
+real flat[n] # Flat field correction
+real illum[n] # Illumination correction
+real fringe[n] # Fringe correction
+int n # Number of pixels
+pointer zeroim # Zero level IMIO pointer (NULL if 1D vector)
+pointer flatim # Flat field IMIO pointer (NULL if 1D vector)
+real darkscale # Dark count scale factor
+real flatscale # Flat field scale factor
+real illumscale # Illumination scale factor
+real frgscale # Fringe scale factor
+
+real zeroval
+real flatval
+int i, op
+
+begin
+ op = cors[OVERSCAN] + cors[ZEROCOR] + cors[DARKCOR] + cors[FLATCOR]
+ switch (op) {
+ case O: # overscan
+ do i = 1, n
+ out[i] = out[i] - overscan[i]
+ case Z: # zero level
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - zero[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - zeroval
+ }
+
+ case ZO: # zero level + overscan
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zero[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zeroval
+ }
+
+ case D: # dark count
+ do i = 1, n
+ out[i] = out[i] - darkscale * dark[i]
+ case DO: # dark count + overscan
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - darkscale * dark[i]
+ case DZ: # dark count + zero level
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - zero[i] - darkscale * dark[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - zeroval - darkscale * dark[i]
+ }
+ case DZO: # dark count + zero level + overscan
+ if (zeroim != NULL)
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]
+ else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]
+ }
+
+ case F: # flat field
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = out[i] * flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = out[i] * flatval
+ }
+ case FO: # flat field + overscan
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i]) * flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i]) * flatval
+ }
+ case FZ: # flat field + zero level
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval) * flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval) * flatval
+ }
+ }
+ case FZO: # flat field + zero level + overscan
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i]) *
+ flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval) *
+ flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval) * flatval
+ }
+ }
+ case FD: # flat field + dark count
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatscale/flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - darkscale * dark[i]) * flatval
+ }
+ case FDO: # flat field + dark count + overscan
+ if (flatim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ } else {
+ flatval = flatscale / flat[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - darkscale * dark[i]) *
+ flatval
+ }
+ case FDZ: # flat field + dark count + zero level
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval - darkscale * dark[i]) *
+ flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - zero[i] - darkscale * dark[i]) *
+ flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - zeroval - darkscale * dark[i]) *
+ flatval
+ }
+ }
+ case FDZO: # flat field + dark count + zero level + overscan
+ if (flatim != NULL) {
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]) * flatscale / flat[i]
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]) * flatscale / flat[i]
+ }
+ } else {
+ flatval = flatscale / flat[line]
+ if (zeroim != NULL) {
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zero[i] -
+ darkscale * dark[i]) * flatval
+ } else {
+ zeroval = zero[line]
+ do i = 1, n
+ out[i] = (out[i] - overscan[i] - zeroval -
+ darkscale * dark[i]) * flatval
+ }
+ }
+ }
+
+ # Often these operations will not be performed so test for no
+ # correction rather than go through the switch.
+
+ op = cors[ILLUMCOR] + cors[FRINGECOR]
+ if (op != 0) {
+ switch (op) {
+ case I: # illumination
+ do i = 1, n
+ out[i] = out[i] * illumscale / illum[i]
+ case Q: # fringe
+ do i = 1, n
+ out[i] = out[i] - frgscale * fringe[i]
+ case QI: # fringe + illumination
+ do i = 1, n
+ out[i] = out[i]*illumscale/illum[i] - frgscale*fringe[i]
+ }
+ }
+end
+
diff --git a/noao/imred/quadred/src/ccdproc/generic/corinput.x b/noao/imred/quadred/src/ccdproc/generic/corinput.x
new file mode 100644
index 00000000..07afaa41
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/generic/corinput.x
@@ -0,0 +1,436 @@
+include <imhdr.h>
+include "ccdred.h"
+
+
+# CORINPUT -- Get an input image line, fix the bad pixels, and trim.
+# Return the corrected input line in the output array.
+
+procedure corinputs (in, line, ccd, output, ncols)
+
+pointer in # Input IMIO pointer
+int line # Corrected output line
+pointer ccd # CCD pointer
+short output[ncols] # Output data (returned)
+int ncols # Number of output columns
+
+int i, inline
+pointer inbuf, imgl2s()
+
+begin
+ # Determine the input line in terms of the trimmed output line.
+ if (IN_SEC(ccd) == NULL)
+ inline = IN_L1(ccd) + line - 1
+ else {
+ do i = 1, IN_NSEC(ccd) {
+ if (line < OUT_SL1(ccd,i) || line > OUT_SL2(ccd,i))
+ next
+ inline = IN_SL1(ccd,i) + line - OUT_SL1(ccd,i)
+ break
+ }
+ }
+
+ # If there are bad lines call a procedure to fix them. Otherwise
+ # read the image line directly.
+
+ if (NBADLINES(ccd) != 0)
+ call lfixs (in, inline, Mems[BADLINES(ccd)], IM_LEN(in,1),
+ IM_LEN(in,2), NBADLINES(ccd), inbuf)
+ else
+ inbuf = imgl2s (in, inline)
+
+ # IF there are bad columns call a procedure to fix them.
+ if (NBADCOLS(ccd) != 0)
+ call cfixs (inline, Mems[BADCOLS(ccd)], IM_LEN(in,1),
+ IM_LEN(in,2), NBADCOLS(ccd), Mems[inbuf])
+
+ # Move the pixels to the output line.
+ if (IN_SEC(ccd) == NULL)
+ call amovs (Mems[inbuf+IN_C1(ccd)-OUT_C1(ccd)], output, ncols)
+ else {
+ do i = 1, IN_NSEC(ccd) {
+ if (inline < IN_SL1(ccd,i) || inline > IN_SL2(ccd,i))
+ next
+ call amovs (Mems[inbuf+IN_SC1(ccd,i)-OUT_C1(ccd)],
+ output[OUT_SC1(ccd,i)], OUT_SC2(ccd,i)-OUT_SC1(ccd,i)+1)
+ }
+ }
+end
+
+
+# CFIX -- Interpolate across bad columns defined in the bad column array.
+
+procedure cfixs (line, badcols, ncols, nlines, nbadcols, data)
+
+int line # Line to be fixed
+short badcols[2, nlines, nbadcols] # Bad column array
+int ncols # Number of columns
+int nlines # Number of lines
+int nbadcols # Number of bad column regions
+short data[ncols] # Data to be fixed
+
+short val
+real del
+int i, j, col1, col2
+
+begin
+ do i = 1, nbadcols {
+ col1 = badcols[1, line, i]
+ if (col1 == 0) # No bad columns
+ return
+ col2 = badcols[2, line, i]
+ if (col1 == 1) { # Bad first column
+ val = data[col2+1]
+ do j = col1, col2
+ data[j] = val
+ } else if (col2 == ncols) { # Bad last column
+ val = data[col1-1]
+ do j = col1, col2
+ data[j] = val
+ } else { # Interpolate
+ del = (data[col2+1] - data[col1-1]) / (col2 - col1 + 2)
+ val = data[col1-1] + del
+ do j = col1, col2
+ data[j] = val + (j - col1) * del
+ }
+ }
+end
+
+
+# LFIX -- Get image line and replace bad pixels by interpolation from
+# neighboring lines. Internal buffers are used to keep the last fixed
+# line and the next good line. They are allocated with LFIXINIT and
+# freed with LFIXFREE.
+
+procedure lfixs (im, line, badlines, ncols, nlines, nbadlines, data)
+
+pointer im # IMIO pointer
+int line # Line to be obtained and fixed
+short badlines[2,nlines,nbadlines] # Bad line region array
+int ncols # Number of columns in image
+int nlines # Number of lines in images
+int nbadlines # Number of bad line regions
+pointer data # Data line pointer (returned)
+
+real wt1, wt2
+int i, nextgood, lastgood, col1, col2
+pointer imgl2s()
+
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ # If this line has bad pixels replace them. Otherwise just
+ # read the line.
+
+ if (badlines[1, line, 1] != 0) {
+ # Save the last line which has already been fixed.
+ if (line != 1)
+ call amovs (Mems[data], Mems[lastbuf], ncols)
+
+ # Determine the next line with no bad line pixels. Note that
+ # this requirement is overly strict since the bad columns
+ # may not be the same in neighboring lines.
+
+ nextgood = 0
+ do i = line+1, nlines {
+ if (badlines[1, i, 1] == 0) {
+ nextgood = i
+ break
+ }
+ }
+
+ # If the next good line is not the same as previously
+ # read the data line and store it in a buffer.
+
+ if ((nextgood != lastgood) && (nextgood != 0)) {
+ data = imgl2s (im, nextgood)
+ call amovs (Mems[data], Mems[nextbuf], ncols)
+ lastgood = nextgood
+ }
+
+ # Get the data line.
+ data = imgl2s (im, line)
+
+ # Interpolate the bad columns. At the ends of the image use
+ # extension otherwise use linear interpolation.
+
+ if (line == 1) { # First line is bad
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i]
+ call amovs (Mems[nextbuf+col1], Mems[data+col1],
+ col2-col1)
+ }
+ } else if (nextgood == 0) { # Last line is bad
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i]
+ call amovs (Mems[lastbuf+col1], Mems[data+col1],
+ col2-col1)
+ }
+ } else { # Interpolate
+ wt1 = 1. / (nextgood - line + 1)
+ wt2 = 1. - wt1
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i] - 1
+ call awsus (Mems[nextbuf+col1], Mems[lastbuf+col1],
+ Mems[data+col1], col2-col1+1, wt1, wt2)
+ }
+ }
+ } else
+ data = imgl2s (im, line)
+end
+
+
+# LFIXINIT -- Allocate internal buffers.
+
+procedure lfixinits (im)
+
+pointer im # IMIO pointer
+
+int lastgood
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ call malloc (lastbuf, IM_LEN(im,1), TY_SHORT)
+ call malloc (nextbuf, IM_LEN(im,1), TY_SHORT)
+ lastgood=0
+end
+
+# LFIXFREE -- Free memory when the last line has been obtained.
+
+procedure lfixfrees ()
+
+int lastgood
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ call mfree (lastbuf, TY_SHORT)
+ call mfree (nextbuf, TY_SHORT)
+end
+
+# CORINPUT -- Get an input image line, fix the bad pixels, and trim.
+# Return the corrected input line in the output array.
+
+procedure corinputr (in, line, ccd, output, ncols)
+
+pointer in # Input IMIO pointer
+int line # Corrected output line
+pointer ccd # CCD pointer
+real output[ncols] # Output data (returned)
+int ncols # Number of output columns
+
+int i, inline
+pointer inbuf, imgl2r()
+
+begin
+ # Determine the input line in terms of the trimmed output line.
+ if (IN_SEC(ccd) == NULL)
+ inline = IN_L1(ccd) + line - 1
+ else {
+ do i = 1, IN_NSEC(ccd) {
+ if (line < OUT_SL1(ccd,i) || line > OUT_SL2(ccd,i))
+ next
+ inline = IN_SL1(ccd,i) + line - OUT_SL1(ccd,i)
+ break
+ }
+ }
+
+ # If there are bad lines call a procedure to fix them. Otherwise
+ # read the image line directly.
+
+ if (NBADLINES(ccd) != 0)
+ call lfixr (in, inline, Mems[BADLINES(ccd)], IM_LEN(in,1),
+ IM_LEN(in,2), NBADLINES(ccd), inbuf)
+ else
+ inbuf = imgl2r (in, inline)
+
+ # IF there are bad columns call a procedure to fix them.
+ if (NBADCOLS(ccd) != 0)
+ call cfixr (inline, Mems[BADCOLS(ccd)], IM_LEN(in,1),
+ IM_LEN(in,2), NBADCOLS(ccd), Memr[inbuf])
+
+ # Move the pixels to the output line.
+ if (IN_SEC(ccd) == NULL)
+ call amovr (Memr[inbuf+IN_C1(ccd)-OUT_C1(ccd)], output, ncols)
+ else {
+ do i = 1, IN_NSEC(ccd) {
+ if (inline < IN_SL1(ccd,i) || inline > IN_SL2(ccd,i))
+ next
+ call amovr (Memr[inbuf+IN_SC1(ccd,i)-OUT_C1(ccd)],
+ output[OUT_SC1(ccd,i)], OUT_SC2(ccd,i)-OUT_SC1(ccd,i)+1)
+ }
+ }
+end
+
+
+# CFIX -- Interpolate across bad columns defined in the bad column array.
+
+procedure cfixr (line, badcols, ncols, nlines, nbadcols, data)
+
+int line # Line to be fixed
+short badcols[2, nlines, nbadcols] # Bad column array
+int ncols # Number of columns
+int nlines # Number of lines
+int nbadcols # Number of bad column regions
+real data[ncols] # Data to be fixed
+
+real val
+real del
+int i, j, col1, col2
+
+begin
+ do i = 1, nbadcols {
+ col1 = badcols[1, line, i]
+ if (col1 == 0) # No bad columns
+ return
+ col2 = badcols[2, line, i]
+ if (col1 == 1) { # Bad first column
+ val = data[col2+1]
+ do j = col1, col2
+ data[j] = val
+ } else if (col2 == ncols) { # Bad last column
+ val = data[col1-1]
+ do j = col1, col2
+ data[j] = val
+ } else { # Interpolate
+ del = (data[col2+1] - data[col1-1]) / (col2 - col1 + 2)
+ val = data[col1-1] + del
+ do j = col1, col2
+ data[j] = val + (j - col1) * del
+ }
+ }
+end
+
+
+# LFIX -- Get image line and replace bad pixels by interpolation from
+# neighboring lines. Internal buffers are used to keep the last fixed
+# line and the next good line. They are allocated with LFIXINIT and
+# freed with LFIXFREE.
+
+procedure lfixr (im, line, badlines, ncols, nlines, nbadlines, data)
+
+pointer im # IMIO pointer
+int line # Line to be obtained and fixed
+short badlines[2,nlines,nbadlines] # Bad line region array
+int ncols # Number of columns in image
+int nlines # Number of lines in images
+int nbadlines # Number of bad line regions
+pointer data # Data line pointer (returned)
+
+real wt1, wt2
+int i, nextgood, lastgood, col1, col2
+pointer imgl2r()
+
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ # If this line has bad pixels replace them. Otherwise just
+ # read the line.
+
+ if (badlines[1, line, 1] != 0) {
+ # Save the last line which has already been fixed.
+ if (line != 1)
+ call amovr (Memr[data], Memr[lastbuf], ncols)
+
+ # Determine the next line with no bad line pixels. Note that
+ # this requirement is overly strict since the bad columns
+ # may not be the same in neighboring lines.
+
+ nextgood = 0
+ do i = line+1, nlines {
+ if (badlines[1, i, 1] == 0) {
+ nextgood = i
+ break
+ }
+ }
+
+ # If the next good line is not the same as previously
+ # read the data line and store it in a buffer.
+
+ if ((nextgood != lastgood) && (nextgood != 0)) {
+ data = imgl2r (im, nextgood)
+ call amovr (Memr[data], Memr[nextbuf], ncols)
+ lastgood = nextgood
+ }
+
+ # Get the data line.
+ data = imgl2r (im, line)
+
+ # Interpolate the bad columns. At the ends of the image use
+ # extension otherwise use linear interpolation.
+
+ if (line == 1) { # First line is bad
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i]
+ call amovr (Memr[nextbuf+col1], Memr[data+col1],
+ col2-col1)
+ }
+ } else if (nextgood == 0) { # Last line is bad
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i]
+ call amovr (Memr[lastbuf+col1], Memr[data+col1],
+ col2-col1)
+ }
+ } else { # Interpolate
+ wt1 = 1. / (nextgood - line + 1)
+ wt2 = 1. - wt1
+ do i = 1, nbadlines {
+ col1 = badlines[1,line,i] - 1
+ if (col1 == -1)
+ break
+ col2 = badlines[2,line,i] - 1
+ call awsur (Memr[nextbuf+col1], Memr[lastbuf+col1],
+ Memr[data+col1], col2-col1+1, wt1, wt2)
+ }
+ }
+ } else
+ data = imgl2r (im, line)
+end
+
+
+# LFIXINIT -- Allocate internal buffers.
+
+procedure lfixinitr (im)
+
+pointer im # IMIO pointer
+
+int lastgood
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ call malloc (lastbuf, IM_LEN(im,1), TY_REAL)
+ call malloc (nextbuf, IM_LEN(im,1), TY_REAL)
+ lastgood=0
+end
+
+# LFIXFREE -- Free memory when the last line has been obtained.
+
+procedure lfixfreer ()
+
+int lastgood
+pointer lastbuf, nextbuf
+common /lfixcom/ lastbuf, nextbuf, lastgood
+
+begin
+ call mfree (lastbuf, TY_REAL)
+ call mfree (nextbuf, TY_REAL)
+end
+
diff --git a/noao/imred/quadred/src/ccdproc/generic/mkpkg b/noao/imred/quadred/src/ccdproc/generic/mkpkg
new file mode 100644
index 00000000..0f12b368
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/generic/mkpkg
@@ -0,0 +1,12 @@
+# Make CCDRED Package.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ cor.x ccdred.h
+ corinput.x ccdred.h <imhdr.h>
+ proc.x ccdred.h <imhdr.h>
+ ;
diff --git a/noao/imred/quadred/src/ccdproc/generic/proc.x b/noao/imred/quadred/src/ccdproc/generic/proc.x
new file mode 100644
index 00000000..0251f4f8
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/generic/proc.x
@@ -0,0 +1,678 @@
+include <imhdr.h>
+include "ccdred.h"
+
+
+.help proc Feb87 noao.imred.ccdred
+.nf ----------------------------------------------------------------------------
+proc -- Process CCD images
+
+These are the main CCD reduction procedures. There is one for each
+readout axis (lines or columns) and one for short and real image data.
+They apply corrections for bad pixels, overscan levels, zero levels,
+dark counts, flat field response, illumination response, and fringe
+effects. The image is also trimmed if it was mapped with an image
+section. The mean value for the output image is computed when the flat
+field or illumination image is processed to form the scale factor for
+these calibrations in order to avoid reading through these image a
+second time.
+
+The processing information and parameters are specified in the CCD
+structure. The processing operations to be performed are specified by
+the correction array CORS in the ccd structure. There is one array
+element for each operation with indices defined symbolically by macro
+definitions (see ccdred.h); i.e. FLATCOR. The value of the array
+element is an integer bit field in which the bit set is the same as the
+array index; i.e element 3 will have the third bit set for an operation
+with array value 2**(3-1)=4. If an operation is not to be performed
+the bit is not set and the array element has the numeric value zero.
+Note that the addition of several correction elements gives a unique
+bit field describing a combination of operations. For efficiency the
+most common combinations are implemented as separate units.
+
+The CCD structure also contains the correction or calibration data
+consisting either pointers to data, IMIO pointers for the calibration
+images, and scale factors.
+
+The processing is performed line-by-line. The procedure CORINPUT is
+called to get an input line. This procedure trims and fixes bad pixels by
+interpolation. The output line and lines from the various calibration
+images are read. The image vectors as well as the overscan vector and
+the scale factors are passed to the procedure COR (which also
+dereferences the pointer data into simple arrays and variables). That
+procedure does the actual corrections apart from bad pixel
+corrections.
+
+The final optional step is to add each corrected output line to form a
+mean. This adds efficiency since the operation is done only if desired
+and the output image data is already in memory so there is no I/O
+penalty.
+
+SEE ALSO
+ ccdred.h, cor, fixpix, setfixpix, setoverscan, settrim,
+ setzero, setdark, setflat, setillum, setfringe
+.endhelp ----------------------------------------------------------------------
+
+
+
+# PROC1 -- Process CCD images with readout axis 1 (lines).
+
+procedure proc1s (ccd)
+
+pointer ccd # CCD structure
+
+int i, line, nlin, ncols, nlines, findmean, rep
+int c1, c2, l1, l2
+real overscan, darkscale, flatscale, illumscale, frgscale, mean
+short minrep
+pointer in, out, zeroim, darkim, flatim, illumim, fringeim
+pointer outbuf, overscan_vec, zerobuf, darkbuf, flatbuf, illumbuf, fringebuf
+
+real asums()
+pointer imgl2s(), impl2s(), ccd_gls()
+
+begin
+ # Initialize. If the correction image is 1D then just get the
+ # data once.
+
+ in = IN_IM(ccd)
+ out = OUT_IM(ccd)
+ nlin = IM_LEN(in,2)
+ ncols = OUT_C2(ccd) - OUT_C1(ccd) + 1
+ nlines = OUT_L2(ccd) - OUT_L1(ccd) + 1
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixinits (in)
+
+ findmean = CORS(ccd, FINDMEAN)
+ if (findmean == YES)
+ mean = 0.
+ rep = CORS(ccd, MINREP)
+ if (rep == YES)
+ minrep = MINREPLACE(ccd)
+
+ overscan_vec = OVERSCAN_VEC(ccd)
+
+ if (CORS(ccd, ZEROCOR) == 0) {
+ zeroim = NULL
+ zerobuf = 1
+ } else if (IM_LEN(ZERO_IM(ccd),2) == 1) {
+ zeroim = NULL
+ zerobuf = ccd_gls (ZERO_IM(ccd), ZERO_C1(ccd), ZERO_C2(ccd), 1)
+ } else
+ zeroim = ZERO_IM(ccd)
+
+ if (CORS(ccd, DARKCOR) == 0) {
+ darkim = NULL
+ darkbuf = 1
+ } else if (IM_LEN(DARK_IM(ccd),2) == 1) {
+ darkim = NULL
+ darkbuf = ccd_gls (DARK_IM(ccd), DARK_C1(ccd), DARK_C2(ccd), 1)
+ darkscale = FLATSCALE(ccd)
+ } else {
+ darkim = DARK_IM(ccd)
+ darkscale = DARKSCALE(ccd)
+ }
+
+ if (CORS(ccd, FLATCOR) == 0) {
+ flatim = NULL
+ flatbuf = 1
+ } else if (IM_LEN(FLAT_IM(ccd),2) == 1) {
+ flatim = NULL
+ flatbuf = ccd_gls (FLAT_IM(ccd), FLAT_C1(ccd), FLAT_C2(ccd), 1)
+ flatscale = FLATSCALE(ccd)
+ } else {
+ flatim = FLAT_IM(ccd)
+ flatscale = FLATSCALE(ccd)
+ }
+
+ if (CORS(ccd, ILLUMCOR) == 0) {
+ illumim = NULL
+ illumbuf = 1
+ } else {
+ illumim = ILLUM_IM(ccd)
+ illumscale = ILLUMSCALE(ccd)
+ }
+
+ if (CORS(ccd, FRINGECOR) == 0) {
+ fringeim = NULL
+ fringebuf = 1
+ } else {
+ fringeim = FRINGE_IM(ccd)
+ frgscale = FRINGESCALE(ccd)
+ }
+
+ # For each line read lines from the input. Procedure CORINPUT
+ # replaces bad pixels by interpolation and applies a trim to the
+ # input. Get lines from the output image and from the zero level,
+ # dark count, flat field, illumination, and fringe images.
+ # Call COR1 to do the actual pixel corrections. Finally, add the
+ # output pixels to a sum for computing the mean.
+ # We must copy data outside of the output data section.
+
+ do line = 2 - OUT_L1(ccd), 0
+ call amovs (
+ Mems[imgl2s(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mems[impl2s(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ do line = 1, nlines {
+ outbuf = impl2s (out, OUT_L1(ccd)+line-1)
+ call corinputs (in, line, ccd, Mems[outbuf], IM_LEN(out,1))
+
+ outbuf = outbuf + OUT_C1(ccd) - 1
+ if (overscan_vec != NULL)
+ overscan = Memr[overscan_vec+line-1]
+ if (zeroim != NULL)
+ zerobuf = ccd_gls (zeroim, ZERO_C1(ccd), ZERO_C2(ccd),
+ ZERO_L1(ccd)+line-1)
+ if (darkim != NULL)
+ darkbuf = ccd_gls (darkim, DARK_C1(ccd), DARK_C2(ccd),
+ DARK_L1(ccd)+line-1)
+ if (flatim != NULL)
+ flatbuf = ccd_gls (flatim, FLAT_C1(ccd), FLAT_C2(ccd),
+ FLAT_L1(ccd)+line-1)
+ if (illumim != NULL)
+ illumbuf = ccd_gls (illumim, ILLUM_C1(ccd), ILLUM_C2(ccd),
+ ILLUM_L1(ccd)+line-1)
+ if (fringeim != NULL)
+ fringebuf = ccd_gls (fringeim, FRINGE_C1(ccd), FRINGE_C2(ccd),
+ FRINGE_L1(ccd)+line-1)
+
+ if (OUT_SEC(ccd) == NULL) {
+ call cor1s (CORS(ccd,1), Mems[outbuf],
+ overscan, Mems[zerobuf], Mems[darkbuf],
+ Mems[flatbuf], Mems[illumbuf], Mems[fringebuf], ncols,
+ darkscale, flatscale, illumscale, frgscale)
+ } else {
+ do i = 1, IN_NSEC(ccd) {
+ l1 = OUT_SL1(ccd,i)
+ l2 = OUT_SL2(ccd,i)
+ if (line < l1 || line > l2)
+ next
+ c1 = OUT_SC1(ccd,i) - 1
+ c2 = OUT_SC2(ccd,i) - 1
+ ncols = c2 - c1 + 1
+ if (overscan_vec != NULL)
+ overscan = Memr[overscan_vec+(i-1)*nlin+line-l1]
+
+ call cor1s (CORS(ccd,1), Mems[outbuf+c1],
+ overscan, Mems[zerobuf+c1], Mems[darkbuf+c1],
+ Mems[flatbuf+c1], Mems[illumbuf+c1],
+ Mems[fringebuf+c1], ncols,
+ darkscale, flatscale, illumscale, frgscale)
+ }
+ }
+
+ if (rep == YES)
+ call amaxks (Mems[outbuf], minrep, Mems[outbuf], ncols)
+ if (findmean == YES)
+ mean = mean + asums (Mems[outbuf], ncols)
+ }
+
+ do line = nlines+1, IM_LEN(out,2)-OUT_L1(ccd)+1
+ call amovs (
+ Mems[imgl2s(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mems[impl2s(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ # Compute the mean from the sum of the output pixels.
+ if (findmean == YES)
+ MEAN(ccd) = mean / ncols / nlines
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixfrees ()
+end
+
+
+# PROC2 -- Process CCD images with readout axis 2 (columns).
+
+procedure proc2s (ccd)
+
+pointer ccd # CCD structure
+
+int line, ncols, nlines, findmean, rep
+real darkscale, flatscale, illumscale, frgscale, mean
+short minrep
+pointer in, out, zeroim, darkim, flatim, illumim, fringeim
+pointer outbuf, overscan_vec, zerobuf, darkbuf, flatbuf, illumbuf, fringebuf
+
+real asums()
+pointer imgl2s(), impl2s(), imgs2s(), ccd_gls()
+
+begin
+ # Initialize. If the correction image is 1D then just get the
+ # data once.
+
+ in = IN_IM(ccd)
+ out = OUT_IM(ccd)
+ ncols = OUT_C2(ccd) - OUT_C1(ccd) + 1
+ nlines = OUT_L2(ccd) - OUT_L1(ccd) + 1
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixinits (in)
+
+ findmean = CORS(ccd, FINDMEAN)
+ if (findmean == YES)
+ mean = 0.
+ rep = CORS(ccd, MINREP)
+ if (rep == YES)
+ minrep = MINREPLACE(ccd)
+
+ overscan_vec = OVERSCAN_VEC(ccd)
+
+ if (CORS(ccd, ZEROCOR) == 0) {
+ zeroim = NULL
+ zerobuf = 1
+ } else if (IM_LEN(ZERO_IM(ccd),1) == 1) {
+ zeroim = NULL
+ zerobuf = imgs2s (ZERO_IM(ccd), 1, 1, ZERO_L1(ccd), ZERO_L2(ccd))
+ } else
+ zeroim = ZERO_IM(ccd)
+
+ if (CORS(ccd, DARKCOR) == 0) {
+ darkim = NULL
+ darkbuf = 1
+ } else if (IM_LEN(DARK_IM(ccd),1) == 1) {
+ darkim = NULL
+ darkbuf = imgs2s (DARK_IM(ccd), 1, 1, DARK_L1(ccd), DARK_L2(ccd))
+ darkscale = DARKSCALE(ccd)
+ } else {
+ darkim = DARK_IM(ccd)
+ darkscale = DARKSCALE(ccd)
+ }
+
+ if (CORS(ccd, FLATCOR) == 0) {
+ flatim = NULL
+ flatbuf = 1
+ } else if (IM_LEN(FLAT_IM(ccd),1) == 1) {
+ flatim = NULL
+ flatbuf = imgs2s (FLAT_IM(ccd), 1, 1, FLAT_L1(ccd), FLAT_L2(ccd))
+ flatscale = FLATSCALE(ccd)
+ } else {
+ flatim = FLAT_IM(ccd)
+ flatscale = FLATSCALE(ccd)
+ }
+
+ if (CORS(ccd, ILLUMCOR) == 0) {
+ illumim = NULL
+ illumbuf = 1
+ } else {
+ illumim = ILLUM_IM(ccd)
+ illumscale = ILLUMSCALE(ccd)
+ }
+
+ if (CORS(ccd, FRINGECOR) == 0) {
+ fringeim = NULL
+ fringebuf = 1
+ } else {
+ fringeim = FRINGE_IM(ccd)
+ frgscale = FRINGESCALE(ccd)
+ }
+
+ # For each line read lines from the input. Procedure CORINPUT
+ # replaces bad pixels by interpolation and applies a trim to the
+ # input. Get lines from the output image and from the zero level,
+ # dark count, flat field, illumination, and fringe images.
+ # Call COR2 to do the actual pixel corrections. Finally, add the
+ # output pixels to a sum for computing the mean.
+ # We must copy data outside of the output data section.
+
+ do line = 2 - OUT_L1(ccd), 0
+ call amovs (
+ Mems[imgl2s(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mems[impl2s(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ do line = 1, nlines {
+ outbuf = impl2s (out, OUT_L1(ccd)+line-1)
+ call corinputs (in, line, ccd, Mems[outbuf], IM_LEN(out,1))
+
+ outbuf = outbuf + OUT_C1(ccd) - 1
+ if (zeroim != NULL)
+ zerobuf = ccd_gls (zeroim, ZERO_C1(ccd), ZERO_C2(ccd),
+ ZERO_L1(ccd)+line-1)
+ if (darkim != NULL)
+ darkbuf = ccd_gls (darkim, DARK_C1(ccd), DARK_C2(ccd),
+ DARK_L1(ccd)+line-1)
+ if (flatim != NULL)
+ flatbuf = ccd_gls (flatim, FLAT_C1(ccd), FLAT_C2(ccd),
+ FLAT_L1(ccd)+line-1)
+ if (illumim != NULL)
+ illumbuf = ccd_gls (illumim, ILLUM_C1(ccd), ILLUM_C2(ccd),
+ ILLUM_L1(ccd)+line-1)
+ if (fringeim != NULL)
+ fringebuf = ccd_gls (fringeim, FRINGE_C1(ccd), FRINGE_C2(ccd),
+ FRINGE_L1(ccd)+line-1)
+
+ call cor2s (line, CORS(ccd,1), Mems[outbuf],
+ Memr[overscan_vec], Mems[zerobuf], Mems[darkbuf],
+ Mems[flatbuf], Mems[illumbuf], Mems[fringebuf], ncols,
+ zeroim, flatim, darkscale, flatscale, illumscale, frgscale)
+
+ if (rep == YES)
+ call amaxks (Mems[outbuf], minrep, Mems[outbuf], ncols)
+ if (findmean == YES)
+ mean = mean + asums (Mems[outbuf], ncols)
+ }
+
+ do line = nlines+1, IM_LEN(out,2)-OUT_L1(ccd)+1
+ call amovs (
+ Mems[imgl2s(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mems[impl2s(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ # Compute the mean from the sum of the output pixels.
+ if (findmean == YES)
+ MEAN(ccd) = mean / ncols / nlines
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixfrees ()
+end
+
+# PROC1 -- Process CCD images with readout axis 1 (lines).
+
+procedure proc1r (ccd)
+
+pointer ccd # CCD structure
+
+int i, line, nlin, ncols, nlines, findmean, rep
+int c1, c2, l1, l2
+real overscan, darkscale, flatscale, illumscale, frgscale, mean
+real minrep
+pointer in, out, zeroim, darkim, flatim, illumim, fringeim
+pointer outbuf, overscan_vec, zerobuf, darkbuf, flatbuf, illumbuf, fringebuf
+
+real asumr()
+pointer imgl2r(), impl2r(), ccd_glr()
+
+begin
+ # Initialize. If the correction image is 1D then just get the
+ # data once.
+
+ in = IN_IM(ccd)
+ out = OUT_IM(ccd)
+ nlin = IM_LEN(in,2)
+ ncols = OUT_C2(ccd) - OUT_C1(ccd) + 1
+ nlines = OUT_L2(ccd) - OUT_L1(ccd) + 1
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixinitr (in)
+
+ findmean = CORS(ccd, FINDMEAN)
+ if (findmean == YES)
+ mean = 0.
+ rep = CORS(ccd, MINREP)
+ if (rep == YES)
+ minrep = MINREPLACE(ccd)
+
+ overscan_vec = OVERSCAN_VEC(ccd)
+
+ if (CORS(ccd, ZEROCOR) == 0) {
+ zeroim = NULL
+ zerobuf = 1
+ } else if (IM_LEN(ZERO_IM(ccd),2) == 1) {
+ zeroim = NULL
+ zerobuf = ccd_glr (ZERO_IM(ccd), ZERO_C1(ccd), ZERO_C2(ccd), 1)
+ } else
+ zeroim = ZERO_IM(ccd)
+
+ if (CORS(ccd, DARKCOR) == 0) {
+ darkim = NULL
+ darkbuf = 1
+ } else if (IM_LEN(DARK_IM(ccd),2) == 1) {
+ darkim = NULL
+ darkbuf = ccd_glr (DARK_IM(ccd), DARK_C1(ccd), DARK_C2(ccd), 1)
+ darkscale = FLATSCALE(ccd)
+ } else {
+ darkim = DARK_IM(ccd)
+ darkscale = DARKSCALE(ccd)
+ }
+
+ if (CORS(ccd, FLATCOR) == 0) {
+ flatim = NULL
+ flatbuf = 1
+ } else if (IM_LEN(FLAT_IM(ccd),2) == 1) {
+ flatim = NULL
+ flatbuf = ccd_glr (FLAT_IM(ccd), FLAT_C1(ccd), FLAT_C2(ccd), 1)
+ flatscale = FLATSCALE(ccd)
+ } else {
+ flatim = FLAT_IM(ccd)
+ flatscale = FLATSCALE(ccd)
+ }
+
+ if (CORS(ccd, ILLUMCOR) == 0) {
+ illumim = NULL
+ illumbuf = 1
+ } else {
+ illumim = ILLUM_IM(ccd)
+ illumscale = ILLUMSCALE(ccd)
+ }
+
+ if (CORS(ccd, FRINGECOR) == 0) {
+ fringeim = NULL
+ fringebuf = 1
+ } else {
+ fringeim = FRINGE_IM(ccd)
+ frgscale = FRINGESCALE(ccd)
+ }
+
+ # For each line read lines from the input. Procedure CORINPUT
+ # replaces bad pixels by interpolation and applies a trim to the
+ # input. Get lines from the output image and from the zero level,
+ # dark count, flat field, illumination, and fringe images.
+ # Call COR1 to do the actual pixel corrections. Finally, add the
+ # output pixels to a sum for computing the mean.
+ # We must copy data outside of the output data section.
+
+ do line = 2 - OUT_L1(ccd), 0
+ call amovr (
+ Memr[imgl2r(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Memr[impl2r(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ do line = 1, nlines {
+ outbuf = impl2r (out, OUT_L1(ccd)+line-1)
+ call corinputr (in, line, ccd, Memr[outbuf], IM_LEN(out,1))
+
+ outbuf = outbuf + OUT_C1(ccd) - 1
+ if (overscan_vec != NULL)
+ overscan = Memr[overscan_vec+line-1]
+ if (zeroim != NULL)
+ zerobuf = ccd_glr (zeroim, ZERO_C1(ccd), ZERO_C2(ccd),
+ ZERO_L1(ccd)+line-1)
+ if (darkim != NULL)
+ darkbuf = ccd_glr (darkim, DARK_C1(ccd), DARK_C2(ccd),
+ DARK_L1(ccd)+line-1)
+ if (flatim != NULL)
+ flatbuf = ccd_glr (flatim, FLAT_C1(ccd), FLAT_C2(ccd),
+ FLAT_L1(ccd)+line-1)
+ if (illumim != NULL)
+ illumbuf = ccd_glr (illumim, ILLUM_C1(ccd), ILLUM_C2(ccd),
+ ILLUM_L1(ccd)+line-1)
+ if (fringeim != NULL)
+ fringebuf = ccd_glr (fringeim, FRINGE_C1(ccd), FRINGE_C2(ccd),
+ FRINGE_L1(ccd)+line-1)
+
+ if (OUT_SEC(ccd) == NULL) {
+ call cor1r (CORS(ccd,1), Memr[outbuf],
+ overscan, Memr[zerobuf], Memr[darkbuf],
+ Memr[flatbuf], Memr[illumbuf], Memr[fringebuf], ncols,
+ darkscale, flatscale, illumscale, frgscale)
+ } else {
+ do i = 1, IN_NSEC(ccd) {
+ l1 = OUT_SL1(ccd,i)
+ l2 = OUT_SL2(ccd,i)
+ if (line < l1 || line > l2)
+ next
+ c1 = OUT_SC1(ccd,i) - 1
+ c2 = OUT_SC2(ccd,i) - 1
+ ncols = c2 - c1 + 1
+ if (overscan_vec != NULL)
+ overscan = Memr[overscan_vec+(i-1)*nlin+line-l1]
+
+ call cor1r (CORS(ccd,1), Memr[outbuf+c1],
+ overscan, Memr[zerobuf+c1], Memr[darkbuf+c1],
+ Memr[flatbuf+c1], Memr[illumbuf+c1],
+ Memr[fringebuf+c1], ncols,
+ darkscale, flatscale, illumscale, frgscale)
+ }
+ }
+
+ if (rep == YES)
+ call amaxkr (Memr[outbuf], minrep, Memr[outbuf], ncols)
+ if (findmean == YES)
+ mean = mean + asumr (Memr[outbuf], ncols)
+ }
+
+ do line = nlines+1, IM_LEN(out,2)-OUT_L1(ccd)+1
+ call amovr (
+ Memr[imgl2r(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Memr[impl2r(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ # Compute the mean from the sum of the output pixels.
+ if (findmean == YES)
+ MEAN(ccd) = mean / ncols / nlines
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixfreer ()
+end
+
+
+# PROC2 -- Process CCD images with readout axis 2 (columns).
+
+procedure proc2r (ccd)
+
+pointer ccd # CCD structure
+
+int line, ncols, nlines, findmean, rep
+real darkscale, flatscale, illumscale, frgscale, mean
+real minrep
+pointer in, out, zeroim, darkim, flatim, illumim, fringeim
+pointer outbuf, overscan_vec, zerobuf, darkbuf, flatbuf, illumbuf, fringebuf
+
+real asumr()
+pointer imgl2r(), impl2r(), imgs2r(), ccd_glr()
+
+begin
+ # Initialize. If the correction image is 1D then just get the
+ # data once.
+
+ in = IN_IM(ccd)
+ out = OUT_IM(ccd)
+ ncols = OUT_C2(ccd) - OUT_C1(ccd) + 1
+ nlines = OUT_L2(ccd) - OUT_L1(ccd) + 1
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixinitr (in)
+
+ findmean = CORS(ccd, FINDMEAN)
+ if (findmean == YES)
+ mean = 0.
+ rep = CORS(ccd, MINREP)
+ if (rep == YES)
+ minrep = MINREPLACE(ccd)
+
+ overscan_vec = OVERSCAN_VEC(ccd)
+
+ if (CORS(ccd, ZEROCOR) == 0) {
+ zeroim = NULL
+ zerobuf = 1
+ } else if (IM_LEN(ZERO_IM(ccd),1) == 1) {
+ zeroim = NULL
+ zerobuf = imgs2r (ZERO_IM(ccd), 1, 1, ZERO_L1(ccd), ZERO_L2(ccd))
+ } else
+ zeroim = ZERO_IM(ccd)
+
+ if (CORS(ccd, DARKCOR) == 0) {
+ darkim = NULL
+ darkbuf = 1
+ } else if (IM_LEN(DARK_IM(ccd),1) == 1) {
+ darkim = NULL
+ darkbuf = imgs2r (DARK_IM(ccd), 1, 1, DARK_L1(ccd), DARK_L2(ccd))
+ darkscale = DARKSCALE(ccd)
+ } else {
+ darkim = DARK_IM(ccd)
+ darkscale = DARKSCALE(ccd)
+ }
+
+ if (CORS(ccd, FLATCOR) == 0) {
+ flatim = NULL
+ flatbuf = 1
+ } else if (IM_LEN(FLAT_IM(ccd),1) == 1) {
+ flatim = NULL
+ flatbuf = imgs2r (FLAT_IM(ccd), 1, 1, FLAT_L1(ccd), FLAT_L2(ccd))
+ flatscale = FLATSCALE(ccd)
+ } else {
+ flatim = FLAT_IM(ccd)
+ flatscale = FLATSCALE(ccd)
+ }
+
+ if (CORS(ccd, ILLUMCOR) == 0) {
+ illumim = NULL
+ illumbuf = 1
+ } else {
+ illumim = ILLUM_IM(ccd)
+ illumscale = ILLUMSCALE(ccd)
+ }
+
+ if (CORS(ccd, FRINGECOR) == 0) {
+ fringeim = NULL
+ fringebuf = 1
+ } else {
+ fringeim = FRINGE_IM(ccd)
+ frgscale = FRINGESCALE(ccd)
+ }
+
+ # For each line read lines from the input. Procedure CORINPUT
+ # replaces bad pixels by interpolation and applies a trim to the
+ # input. Get lines from the output image and from the zero level,
+ # dark count, flat field, illumination, and fringe images.
+ # Call COR2 to do the actual pixel corrections. Finally, add the
+ # output pixels to a sum for computing the mean.
+ # We must copy data outside of the output data section.
+
+ do line = 2 - OUT_L1(ccd), 0
+ call amovr (
+ Memr[imgl2r(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Memr[impl2r(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ do line = 1, nlines {
+ outbuf = impl2r (out, OUT_L1(ccd)+line-1)
+ call corinputr (in, line, ccd, Memr[outbuf], IM_LEN(out,1))
+
+ outbuf = outbuf + OUT_C1(ccd) - 1
+ if (zeroim != NULL)
+ zerobuf = ccd_glr (zeroim, ZERO_C1(ccd), ZERO_C2(ccd),
+ ZERO_L1(ccd)+line-1)
+ if (darkim != NULL)
+ darkbuf = ccd_glr (darkim, DARK_C1(ccd), DARK_C2(ccd),
+ DARK_L1(ccd)+line-1)
+ if (flatim != NULL)
+ flatbuf = ccd_glr (flatim, FLAT_C1(ccd), FLAT_C2(ccd),
+ FLAT_L1(ccd)+line-1)
+ if (illumim != NULL)
+ illumbuf = ccd_glr (illumim, ILLUM_C1(ccd), ILLUM_C2(ccd),
+ ILLUM_L1(ccd)+line-1)
+ if (fringeim != NULL)
+ fringebuf = ccd_glr (fringeim, FRINGE_C1(ccd), FRINGE_C2(ccd),
+ FRINGE_L1(ccd)+line-1)
+
+ call cor2r (line, CORS(ccd,1), Memr[outbuf],
+ Memr[overscan_vec], Memr[zerobuf], Memr[darkbuf],
+ Memr[flatbuf], Memr[illumbuf], Memr[fringebuf], ncols,
+ zeroim, flatim, darkscale, flatscale, illumscale, frgscale)
+
+ if (rep == YES)
+ call amaxkr (Memr[outbuf], minrep, Memr[outbuf], ncols)
+ if (findmean == YES)
+ mean = mean + asumr (Memr[outbuf], ncols)
+ }
+
+ do line = nlines+1, IM_LEN(out,2)-OUT_L1(ccd)+1
+ call amovr (
+ Memr[imgl2r(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Memr[impl2r(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ # Compute the mean from the sum of the output pixels.
+ if (findmean == YES)
+ MEAN(ccd) = mean / ncols / nlines
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixfreer ()
+end
+
diff --git a/noao/imred/quadred/src/ccdproc/hdrmap.com b/noao/imred/quadred/src/ccdproc/hdrmap.com
new file mode 100644
index 00000000..5aa74185
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/hdrmap.com
@@ -0,0 +1,4 @@
+# Common for HDRMAP package.
+
+pointer stp # Symbol table pointer
+common /hdmcom/ stp
diff --git a/noao/imred/quadred/src/ccdproc/hdrmap.x b/noao/imred/quadred/src/ccdproc/hdrmap.x
new file mode 100644
index 00000000..ebcb253e
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/hdrmap.x
@@ -0,0 +1,544 @@
+include <error.h>
+include <syserr.h>
+
+.help hdrmap
+.nf-----------------------------------------------------------------------------
+HDRMAP -- Map translation between task parameters and image header parameters.
+
+In order for tasks to be partially independent of the image header
+parameter names used by different instruments and observatories a
+translation is made between task parameters and image header
+parameters. This translation is given in a file consisting of the task
+parameter name, the image header parameter name, and an optional
+default value. This file is turned into a symbol table. If the
+translation file is not found a null pointer is returned. The package will
+then use the task parameter names directly. Also if there is no
+translation given in the file for a particular parameter it is passed
+on directly. If a parameter is not in the image header then the symbol
+table default value, if given, is returned. This package is layered on
+the IMIO header package.
+
+ hdmopen (fname)
+ hdmclose ()
+ hdmwrite (fname, mode)
+ hdmname (parameter, str, max_char)
+ hdmgdef (parameter, str, max_char)
+ hdmpdef (parameter, str, max_char)
+ y/n = hdmaccf (im, parameter)
+ hdmgstr (im, parameter, str, max_char)
+ ival = hdmgeti (im, parameter)
+ rval = hdmgetr (im, parameter)
+ hdmpstr (im, parameter, str)
+ hdmputi (im, parameter, value)
+ hdmputr (im, parameter, value)
+ hdmgstp (stp)
+ hdmpstp (stp)
+ hdmdelf (im, parameter)
+ hdmparm (name, parameter, max_char)
+
+hdmopen -- Open the translation file and map it into a symbol table pointer.
+hdmclose -- Close the symbol table pointer.
+hdmwrite -- Write out translation file.
+hdmname -- Return the image header parameter name.
+hdmpname -- Put the image header parameter name.
+hdmgdef -- Get the default value as a string (null if none).
+hdmpdef -- Put the default value as a string.
+hdmaccf -- Return whether the image header parameter exists (regardless of
+ whether there is a default value).
+hdmgstr -- Get a string valued parameter. Return default value if not in the
+ image header. Return null string if no default or image value.
+hdmgeti -- Get an integer valued parameter. Return default value if not in
+ the image header and error condition if no default or image value.
+hdmgetr -- Get a real valued parameter. Return default value if not in
+ the image header or error condition if no default or image value.
+hdmpstr -- Put a string valued parameter in the image header.
+hdmputi -- Put an integer valued parameter in the image header.
+hdmputr -- Put a real valued parameter in the image header.
+hdmgstp -- Get the symbol table pointer to save it while another map is used.
+hdmpstp -- Put the symbol table pointer to restore a map.
+hdmdelf -- Delete a field.
+hdmparm -- Return the parameter name corresponding to an image header name.
+.endhelp -----------------------------------------------------------------------
+
+# Symbol table definitions.
+define LEN_INDEX 32 # Length of symtab index
+define LEN_STAB 1024 # Length of symtab string buffer
+define SZ_SBUF 128 # Size of symtab string buffer
+
+define SZ_NAME 79 # Size of translation symbol name
+define SZ_DEFAULT 79 # Size of default string
+define SYMLEN 80 # Length of symbol structure
+
+# Symbol table structure
+define NAME Memc[P2C($1)] # Translation name for symbol
+define DEFAULT Memc[P2C($1+40)] # Default value of parameter
+
+
+# HDMOPEN -- Open the translation file and map it into a symbol table pointer.
+
+procedure hdmopen (fname)
+
+char fname[ARB] # Image header map file
+
+int fd, open(), fscan(), nscan(), errcode()
+pointer sp, parameter, sym, stopen(), stenter()
+include "hdrmap.com"
+
+begin
+ # Create an empty symbol table.
+ stp = stopen (fname, LEN_INDEX, LEN_STAB, SZ_SBUF)
+
+ # Return if file not found.
+ iferr (fd = open (fname, READ_ONLY, TEXT_FILE)) {
+ if (errcode () != SYS_FNOFNAME)
+ call erract (EA_WARN)
+ return
+ }
+
+ call smark (sp)
+ call salloc (parameter, SZ_NAME, TY_CHAR)
+
+ # Read the file an enter the translations in the symbol table.
+ while (fscan(fd) != EOF) {
+ call gargwrd (Memc[parameter], SZ_NAME)
+ if ((nscan() == 0) || (Memc[parameter] == '#'))
+ next
+ sym = stenter (stp, Memc[parameter], SYMLEN)
+ call gargwrd (NAME(sym), SZ_NAME)
+ call gargwrd (DEFAULT(sym), SZ_DEFAULT)
+ }
+
+ call close (fd)
+ call sfree (sp)
+end
+
+
+# HDMCLOSE -- Close the symbol table pointer.
+
+procedure hdmclose ()
+
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ call stclose (stp)
+end
+
+
+# HDMWRITE -- Write out translation file.
+
+procedure hdmwrite (fname, mode)
+
+char fname[ARB] # Image header map file
+int mode # Access mode (APPEND, NEW_FILE)
+
+int fd, open(), stridxs()
+pointer sym, sthead(), stnext(), stname()
+errchk open
+include "hdrmap.com"
+
+begin
+ # If there is no symbol table do nothing.
+ if (stp == NULL)
+ return
+
+ fd = open (fname, mode, TEXT_FILE)
+
+ sym = sthead (stp)
+ for (sym = sthead (stp); sym != NULL; sym = stnext (stp, sym)) {
+ if (stridxs (" ", Memc[stname (stp, sym)]) > 0)
+ call fprintf (fd, "'%s'%30t")
+ else
+ call fprintf (fd, "%s%30t")
+ call pargstr (Memc[stname (stp, sym)])
+ if (stridxs (" ", NAME(sym)) > 0)
+ call fprintf (fd, " '%s'%10t")
+ else
+ call fprintf (fd, " %s%10t")
+ call pargstr (NAME(sym))
+ if (DEFAULT(sym) != EOS) {
+ if (stridxs (" ", DEFAULT(sym)) > 0)
+ call fprintf (fd, " '%s'")
+ else
+ call fprintf (fd, " %s")
+ call pargstr (DEFAULT(sym))
+ }
+ call fprintf (fd, "\n")
+ }
+
+ call close (fd)
+end
+
+
+# HDMNAME -- Return the image header parameter name
+
+procedure hdmname (parameter, str, max_char)
+
+char parameter[ARB] # Parameter name
+char str[max_char] # String containing mapped parameter name
+int max_char # Maximum characters in string
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call strcpy (NAME(sym), str, max_char)
+ else
+ call strcpy (parameter, str, max_char)
+end
+
+
+# HDMPNAME -- Put the image header parameter name
+
+procedure hdmpname (parameter, str)
+
+char parameter[ARB] # Parameter name
+char str[ARB] # String containing mapped parameter name
+
+pointer sym, stfind(), stenter()
+include "hdrmap.com"
+
+begin
+ if (stp == NULL)
+ return
+
+ sym = stfind (stp, parameter)
+ if (sym == NULL) {
+ sym = stenter (stp, parameter, SYMLEN)
+ DEFAULT(sym) = EOS
+ }
+
+ call strcpy (str, NAME(sym), SZ_NAME)
+end
+
+
+# HDMGDEF -- Get the default value as a string (null string if none).
+
+procedure hdmgdef (parameter, str, max_char)
+
+char parameter[ARB] # Parameter name
+char str[max_char] # String containing default value
+int max_char # Maximum characters in string
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call strcpy (DEFAULT(sym), str, max_char)
+ else
+ str[1] = EOS
+end
+
+
+# HDMPDEF -- PUt the default value as a string.
+
+procedure hdmpdef (parameter, str)
+
+char parameter[ARB] # Parameter name
+char str[ARB] # String containing default value
+
+pointer sym, stfind(), stenter()
+include "hdrmap.com"
+
+begin
+ if (stp == NULL)
+ return
+
+ sym = stfind (stp, parameter)
+ if (sym == NULL) {
+ sym = stenter (stp, parameter, SYMLEN)
+ call strcpy (parameter, NAME(sym), SZ_NAME)
+ }
+
+ call strcpy (str, DEFAULT(sym), SZ_DEFAULT)
+end
+
+
+# HDMACCF -- Return whether the image header parameter exists (regardless of
+# whether there is a default value).
+
+int procedure hdmaccf (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+int imaccf()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ return (imaccf (im, NAME(sym)))
+ else
+ return (imaccf (im, parameter))
+end
+
+
+# HDMGSTR -- Get a string valued parameter. Return default value if not in
+# the image header. Return null string if no default or image value.
+
+procedure hdmgstr (im, parameter, str, max_char)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+char str[max_char] # String value to return
+int max_char # Maximum characters in returned string
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ iferr (call imgstr (im, NAME(sym), str, max_char))
+ call strcpy (DEFAULT(sym), str, max_char)
+ } else {
+ iferr (call imgstr (im, parameter, str, max_char))
+ str[1] = EOS
+ }
+end
+
+
+# HDMGETR -- Get a real valued parameter. Return default value if not in
+# the image header. Return error condition if no default or image value.
+
+real procedure hdmgetr (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+int ip, ctor()
+real value, imgetr()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ iferr (value = imgetr (im, NAME(sym))) {
+ ip = 1
+ if (ctor (DEFAULT(sym), ip, value) == 0)
+ call error (0, "HDMGETR: No value found")
+ }
+ } else
+ value = imgetr (im, parameter)
+
+ return (value)
+end
+
+
+# HDMGETI -- Get an integer valued parameter. Return default value if not in
+# the image header. Return error condition if no default or image value.
+
+int procedure hdmgeti (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+int ip, ctoi()
+int value, imgeti()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ iferr (value = imgeti (im, NAME(sym))) {
+ ip = 1
+ if (ctoi (DEFAULT(sym), ip, value) == 0)
+ call error (0, "HDMGETI: No value found")
+ }
+ } else
+ value = imgeti (im, parameter)
+
+ return (value)
+end
+
+
+# HDMPSTR -- Put a string valued parameter in the image header.
+
+procedure hdmpstr (im, parameter, str)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+char str[ARB] # String value
+
+int imaccf(), imgftype()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ if (imaccf (im, NAME(sym)) == YES)
+ if (imgftype (im, NAME(sym)) != TY_CHAR)
+ call imdelf (im, NAME(sym))
+ call imastr (im, NAME(sym), str)
+ } else {
+ if (imaccf (im, parameter) == YES)
+ if (imgftype (im, parameter) != TY_CHAR)
+ call imdelf (im, parameter)
+ call imastr (im, parameter, str)
+ }
+end
+
+
+# HDMPUTI -- Put an integer valued parameter in the image header.
+
+procedure hdmputi (im, parameter, value)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+int value # Integer value to put
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call imaddi (im, NAME(sym), value)
+ else
+ call imaddi (im, parameter, value)
+end
+
+
+# HDMPUTR -- Put a real valued parameter in the image header.
+
+procedure hdmputr (im, parameter, value)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+real value # Real value to put
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call imaddr (im, NAME(sym), value)
+ else
+ call imaddr (im, parameter, value)
+end
+
+
+# HDMGSTP -- Get the symbol table pointer to save a translation map.
+# The symbol table is restored with HDMPSTP.
+
+procedure hdmgstp (ptr)
+
+pointer ptr # Symbol table pointer to return
+
+include "hdrmap.com"
+
+begin
+ ptr = stp
+end
+
+
+# HDMPSTP -- Put a symbol table pointer to restore a header map.
+# The symbol table is optained with HDMGSTP.
+
+procedure hdmpstp (ptr)
+
+pointer ptr # Symbol table pointer to restore
+
+include "hdrmap.com"
+
+begin
+ stp = ptr
+end
+
+
+# HDMDELF -- Delete a field. It is an error if the field does not exist.
+
+procedure hdmdelf (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call imdelf (im, NAME(sym))
+ else
+ call imdelf (im, parameter)
+end
+
+
+# HDMPARAM -- Get parameter given the image header name.
+
+procedure hdmparam (name, parameter, max_char)
+
+char name[ARB] # Image header name
+char parameter[max_char] # Parameter
+int max_char # Maximum size of parameter string
+
+bool streq()
+pointer sym, sthead(), stname(), stnext()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = sthead (stp)
+ else
+ sym = NULL
+
+ while (sym != NULL) {
+ if (streq (NAME(sym), name)) {
+ call strcpy (Memc[stname(stp, sym)], parameter, max_char)
+ return
+ }
+ sym = stnext (stp, sym)
+ }
+ call strcpy (name, parameter, max_char)
+end
diff --git a/noao/imred/quadred/src/ccdproc/mkpkg b/noao/imred/quadred/src/ccdproc/mkpkg
new file mode 100644
index 00000000..7f263c15
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/mkpkg
@@ -0,0 +1,78 @@
+# Make QUADRED Package.
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $update libpkg.a
+ $call quadred
+ ;
+
+install:
+ $move xx_quadred.e noaobin$x_quadred.e
+ ;
+
+quadred:
+ $omake x_quadred.x
+ $link x_quadred.o libpkg.a -lxtools -lcurfit -lgsurfit -lncar -lgks\
+ -o xx_quadred.e
+ ;
+
+generic:
+ $set GEN = "$$generic -k"
+
+ $ifolder (generic/ccdred.h, ccdred.h)
+ $copy ccdred.h generic/ccdred.h $endif
+ $ifolder (generic/proc.x, proc.gx)
+ $(GEN) proc.gx -o generic/proc.x $endif
+ $ifolder (generic/cor.x, cor.gx)
+ $(GEN) cor.gx -o generic/cor.x $endif
+ $ifolder (generic/corinput.x, corinput.gx)
+ $(GEN) corinput.gx -o generic/corinput.x $endif
+ ;
+
+libpkg.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+ @generic
+
+ calimage.x ccdtypes.h <error.h> <imset.h>
+ ccdcache.x ccdcache.com ccdcache.h <imhdr.h> <imset.h> <mach.h>\
+ ccdcache.com
+ ccdcheck.x ccdtypes.h <imhdr.h>
+ ccdcmp.x
+ ccddelete.x
+ ccdflag.x
+ ccdlog.x <imhdr.h> <imset.h>
+ ccdmean.x <imhdr.h>
+ ccdnscan.x ccdtypes.h
+ ccdproc.x ccdred.h ccdtypes.h <error.h>
+ ccdsection.x <ctype.h>
+ ccdsubsets.x
+ ccdtypes.x ccdtypes.h
+ doproc.x ccdred.h
+ hdrmap.x hdrmap.com <error.h>
+ readcor.x <imhdr.h>
+ scancor.x <imhdr.h> <imset.h>
+ setdark.x ccdred.h ccdtypes.h <imhdr.h>
+ setfixpix.x ccdred.h <imhdr.h>
+ setflat.x ccdred.h ccdtypes.h <imhdr.h>
+ setfringe.x ccdred.h ccdtypes.h <imhdr.h>
+ setheader.x ccdred.h <imhdr.h>
+ setillum.x ccdred.h ccdtypes.h <imhdr.h>
+ setinput.x ccdtypes.h <error.h>
+ setinteract.x <pkg/xtanswer.h>
+ setoutput.x <imhdr.h> <imset.h>
+ setoverscan.x ccdred.h <imhdr.h> <imset.h> <pkg/xtanswer.h>\
+ <pkg/gtools.h>
+ setproc.x ccdred.h <imhdr.h>
+ setsections.x ccdred.h <imhdr.h>
+ settrim.x ccdred.h <imhdr.h> <imset.h>
+ setzero.x ccdred.h ccdtypes.h <imhdr.h>
+ t_ccdproc.x ccdred.h ccdtypes.h <error.h> <imhdr.h>
+ timelog.x <time.h>
+ ;
diff --git a/noao/imred/quadred/src/ccdproc/proc.gx b/noao/imred/quadred/src/ccdproc/proc.gx
new file mode 100644
index 00000000..b6604179
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/proc.gx
@@ -0,0 +1,379 @@
+include <imhdr.h>
+include "ccdred.h"
+
+
+.help proc Feb87 noao.imred.ccdred
+.nf ----------------------------------------------------------------------------
+proc -- Process CCD images
+
+These are the main CCD reduction procedures. There is one for each
+readout axis (lines or columns) and one for short and real image data.
+They apply corrections for bad pixels, overscan levels, zero levels,
+dark counts, flat field response, illumination response, and fringe
+effects. The image is also trimmed if it was mapped with an image
+section. The mean value for the output image is computed when the flat
+field or illumination image is processed to form the scale factor for
+these calibrations in order to avoid reading through these image a
+second time.
+
+The processing information and parameters are specified in the CCD
+structure. The processing operations to be performed are specified by
+the correction array CORS in the ccd structure. There is one array
+element for each operation with indices defined symbolically by macro
+definitions (see ccdred.h); i.e. FLATCOR. The value of the array
+element is an integer bit field in which the bit set is the same as the
+array index; i.e element 3 will have the third bit set for an operation
+with array value 2**(3-1)=4. If an operation is not to be performed
+the bit is not set and the array element has the numeric value zero.
+Note that the addition of several correction elements gives a unique
+bit field describing a combination of operations. For efficiency the
+most common combinations are implemented as separate units.
+
+The CCD structure also contains the correction or calibration data
+consisting either pointers to data, IMIO pointers for the calibration
+images, and scale factors.
+
+The processing is performed line-by-line. The procedure CORINPUT is
+called to get an input line. This procedure trims and fixes bad pixels by
+interpolation. The output line and lines from the various calibration
+images are read. The image vectors as well as the overscan vector and
+the scale factors are passed to the procedure COR (which also
+dereferences the pointer data into simple arrays and variables). That
+procedure does the actual corrections apart from bad pixel
+corrections.
+
+The final optional step is to add each corrected output line to form a
+mean. This adds efficiency since the operation is done only if desired
+and the output image data is already in memory so there is no I/O
+penalty.
+
+SEE ALSO
+ ccdred.h, cor, fixpix, setfixpix, setoverscan, settrim,
+ setzero, setdark, setflat, setillum, setfringe
+.endhelp ----------------------------------------------------------------------
+
+
+$for (sr)
+# PROC1 -- Process CCD images with readout axis 1 (lines).
+
+procedure proc1$t (ccd)
+
+pointer ccd # CCD structure
+
+int i, line, nlin, ncols, nlines, findmean, rep
+int c1, c2, l1, l2
+real overscan, darkscale, flatscale, illumscale, frgscale, mean
+PIXEL minrep
+pointer in, out, zeroim, darkim, flatim, illumim, fringeim
+pointer outbuf, overscan_vec, zerobuf, darkbuf, flatbuf, illumbuf, fringebuf
+
+$if (datatype == csir)
+real asum$t()
+$else $if (datatype == ld)
+double asum$t()
+$else
+PIXEL asum$t()
+$endif $endif
+pointer imgl2$t(), impl2$t(), ccd_gl$t()
+
+begin
+ # Initialize. If the correction image is 1D then just get the
+ # data once.
+
+ in = IN_IM(ccd)
+ out = OUT_IM(ccd)
+ nlin = IM_LEN(in,2)
+ ncols = OUT_C2(ccd) - OUT_C1(ccd) + 1
+ nlines = OUT_L2(ccd) - OUT_L1(ccd) + 1
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixinit$t (in)
+
+ findmean = CORS(ccd, FINDMEAN)
+ if (findmean == YES)
+ mean = 0.
+ rep = CORS(ccd, MINREP)
+ if (rep == YES)
+ minrep = MINREPLACE(ccd)
+
+ overscan_vec = OVERSCAN_VEC(ccd)
+
+ if (CORS(ccd, ZEROCOR) == 0) {
+ zeroim = NULL
+ zerobuf = 1
+ } else if (IM_LEN(ZERO_IM(ccd),2) == 1) {
+ zeroim = NULL
+ zerobuf = ccd_gl$t (ZERO_IM(ccd), ZERO_C1(ccd), ZERO_C2(ccd), 1)
+ } else
+ zeroim = ZERO_IM(ccd)
+
+ if (CORS(ccd, DARKCOR) == 0) {
+ darkim = NULL
+ darkbuf = 1
+ } else if (IM_LEN(DARK_IM(ccd),2) == 1) {
+ darkim = NULL
+ darkbuf = ccd_gl$t (DARK_IM(ccd), DARK_C1(ccd), DARK_C2(ccd), 1)
+ darkscale = FLATSCALE(ccd)
+ } else {
+ darkim = DARK_IM(ccd)
+ darkscale = DARKSCALE(ccd)
+ }
+
+ if (CORS(ccd, FLATCOR) == 0) {
+ flatim = NULL
+ flatbuf = 1
+ } else if (IM_LEN(FLAT_IM(ccd),2) == 1) {
+ flatim = NULL
+ flatbuf = ccd_gl$t (FLAT_IM(ccd), FLAT_C1(ccd), FLAT_C2(ccd), 1)
+ flatscale = FLATSCALE(ccd)
+ } else {
+ flatim = FLAT_IM(ccd)
+ flatscale = FLATSCALE(ccd)
+ }
+
+ if (CORS(ccd, ILLUMCOR) == 0) {
+ illumim = NULL
+ illumbuf = 1
+ } else {
+ illumim = ILLUM_IM(ccd)
+ illumscale = ILLUMSCALE(ccd)
+ }
+
+ if (CORS(ccd, FRINGECOR) == 0) {
+ fringeim = NULL
+ fringebuf = 1
+ } else {
+ fringeim = FRINGE_IM(ccd)
+ frgscale = FRINGESCALE(ccd)
+ }
+
+ # For each line read lines from the input. Procedure CORINPUT
+ # replaces bad pixels by interpolation and applies a trim to the
+ # input. Get lines from the output image and from the zero level,
+ # dark count, flat field, illumination, and fringe images.
+ # Call COR1 to do the actual pixel corrections. Finally, add the
+ # output pixels to a sum for computing the mean.
+ # We must copy data outside of the output data section.
+
+ do line = 2 - OUT_L1(ccd), 0
+ call amov$t (
+ Mem$t[imgl2$t(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mem$t[impl2$t(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ do line = 1, nlines {
+ outbuf = impl2$t (out, OUT_L1(ccd)+line-1)
+ call corinput$t (in, line, ccd, Mem$t[outbuf], IM_LEN(out,1))
+
+ outbuf = outbuf + OUT_C1(ccd) - 1
+ if (overscan_vec != NULL)
+ overscan = Memr[overscan_vec+line-1]
+ if (zeroim != NULL)
+ zerobuf = ccd_gl$t (zeroim, ZERO_C1(ccd), ZERO_C2(ccd),
+ ZERO_L1(ccd)+line-1)
+ if (darkim != NULL)
+ darkbuf = ccd_gl$t (darkim, DARK_C1(ccd), DARK_C2(ccd),
+ DARK_L1(ccd)+line-1)
+ if (flatim != NULL)
+ flatbuf = ccd_gl$t (flatim, FLAT_C1(ccd), FLAT_C2(ccd),
+ FLAT_L1(ccd)+line-1)
+ if (illumim != NULL)
+ illumbuf = ccd_gl$t (illumim, ILLUM_C1(ccd), ILLUM_C2(ccd),
+ ILLUM_L1(ccd)+line-1)
+ if (fringeim != NULL)
+ fringebuf = ccd_gl$t (fringeim, FRINGE_C1(ccd), FRINGE_C2(ccd),
+ FRINGE_L1(ccd)+line-1)
+
+ if (OUT_SEC(ccd) == NULL) {
+ call cor1$t (CORS(ccd,1), Mem$t[outbuf],
+ overscan, Mem$t[zerobuf], Mem$t[darkbuf],
+ Mem$t[flatbuf], Mem$t[illumbuf], Mem$t[fringebuf], ncols,
+ darkscale, flatscale, illumscale, frgscale)
+ } else {
+ do i = 1, IN_NSEC(ccd) {
+ l1 = OUT_SL1(ccd,i)
+ l2 = OUT_SL2(ccd,i)
+ if (line < l1 || line > l2)
+ next
+ c1 = OUT_SC1(ccd,i) - 1
+ c2 = OUT_SC2(ccd,i) - 1
+ ncols = c2 - c1 + 1
+ if (overscan_vec != NULL)
+ overscan = Memr[overscan_vec+(i-1)*nlin+line-l1]
+
+ call cor1$t (CORS(ccd,1), Mem$t[outbuf+c1],
+ overscan, Mem$t[zerobuf+c1], Mem$t[darkbuf+c1],
+ Mem$t[flatbuf+c1], Mem$t[illumbuf+c1],
+ Mem$t[fringebuf+c1], ncols,
+ darkscale, flatscale, illumscale, frgscale)
+ }
+ }
+
+ if (rep == YES)
+ call amaxk$t (Mem$t[outbuf], minrep, Mem$t[outbuf], ncols)
+ if (findmean == YES)
+ mean = mean + asum$t (Mem$t[outbuf], ncols)
+ }
+
+ do line = nlines+1, IM_LEN(out,2)-OUT_L1(ccd)+1
+ call amov$t (
+ Mem$t[imgl2$t(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mem$t[impl2$t(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ # Compute the mean from the sum of the output pixels.
+ if (findmean == YES)
+ MEAN(ccd) = mean / ncols / nlines
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixfree$t ()
+end
+
+
+# PROC2 -- Process CCD images with readout axis 2 (columns).
+
+procedure proc2$t (ccd)
+
+pointer ccd # CCD structure
+
+int line, ncols, nlines, findmean, rep
+real darkscale, flatscale, illumscale, frgscale, mean
+PIXEL minrep
+pointer in, out, zeroim, darkim, flatim, illumim, fringeim
+pointer outbuf, overscan_vec, zerobuf, darkbuf, flatbuf, illumbuf, fringebuf
+
+$if (datatype == csir)
+real asum$t()
+$else $if (datatype == ld)
+double asum$t()
+$else
+PIXEL asum$t()
+$endif $endif
+pointer imgl2$t(), impl2$t(), imgs2$t(), ccd_gl$t()
+
+begin
+ # Initialize. If the correction image is 1D then just get the
+ # data once.
+
+ in = IN_IM(ccd)
+ out = OUT_IM(ccd)
+ ncols = OUT_C2(ccd) - OUT_C1(ccd) + 1
+ nlines = OUT_L2(ccd) - OUT_L1(ccd) + 1
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixinit$t (in)
+
+ findmean = CORS(ccd, FINDMEAN)
+ if (findmean == YES)
+ mean = 0.
+ rep = CORS(ccd, MINREP)
+ if (rep == YES)
+ minrep = MINREPLACE(ccd)
+
+ overscan_vec = OVERSCAN_VEC(ccd)
+
+ if (CORS(ccd, ZEROCOR) == 0) {
+ zeroim = NULL
+ zerobuf = 1
+ } else if (IM_LEN(ZERO_IM(ccd),1) == 1) {
+ zeroim = NULL
+ zerobuf = imgs2$t (ZERO_IM(ccd), 1, 1, ZERO_L1(ccd), ZERO_L2(ccd))
+ } else
+ zeroim = ZERO_IM(ccd)
+
+ if (CORS(ccd, DARKCOR) == 0) {
+ darkim = NULL
+ darkbuf = 1
+ } else if (IM_LEN(DARK_IM(ccd),1) == 1) {
+ darkim = NULL
+ darkbuf = imgs2$t (DARK_IM(ccd), 1, 1, DARK_L1(ccd), DARK_L2(ccd))
+ darkscale = DARKSCALE(ccd)
+ } else {
+ darkim = DARK_IM(ccd)
+ darkscale = DARKSCALE(ccd)
+ }
+
+ if (CORS(ccd, FLATCOR) == 0) {
+ flatim = NULL
+ flatbuf = 1
+ } else if (IM_LEN(FLAT_IM(ccd),1) == 1) {
+ flatim = NULL
+ flatbuf = imgs2$t (FLAT_IM(ccd), 1, 1, FLAT_L1(ccd), FLAT_L2(ccd))
+ flatscale = FLATSCALE(ccd)
+ } else {
+ flatim = FLAT_IM(ccd)
+ flatscale = FLATSCALE(ccd)
+ }
+
+ if (CORS(ccd, ILLUMCOR) == 0) {
+ illumim = NULL
+ illumbuf = 1
+ } else {
+ illumim = ILLUM_IM(ccd)
+ illumscale = ILLUMSCALE(ccd)
+ }
+
+ if (CORS(ccd, FRINGECOR) == 0) {
+ fringeim = NULL
+ fringebuf = 1
+ } else {
+ fringeim = FRINGE_IM(ccd)
+ frgscale = FRINGESCALE(ccd)
+ }
+
+ # For each line read lines from the input. Procedure CORINPUT
+ # replaces bad pixels by interpolation and applies a trim to the
+ # input. Get lines from the output image and from the zero level,
+ # dark count, flat field, illumination, and fringe images.
+ # Call COR2 to do the actual pixel corrections. Finally, add the
+ # output pixels to a sum for computing the mean.
+ # We must copy data outside of the output data section.
+
+ do line = 2 - OUT_L1(ccd), 0
+ call amov$t (
+ Mem$t[imgl2$t(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mem$t[impl2$t(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ do line = 1, nlines {
+ outbuf = impl2$t (out, OUT_L1(ccd)+line-1)
+ call corinput$t (in, line, ccd, Mem$t[outbuf], IM_LEN(out,1))
+
+ outbuf = outbuf + OUT_C1(ccd) - 1
+ if (zeroim != NULL)
+ zerobuf = ccd_gl$t (zeroim, ZERO_C1(ccd), ZERO_C2(ccd),
+ ZERO_L1(ccd)+line-1)
+ if (darkim != NULL)
+ darkbuf = ccd_gl$t (darkim, DARK_C1(ccd), DARK_C2(ccd),
+ DARK_L1(ccd)+line-1)
+ if (flatim != NULL)
+ flatbuf = ccd_gl$t (flatim, FLAT_C1(ccd), FLAT_C2(ccd),
+ FLAT_L1(ccd)+line-1)
+ if (illumim != NULL)
+ illumbuf = ccd_gl$t (illumim, ILLUM_C1(ccd), ILLUM_C2(ccd),
+ ILLUM_L1(ccd)+line-1)
+ if (fringeim != NULL)
+ fringebuf = ccd_gl$t (fringeim, FRINGE_C1(ccd), FRINGE_C2(ccd),
+ FRINGE_L1(ccd)+line-1)
+
+ call cor2$t (line, CORS(ccd,1), Mem$t[outbuf],
+ Memr[overscan_vec], Mem$t[zerobuf], Mem$t[darkbuf],
+ Mem$t[flatbuf], Mem$t[illumbuf], Mem$t[fringebuf], ncols,
+ zeroim, flatim, darkscale, flatscale, illumscale, frgscale)
+
+ if (rep == YES)
+ call amaxk$t (Mem$t[outbuf], minrep, Mem$t[outbuf], ncols)
+ if (findmean == YES)
+ mean = mean + asum$t (Mem$t[outbuf], ncols)
+ }
+
+ do line = nlines+1, IM_LEN(out,2)-OUT_L1(ccd)+1
+ call amov$t (
+ Mem$t[imgl2$t(in,IN_L1(ccd)+line-1)+IN_C1(ccd)-OUT_C1(ccd)],
+ Mem$t[impl2$t(out,OUT_L1(ccd)+line-1)], IM_LEN(out,1))
+
+ # Compute the mean from the sum of the output pixels.
+ if (findmean == YES)
+ MEAN(ccd) = mean / ncols / nlines
+
+ if (CORS(ccd, FIXPIX) == YES)
+ call lfixfree$t ()
+end
+$endfor
diff --git a/noao/imred/quadred/src/ccdproc/readcor.x b/noao/imred/quadred/src/ccdproc/readcor.x
new file mode 100644
index 00000000..61fbd836
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/readcor.x
@@ -0,0 +1,138 @@
+include <imhdr.h>
+
+# READCOR -- Create a readout image.
+# Assume it is appropriate to perform this operation on the input image.
+# There is no CCD type checking.
+
+procedure readcor (input)
+
+char input[ARB] # Input image
+int readaxis # Readout axis
+
+int i, nc, nl, c1, c2, cs, l1, l2, ls
+int in_c1, in_c2, in_l1, in_l2, ccd_c1, ccd_c2, ccd_l1, ccd_l2
+pointer sp, output, str, in, out, data
+
+real asumr()
+int clgwrd()
+bool clgetb(), ccdflag()
+pointer immap(), imgl2r(), impl2r(), imps2r()
+errchk immap, ccddelete
+
+begin
+ # Check if this operation is desired.
+ if (!clgetb ("readcor"))
+ return
+
+ # Check if this operation has been done. Unfortunately this requires
+ # mapping the image.
+
+ in = immap (input, READ_ONLY, 0)
+ if (ccdflag (in, "readcor")) {
+ call imunmap (in)
+ return
+ }
+
+ if (clgetb ("noproc")) {
+ call eprintf (
+ " [TO BE DONE] Convert %s to readout correction\n")
+ call pargstr (input)
+ call imunmap (in)
+ return
+ }
+
+ call smark (sp)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # The default data section is the entire image.
+ nc = IM_LEN(in,1)
+ nl = IM_LEN(in,2)
+ c1 = 1
+ c2 = nc
+ cs = 1
+ l1 = 1
+ l2 = nl
+ ls = 1
+ call hdmgstr (in, "datasec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1))
+ call error (0, "Error in DATASEC parameter")
+ in_c1 = c1
+ in_c2 = c2
+ in_l1 = l1
+ in_l2 = l2
+
+ # The default ccd section is the data section.
+ call hdmgstr (in, "ccdsec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((cs != 1) || (ls != 1))
+ call error (0, "Error in CCDSEC parameter")
+ ccd_c1 = c1
+ ccd_c2 = c2
+ ccd_l1 = l1
+ ccd_l2 = l2
+ if ((in_c2-in_c1 != ccd_c2-ccd_c1) || (in_l2-in_l1 != ccd_l2-ccd_l1))
+ call error (0, "Size of DATASEC and CCDSEC do not agree")
+
+ # Determine the readout axis.
+ readaxis = clgwrd ("readaxis", Memc[str], SZ_LINE, "|lines|columns|")
+
+ # Create output.
+ call mktemp ("tmp", Memc[output], SZ_FNAME)
+ call set_output (in, out, Memc[output])
+
+ # Average across the readout axis.
+ switch (readaxis) {
+ case 1:
+ IM_LEN(out,2) = 1
+ data = impl2r (out, 1)
+ call aclrr (Memr[data], nc)
+ nc = in_c2 - in_c1 + 1
+ nl = in_l2 - in_l1 + 1
+ data = data + in_c1 - 1
+ do i = in_l1, in_l2
+ call aaddr (Memr[imgl2r(in,i)+in_c1-1], Memr[data],
+ Memr[data], nc)
+ call adivkr (Memr[data], real (nl), Memr[data], nc)
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,1:1]")
+ call pargi (in_c1)
+ call pargi (in_c2)
+ call hdmpstr (out, "datasec", Memc[str])
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,*]")
+ call pargi (ccd_c1)
+ call pargi (ccd_c2)
+ call hdmpstr (out, "ccdsec", Memc[str])
+ case 2:
+ IM_LEN(out,1) = 1
+ data = imps2r (out, 1, 1, 1, nl)
+ call aclrr (Memr[data], nl)
+ nc = in_c2 - in_c1 + 1
+ nl = in_l2 - in_l1 + 1
+ do i = in_l1, in_l2
+ Memr[data+i-1] = asumr (Memr[imgl2r(in,i)+in_c1-1], nc) / nc
+ call sprintf (Memc[str], SZ_LINE, "[1:1,%d:%d]")
+ call pargi (in_l1)
+ call pargi (in_l2)
+ call hdmpstr (out, "datasec", Memc[str])
+ call sprintf (Memc[str], SZ_LINE, "[*,%d:%d]")
+ call pargi (ccd_l1)
+ call pargi (ccd_l2)
+ call hdmpstr (out, "ccdsec", Memc[str])
+ }
+
+ # Log the operation.
+ call sprintf (Memc[str], SZ_LINE,
+ "Converted to readout format")
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (in, Memc[str])
+ call hdmpstr (out, "readcor", Memc[str])
+
+ # Replace the input image by the output image.
+ call imunmap (in)
+ call imunmap (out)
+ call ccddelete (input)
+ call imrename (Memc[output], input)
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/scancor.x b/noao/imred/quadred/src/ccdproc/scancor.x
new file mode 100644
index 00000000..6a5eb84c
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/scancor.x
@@ -0,0 +1,340 @@
+include <imhdr.h>
+include <imset.h>
+
+define SCANTYPES "|shortscan|longscan|"
+define SHORTSCAN 1 # Short scan accumulation, normal readout
+define LONGSCAN 2 # Long scan continuous readout
+
+# SCANCOR -- Create a scanned image from an unscanned image.
+
+procedure scancor (input, output, nscan, minreplace)
+
+char input[ARB] # Input image
+char output[ARB] # Output image (must be new image)
+int nscan # Number of scan lines
+real minreplace # Minmum value of output
+
+int scantype # Type of scan format
+int readaxis # Readout axis
+
+int clgwrd()
+pointer sp, str, in, out, immap()
+errchk immap
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Determine readout axis and create the temporary output image.
+ scantype = clgwrd ("scantype", Memc[str], SZ_LINE, SCANTYPES)
+ readaxis = clgwrd ("readaxis", Memc[str], SZ_LINE, "|lines|columns|")
+
+ # Make the output scanned image.
+ in = immap (input, READ_ONLY, 0)
+ call set_output (in, out, output)
+
+ switch (scantype) {
+ case SHORTSCAN:
+ call shortscan (in, out, nscan, minreplace, readaxis)
+ case LONGSCAN:
+ call longscan (in, out, readaxis)
+ }
+
+ # Log the operation.
+ switch (scantype) {
+ case SHORTSCAN:
+ call sprintf (Memc[str], SZ_LINE,
+ "Converted to shortscan from %s with nscan=%d")
+ call pargstr (input)
+ call pargi (nscan)
+ call hdmputi (out, "nscanrow", nscan)
+ case LONGSCAN:
+ call sprintf (Memc[str], SZ_LINE, "Converted to longscan from %s")
+ call pargstr (input)
+ }
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (out, Memc[str])
+ call hdmpstr (out, "scancor", Memc[str])
+
+ call imunmap (in)
+ call imunmap (out)
+
+ call sfree (sp)
+end
+
+
+# SHORTSCAN -- Make a shortscan mode image by using a moving average.
+#
+# NOTE!! The value of nscan used here is increased by 1 because the
+# current information in the image header is actually the number of
+# scan steps and NOT the number of rows.
+
+procedure shortscan (in, out, nscan, minreplace, readaxis)
+
+pointer in # Input image
+pointer out # Output image
+int nscan # Number of lines scanned before readout
+real minreplace # Minimum output value
+int readaxis # Readout axis
+
+bool replace
+real nscanr, sum, mean, asumr()
+int i, j, k, l, len1, len2, nc, nl, nscani, c1, c2, cs, l1, l2, ls
+pointer sp, str, bufs, datain, dataout, data, imgl2r(), impl2r()
+long clktime()
+errchk malloc, calloc
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # The default data section is the entire image.
+ len1 = IM_LEN(in,1)
+ len2 = IM_LEN(in,2)
+ c1 = 1
+ c2 = len1
+ cs = 1
+ l1 = 1
+ l2 = len2
+ ls = 1
+ call hdmgstr (in, "datasec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>len1)||(l1<1)||(l2>len2)||(cs!=1)||(ls!=1))
+ call error (0, "Error in DATASEC parameter")
+ nc = c2 - c1 + 1
+ nl = l2 - l1 + 1
+
+ # Copy initial lines.
+ do i = 1, l1 - 1
+ call amovr (Memr[imgl2r(in,i)], Memr[impl2r(out,i)], len1)
+
+ replace = !IS_INDEF(minreplace)
+ mean = 0.
+ switch (readaxis) {
+ case 1:
+ nscani = max (1, min (nscan, nl) + 1)
+ nscanr = nscani
+ call imseti (in, IM_NBUFS, nscani)
+ call malloc (bufs, nscani, TY_INT)
+ call calloc (data, nc, TY_REAL)
+ j = 1
+ k = 1
+ l = 1
+
+ # Ramp up
+ while (j <= nscani) {
+ i = j + l1 - 1
+ datain = imgl2r (in, i)
+ if (nc < len1)
+ call amovr (Memr[datain], Memr[impl2r(out,i)], len1)
+ datain = datain + c1 - 1
+ Memi[bufs+mod(j,nscani)] = datain
+ call aaddr (Memr[data], Memr[datain], Memr[data], nc)
+ j = j + 1
+ }
+ dataout = impl2r (out, l+l1-1) + c1 - 1
+ call adivkr (Memr[data], nscanr, Memr[dataout], nc)
+ if (replace)
+ call amaxkr (Memr[dataout], minreplace, Memr[dataout], nc)
+ mean = mean + asumr (Memr[dataout], nc)
+ l = l + 1
+
+ # Moving average
+ while (j <= nl) {
+ datain = Memi[bufs+mod(k,nscani)]
+ call asubr (Memr[data], Memr[datain], Memr[data], nc)
+ i = j + l1 - 1
+ datain = imgl2r (in, i)
+ if (nc < len1)
+ call amovr (Memr[datain], Memr[impl2r(out,i)], len1)
+ datain = datain + c1 - 1
+ Memi[bufs+mod(j,nscani)] = datain
+ call aaddr (Memr[data], Memr[datain], Memr[data], nc)
+ dataout = impl2r (out, l+l1-1) + c1 - 1
+ call adivkr (Memr[data], nscanr, Memr[dataout], nc)
+ if (replace)
+ call amaxkr (Memr[dataout], minreplace, Memr[dataout], nc)
+ mean = mean + asumr (Memr[dataout], nc)
+
+ j = j + 1
+ k = k + 1
+ l = l + 1
+ }
+
+ # Ramp down.
+ while (l <= nl) {
+ datain = Memi[bufs+mod(k,nscani)]
+ call asubr (Memr[data], Memr[datain], Memr[data], nc)
+ dataout = impl2r (out, l+l1-1) + c1 - 1
+ call adivkr (Memr[data], nscanr, Memr[dataout], nc)
+ if (replace)
+ call amaxkr (Memr[dataout], minreplace, Memr[dataout], nc)
+ mean = mean + asumr (Memr[dataout], nc)
+
+ k = k + 1
+ l = l + 1
+ }
+
+ call mfree (bufs, TY_INT)
+ call mfree (data, TY_REAL)
+
+ case 2:
+ nscani = max (1, min (nscan, nc) + 1)
+ nscanr = nscani
+ do i = 1, nl {
+ datain = imgl2r (in, i + l1 - 1)
+ datain = datain + c1 - 1
+ data = impl2r (out, i + l1 - 1)
+ call amovr (Memr[datain], Memr[data], len1)
+ datain = datain + c1 - 1
+ data = data + c1 - 1
+ sum = 0
+ j = 0
+ k = 0
+ l = 0
+
+ # Ramp up
+ while (j < nscani) {
+ sum = sum + Memr[datain+j]
+ j = j + 1
+ }
+ if (replace)
+ Memr[data] = max (minreplace, sum / nscani)
+ else
+ Memr[data] = sum / nscani
+ mean = mean + Memr[data]
+ l = l + 1
+
+ # Moving average
+ while (j < nl) {
+ sum = sum + Memr[datain+j] - Memr[datain+k]
+ if (replace)
+ Memr[data+l] = max (minreplace, sum / nscani)
+ else
+ Memr[data+l] = sum / nscani
+ mean = mean + Memr[data+l]
+ j = j + 1
+ k = k + 1
+ l = l + 1
+ }
+
+ # Ramp down
+ while (l < nl) {
+ sum = sum - Memr[datain+k]
+ if (replace)
+ Memr[data+l] = max (minreplace, sum / nscani)
+ else
+ Memr[data+l] = sum / nscani
+ mean = mean + Memr[data+l]
+ k = k + 1
+ l = l + 1
+ }
+ }
+ }
+
+ # Copy final lines.
+ do i = l2+1, len2
+ call amovr (Memr[imgl2r(in,i)], Memr[impl2r(out,i)], len1)
+
+ mean = mean / nc / nl
+ call hdmputr (out, "ccdmean", mean)
+ call hdmputi (out, "ccdmeant", int (clktime (long (0))))
+
+ call sfree (sp)
+end
+
+
+# LONGSCAN -- Make a longscan mode readout flat field correction by averaging
+# across the readout axis.
+
+procedure longscan (in, out, readaxis)
+
+pointer in # Input image
+pointer out # Output image
+int readaxis # Readout axis
+
+int i, nc, nl, c1, c2, cs, l1, l2, ls
+int in_c1, in_c2, in_l1, in_l2, ccd_c1, ccd_c2, ccd_l1, ccd_l2
+real mean, asumr()
+long clktime()
+pointer sp, str, data, imgl2r(), impl2r(), imps2r()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # The default data section is the entire image.
+ nc = IM_LEN(in,1)
+ nl = IM_LEN(in,2)
+ c1 = 1
+ c2 = nc
+ cs = 1
+ l1 = 1
+ l2 = nl
+ ls = 1
+ call hdmgstr (in, "datasec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1))
+ call error (0, "Error in DATASEC parameter")
+ in_c1 = c1
+ in_c2 = c2
+ in_l1 = l1
+ in_l2 = l2
+
+ # The default ccd section is the data section.
+ call hdmgstr (in, "ccdsec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((cs != 1) || (ls != 1))
+ call error (0, "Error in CCDSEC parameter")
+ ccd_c1 = c1
+ ccd_c2 = c2
+ ccd_l1 = l1
+ ccd_l2 = l2
+ if ((in_c2-in_c1 != ccd_c2-ccd_c1) || (in_l2-in_l1 != ccd_l2-ccd_l1))
+ call error (0, "Size of DATASEC and CCDSEC do not agree")
+
+ switch (readaxis) {
+ case 1:
+ IM_LEN(out,2) = 1
+ data = impl2r (out, 1)
+ call aclrr (Memr[data], nc)
+ nc = in_c2 - in_c1 + 1
+ nl = in_l2 - in_l1 + 1
+ data = data + in_c1 - 1
+ do i = in_l1, in_l2
+ call aaddr (Memr[imgl2r(in,i)+in_c1-1], Memr[data],
+ Memr[data], nc)
+ call adivkr (Memr[data], real (nl), Memr[data], nc)
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,1:1]")
+ call pargi (in_c1)
+ call pargi (in_c2)
+ call hdmpstr (out, "datasec", Memc[str])
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,*]")
+ call pargi (ccd_c1)
+ call pargi (ccd_c2)
+ call hdmpstr (out, "ccdsec", Memc[str])
+ mean = asumr (Memr[data], nc) / nl
+ case 2:
+ IM_LEN(out,1) = 1
+ data = imps2r (out, 1, 1, 1, nl)
+ call aclrr (Memr[data], nl)
+ nc = in_c2 - in_c1 + 1
+ nl = in_l2 - in_l1 + 1
+ do i = in_l1, in_l2
+ Memr[data+i-1] = asumr (Memr[imgl2r(in,i)+in_c1-1], nc) / nc
+ call sprintf (Memc[str], SZ_LINE, "[1:1,%d:%d]")
+ call pargi (in_l1)
+ call pargi (in_l2)
+ call hdmpstr (out, "datasec", Memc[str])
+ call sprintf (Memc[str], SZ_LINE, "[*,%d:%d]")
+ call pargi (ccd_l1)
+ call pargi (ccd_l2)
+ call hdmpstr (out, "ccdsec", Memc[str])
+ mean = asumr (Memr[data], nl) / nc
+ }
+
+ call hdmputr (out, "ccdmean", mean)
+ call hdmputi (out, "ccdmeant", int (clktime (long (0))))
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setdark.x b/noao/imred/quadred/src/ccdproc/setdark.x
new file mode 100644
index 00000000..bf3c7354
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setdark.x
@@ -0,0 +1,155 @@
+include <imhdr.h>
+include "ccdred.h"
+include "ccdtypes.h"
+
+
+# SET_DARK -- Set parameters for dark count correction.
+#
+# 1. Return immediately if the dark count correction is not requested or
+# if the image has been previously corrected.
+# 2. Get the dark count correction image and return an error if not found.
+# 3. If the dark count image has not been processed call PROC.
+# 4. Compute the dark count integration time scale factor.
+# 5. Set the processing flags.
+# 6. Log the operation (to user, logfile, and output image header).
+
+procedure set_dark (ccd)
+
+pointer ccd # CCD structure
+
+int nscan, nc, nl, c1, c2, cs, l1, l2, ls, data_c1, ccd_c1, data_l1, ccd_l1
+real darktime1, darktime2
+pointer sp, image, str, im
+
+bool clgetb(), ccdflag(), ccdcheck()
+int ccdnscan(), ccdtypei()
+real hdmgetr()
+pointer ccd_cache()
+errchk cal_image, ccd_cache, ccdproc, hdmgetr
+
+begin
+ # Check if the user wants this operation or it has already been done.
+ if (!clgetb ("darkcor") || ccdflag (IN_IM(ccd), "darkcor"))
+ return
+
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the dark count correction image name.
+ if (clgetb ("scancor"))
+ nscan = ccdnscan (IN_IM(ccd), ccdtypei(IN_IM(ccd)))
+ else
+ nscan = 1
+ call cal_image (IN_IM(ccd), DARK, nscan, Memc[image], SZ_FNAME)
+
+ # If no processing is desired print dark count image and return.
+ if (clgetb ("noproc")) {
+ call eprintf (" [TO BE DONE] Dark count correction image is %s.\n")
+ call pargstr (Memc[image])
+ call sfree (sp)
+ return
+ }
+
+ # Map the image and return on an error.
+ # Process the dark count image if necessary.
+ # If nscan > 1 then the dark may not yet exist so create it
+ # from the unscanned dark.
+
+ iferr (im = ccd_cache (Memc[image], DARK)) {
+ call cal_image (IN_IM(ccd), DARK, 1, Memc[str], SZ_LINE)
+ im = ccd_cache (Memc[str], DARK)
+ if (ccdcheck (im, DARK)) {
+ call ccd_flush (im)
+ call ccdproc (Memc[str], DARK)
+ }
+ call scancor (Memc[str], Memc[image], nscan, INDEF)
+ im = ccd_cache (Memc[image], DARK)
+ }
+
+ if (ccdcheck (im, DARK)) {
+ call ccd_flush (im)
+ call ccdproc (Memc[image], DARK)
+ im = ccd_cache (Memc[image], DARK)
+ }
+
+ # Set the processing parameters in the CCD structure.
+ nc = IM_LEN(im,1)
+ nl = IM_LEN(im,2)
+ c1 = 1
+ c2 = nc
+ l1 = 1
+ l2 = nl
+ cs = 1
+ ls = 1
+ call hdmgstr (im, "datasec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1)) {
+ call sprintf (Memc[str], SZ_LINE,
+ "Data section error: image=%s[%d,%d], datasec=[%d:%d,%d:%d]")
+ call pargstr (Memc[image])
+ call pargi (nc)
+ call pargi (nl)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+ data_c1 = c1
+ data_l1 = l1
+ call hdmgstr (im, "ccdsec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if (nc == 1) {
+ c1 = CCD_C1(ccd)
+ c2 = CCD_C2(ccd)
+ }
+ if (nl == 1) {
+ l1 = CCD_L1(ccd)
+ l2 = CCD_L2(ccd)
+ }
+ ccd_c1 = c1
+ ccd_l1 = l1
+ if ((c1 > CCD_C1(ccd)) || (c2 < CCD_C2(ccd)) ||
+ (l1 > CCD_L1(ccd)) || (l2 < CCD_L2(ccd))) {
+ call sprintf (Memc[str], SZ_LINE,
+ "CCD section error: input=[%d:%d,%d:%d], %s=[%d:%d,%d:%d]")
+ call pargi (CCD_C1(ccd))
+ call pargi (CCD_C2(ccd))
+ call pargi (CCD_L1(ccd))
+ call pargi (CCD_L2(ccd))
+ call pargstr (Memc[image])
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+
+ DARK_IM(ccd) = im
+ DARK_C1(ccd) = CCD_C1(ccd) - ccd_c1 + data_c1
+ DARK_C2(ccd) = CCD_C2(ccd) - ccd_c1 + data_c1
+ DARK_L1(ccd) = CCD_L1(ccd) - ccd_l1 + data_l1
+ DARK_L2(ccd) = CCD_L2(ccd) - ccd_l1 + data_l1
+
+ # Get the dark count integration times. Return an error if not found.
+ iferr (darktime1 = hdmgetr (IN_IM(ccd), "darktime"))
+ darktime1 = hdmgetr (IN_IM(ccd), "exptime")
+ iferr (darktime2 = hdmgetr (im, "darktime"))
+ darktime2 = hdmgetr (im, "exptime")
+
+ DARKSCALE(ccd) = darktime1 / darktime2
+ CORS(ccd, DARKCOR) = D
+ COR(ccd) = YES
+
+ # Record the operation in the output image and write a log record.
+ call sprintf (Memc[str], SZ_LINE,
+ "Dark count correction image is %s with scale=%g")
+ call pargstr (Memc[image])
+ call pargr (DARKSCALE(ccd))
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "darkcor", Memc[str])
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setfixpix.x b/noao/imred/quadred/src/ccdproc/setfixpix.x
new file mode 100644
index 00000000..05866bed
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setfixpix.x
@@ -0,0 +1,181 @@
+include <imhdr.h>
+include "ccdred.h"
+
+# SET_FIXPIX -- Setup for fixing bad pixels.
+#
+# 1. Return immediately if the bad pixel correction is not requested or
+# if the image has been previously corrected.
+# 2. Determine the bad pixel correction file. This may be specified
+# directly or indirectly through the image header or symbol table.
+# Return warning if not found.
+# 3. Read through the file collecting the bad pixel regions into a
+# bad column array (regions to be interpolated across columns) and
+# a bad line array (regions to be interpolated across lines).
+# 4. Set the processing flag.
+# 5. Log the operation (to user, logfile, and output image header).
+
+procedure set_fixpix (ccd)
+
+pointer ccd # CCD structure
+
+int fd, nc, nl, c1, c2, l1, l2, dc, dl, nbadcols, nbadlines
+pointer sp, image, str, badcols, badlines
+
+int open(), fscan(), nscan(), strmatch()
+bool clgetb(), streq(), ccdflag()
+errchk open
+
+begin
+ # Check if the user wants this operation or it has been done.
+ if (!clgetb ("fixpix") || ccdflag (IN_IM(ccd), "fixpix"))
+ return
+
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the bad pixel file. If the name is "image" then get the file
+ # name from the image header or symbol table.
+
+ call clgstr ("fixfile", Memc[image], SZ_FNAME)
+ if (streq (Memc[image], "image"))
+ call hdmgstr (IN_IM(ccd), "fixfile", Memc[image], SZ_FNAME)
+
+ # If no processing is desired print message and return.
+ if (clgetb ("noproc")) {
+ call eprintf (" [TO BE DONE] Bad pixel file is %s\n")
+ call pargstr (Memc[image])
+ call sfree (sp)
+ return
+ }
+
+ # Open the file and read the bad pixel regions. Use dynamic memory.
+ # Set the bad pixel coordinates. By default the bad pixel coordinates
+ # refer to the image directly but if the word "untrimmed" appears
+ # in a comment then the coordinates refer to the CCD coordinates.
+
+ fd = open (Memc[image], READ_ONLY, TEXT_FILE)
+ dc = 0
+ dl = 0
+ nc = IM_LEN(IN_IM(ccd),1)
+ nl = IM_LEN(IN_IM(ccd),2)
+ nbadcols = 0
+ nbadlines = 0
+ while (fscan (fd) != EOF) {
+ call gargwrd (Memc[str], SZ_LINE)
+ if (Memc[str] == '#') {
+ call gargstr (Memc[str], SZ_LINE)
+ if (strmatch (Memc[str], "{untrimmed}") != 0) {
+ dc = IN_C1(ccd) - CCD_C1(ccd)
+ dl = IN_L1(ccd) - CCD_L1(ccd)
+ }
+ next
+ }
+
+ call reset_scan()
+ call gargi (c1)
+ call gargi (c2)
+ call gargi (l1)
+ call gargi (l2)
+
+ # Ignore badly specified lines.
+ if (nscan() != 4) {
+ if (nscan() == 2) {
+ l1 = c2
+ c2 = c1
+ l2 = l1
+ } else
+ next
+ }
+
+ # Do the coordinate conversion.
+ c1 = max (IN_C1(ccd), c1 + dc)
+ c2 = min (IN_C2(ccd), c2 + dc)
+ l1 = max (IN_L1(ccd), l1 + dl)
+ l2 = min (IN_L2(ccd), l2 + dl)
+
+ # Ignore an inproperly specified region.
+ if ((c1 > c2) || (l1 > l2))
+ next
+
+ # Interpolate across the shortest direction.
+ if ((l2 - l1) < (c2 - c1)) {
+ nbadlines = nbadlines + 1
+ if (nbadlines == 1)
+ call calloc (badlines, 2*nl*nbadlines, TY_SHORT)
+ else {
+ call realloc (badlines, 2*nl*nbadlines, TY_SHORT)
+ call aclrs (Mems[badlines+2*nl*(nbadlines-1)], 2*nl)
+ }
+ call set_badcols (c1, c2, l1, l2, Mems[badlines],
+ nl, nbadlines)
+
+ } else {
+ nbadcols = nbadcols + 1
+ if (nbadcols == 1)
+ call calloc (badcols, 2*nl*nbadcols, TY_SHORT)
+ else {
+ call realloc (badcols, 2*nl*nbadcols, TY_SHORT)
+ call aclrs (Mems[badcols+2*nl*(nbadcols-1)], 2*nl)
+ }
+ call set_badcols (c1, c2, l1, l2, Mems[badcols],
+ nl, nbadcols)
+ }
+ }
+ call close (fd)
+
+ # Set structure parameters and the correction flags.
+ if (nbadcols != 0) {
+ NBADCOLS(ccd) = nbadcols
+ BADCOLS(ccd) = badcols
+ CORS(ccd, FIXPIX) = YES
+ COR(ccd) = YES
+ }
+ if (nbadlines != 0) {
+ NBADLINES(ccd) = nbadlines
+ BADLINES(ccd) = badlines
+ CORS(ccd, FIXPIX) = YES
+ COR(ccd) = YES
+ }
+
+ # Log the operation.
+ call sprintf (Memc[str], SZ_LINE, "Bad pixel file is %s")
+ call pargstr (Memc[image])
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "fixpix", Memc[str])
+
+ call sfree (sp)
+end
+
+
+# SET_BADCOLS -- Enter bad columns in a bad column array.
+# This procedure is used both for the line and column interpolation arrays.
+# The bad column array contains the starting and ending bad columns for
+# each line. This allows quick look up when processing the image at the
+# expense of memory. A column index of zero indicates no further bad columns
+# in the line.
+
+procedure set_badcols (c1, c2, l1, l2, array, nl, nbadcols)
+
+int c1, c2, l1, l2 # Bad column
+short array[2,nl,nbadcols] # Bad column array
+int nl # Number of image lines
+int nbadcols # Number of bad column areas
+
+int i, j
+
+begin
+ # For each line in the bad columns set the columns
+ # in the first unused entry in the array.
+
+ do i = l1, l2 {
+ do j = 1, nbadcols {
+ if (array[1,i,j] == 0) {
+ array[1,i,j] = c1
+ array[2,i,j] = c2
+ break
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/ccdproc/setflat.x b/noao/imred/quadred/src/ccdproc/setflat.x
new file mode 100644
index 00000000..87713404
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setflat.x
@@ -0,0 +1,146 @@
+include <imhdr.h>
+include "ccdred.h"
+include "ccdtypes.h"
+
+# SET_FLAT -- Set parameters for flat field correction.
+#
+# 1. Return immediately if the flat field correction is not requested or
+# if the image has been previously corrected.
+# 2. Get the flat field image and return on an error.
+# 3. If the flat field image has not been processed call PROC.
+# 4. Set the processing flags and record the operation in the output
+# image and write a log record.
+
+procedure set_flat (ccd)
+
+pointer ccd # CCD structure
+
+int nc, nl, c1, c2, cs, l1, l2, ls, data_c1, ccd_c1, data_l1, ccd_l1
+pointer sp, str, image, im, ccd_cache()
+bool clgetb(), ccdflag(), ccdcheck()
+int nscan, ccdnscan(), ccdtypei()
+real hdmgetr()
+errchk cal_image, ccd_cache, ccdproc, hdmgetr
+
+begin
+ # Check if the user wants this operation or if it has been done.
+ if (!clgetb ("flatcor") || ccdflag (IN_IM(ccd), "flatcor"))
+ return
+
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the flat field correction image.
+ if (clgetb ("scancor"))
+ nscan = ccdnscan (IN_IM(ccd), ccdtypei(IN_IM(ccd)))
+ else
+ nscan = 1
+ call cal_image (IN_IM(ccd), FLAT, nscan, Memc[image], SZ_FNAME)
+
+ # If no processing is desired print flat field image name and return.
+ if (clgetb ("noproc")) {
+ call eprintf (" [TO BE DONE] Flat correction image is %s.\n")
+ call pargstr (Memc[image])
+ call sfree (sp)
+ return
+ }
+
+ # Map the image and return on an error.
+ # Process the flat field image if necessary.
+ # If nscan > 1 then the flat field may not yet exist so create it
+ # from the unscanned flat field.
+
+ iferr (im = ccd_cache (Memc[image], FLAT)) {
+ call cal_image (IN_IM(ccd), FLAT, 1, Memc[str], SZ_LINE)
+ im = ccd_cache (Memc[str], FLAT)
+ if (ccdcheck (im, FLAT)) {
+ call ccd_flush (im)
+ call ccdproc (Memc[str], FLAT)
+ }
+ call scancor (Memc[str], Memc[image], nscan, MINREPLACE(ccd))
+ im = ccd_cache (Memc[image], FLAT)
+ }
+
+ if (ccdcheck (im, FLAT)) {
+ call ccd_flush (im)
+ call ccdproc (Memc[image], FLAT)
+ im = ccd_cache (Memc[image], FLAT)
+ }
+
+ # Set the processing parameters in the CCD structure.
+ nc = IM_LEN(im,1)
+ nl = IM_LEN(im,2)
+ c1 = 1
+ c2 = nc
+ l1 = 1
+ l2 = nl
+ cs = 1
+ ls = 1
+ call hdmgstr (im, "datasec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1)) {
+ call sprintf (Memc[str], SZ_LINE,
+ "Data section error: image=%s[%d,%d], datasec=[%d:%d,%d:%d]")
+ call pargstr (Memc[image])
+ call pargi (nc)
+ call pargi (nl)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+ data_c1 = c1
+ data_l1 = l1
+ call hdmgstr (im, "ccdsec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if (nc == 1) {
+ c1 = CCD_C1(ccd)
+ c2 = CCD_C2(ccd)
+ }
+ if (nl == 1) {
+ l1 = CCD_L1(ccd)
+ l2 = CCD_L2(ccd)
+ }
+ ccd_c1 = c1
+ ccd_l1 = l1
+ if ((c1 > CCD_C1(ccd)) || (c2 < CCD_C2(ccd)) ||
+ (l1 > CCD_L1(ccd)) || (l2 < CCD_L2(ccd))) {
+ call sprintf (Memc[str], SZ_LINE,
+ "CCD section error: input=[%d:%d,%d:%d], %s=[%d:%d,%d:%d]")
+ call pargi (CCD_C1(ccd))
+ call pargi (CCD_C2(ccd))
+ call pargi (CCD_L1(ccd))
+ call pargi (CCD_L2(ccd))
+ call pargstr (Memc[image])
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+
+ FLAT_IM(ccd) = im
+ FLAT_C1(ccd) = CCD_C1(ccd) - ccd_c1 + data_c1
+ FLAT_C2(ccd) = CCD_C2(ccd) - ccd_c1 + data_c1
+ FLAT_L1(ccd) = CCD_L1(ccd) - ccd_l1 + data_l1
+ FLAT_L2(ccd) = CCD_L2(ccd) - ccd_l1 + data_l1
+
+ # If no mean value use 1 as the scale factor.
+ iferr (FLATSCALE(ccd) = hdmgetr (im, "ccdmean"))
+ FLATSCALE(ccd) = 1.
+ CORS(ccd, FLATCOR) = F
+ COR(ccd) = YES
+
+ # Log the operation.
+ call sprintf (Memc[str], SZ_LINE,
+ "Flat field image is %s with scale=%g")
+ call pargstr (Memc[image])
+ call pargr (FLATSCALE(ccd))
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "flatcor", Memc[str])
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setfringe.x b/noao/imred/quadred/src/ccdproc/setfringe.x
new file mode 100644
index 00000000..7055f35f
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setfringe.x
@@ -0,0 +1,123 @@
+include <imhdr.h>
+include "ccdred.h"
+include "ccdtypes.h"
+
+# SET_FRINGE -- Set parameters for fringe correction.
+#
+# 1. Return immediately if the fringe correction is not requested or
+# if the image has been previously corrected.
+# 2. Get the fringe image and return error if the mkfringe flag is missing.
+# 3. Set the processing flags and record the operation in the output
+# image and write a log record.
+
+procedure set_fringe (ccd)
+
+pointer ccd # CCD structure
+
+int nc, nl, c1, c2, cs, l1, l2, ls, data_c1, ccd_c1, data_l1, ccd_l1
+real exptime1, exptime2, fringescale
+pointer sp, str, image, im
+
+bool clgetb(), ccdflag()
+real hdmgetr()
+pointer ccd_cache()
+errchk cal_image, ccd_cache, ccdproc, hdmgetr
+
+begin
+ # Check if the user wants this operation or if it has been done.
+ if (!clgetb ("fringecor") || ccdflag (IN_IM(ccd), "fringcor"))
+ return
+
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the fringe correction image.
+ call cal_image (IN_IM(ccd), FRINGE, 1, Memc[image], SZ_FNAME)
+
+ # If no processing is desired print fringe image name and return.
+ if (clgetb ("noproc")) {
+ call eprintf (
+ " [TO BE DONE] Fringe correction image is %s.\n")
+ call pargstr (Memc[image])
+ call sfree (sp)
+ return
+ }
+
+ # Return an error if the fringe flag is missing.
+ im = ccd_cache (Memc[image], FRINGE)
+ if (!ccdflag (im, "mkfringe"))
+ call error (0, "MKFRINGE flag missing from fringe image.")
+
+ # Set the processing parameters in the CCD structure.
+ nc = IM_LEN(im,1)
+ nl = IM_LEN(im,2)
+ c1 = 1
+ c2 = nc
+ l1 = 1
+ l2 = nl
+ cs = 1
+ ls = 1
+ call hdmgstr (im, "datasec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1)) {
+ call sprintf (Memc[str], SZ_LINE,
+ "Data section error: image=%s[%d,%d], datasec=[%d:%d,%d:%d]")
+ call pargstr (Memc[image])
+ call pargi (nc)
+ call pargi (nl)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+ data_c1 = c1
+ data_l1 = l1
+ call hdmgstr (im, "ccdsec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ ccd_c1 = c1
+ ccd_l1 = l1
+ if ((c1 > CCD_C1(ccd)) || (c2 < CCD_C2(ccd)) ||
+ (l1 > CCD_L1(ccd)) || (l2 < CCD_L2(ccd))) {
+ call sprintf (Memc[str], SZ_LINE,
+ "CCD section error: input=[%d:%d,%d:%d], %s=[%d:%d,%d:%d]")
+ call pargi (CCD_C1(ccd))
+ call pargi (CCD_C2(ccd))
+ call pargi (CCD_L1(ccd))
+ call pargi (CCD_L2(ccd))
+ call pargstr (Memc[image])
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+
+ FRINGE_IM(ccd) = im
+ FRINGE_C1(ccd) = CCD_C1(ccd) - ccd_c1 + data_c1
+ FRINGE_C2(ccd) = CCD_C2(ccd) - ccd_c1 + data_c1
+ FRINGE_L1(ccd) = CCD_L1(ccd) - ccd_l1 + data_l1
+ FRINGE_L2(ccd) = CCD_L2(ccd) - ccd_l1 + data_l1
+
+ # Get the scaling factors. If no fringe scale factor assume 1.
+ exptime1 = hdmgetr (IN_IM(ccd), "exptime")
+ exptime2 = hdmgetr (im, "exptime")
+ iferr (fringescale = hdmgetr (im, "fringscl"))
+ fringescale = 1.
+
+ FRINGESCALE(ccd) = exptime1 / exptime2 * fringescale
+ CORS(ccd, FRINGECOR) = Q
+ COR(ccd) = YES
+
+ # Log the operation.
+ call sprintf (Memc[str], SZ_LINE,
+ "Fringe image is %s with scale=%g")
+ call pargstr (Memc[image])
+ call pargr (FRINGESCALE(ccd))
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "fringcor", Memc[str])
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setheader.x b/noao/imred/quadred/src/ccdproc/setheader.x
new file mode 100644
index 00000000..5687612d
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setheader.x
@@ -0,0 +1,76 @@
+include <imhdr.h>
+include "ccdred.h"
+
+# SET_HEADER -- Set the output image header.
+
+procedure set_header (ccd)
+
+pointer ccd # CCD structure
+
+int nc, nl
+pointer sp, str, out
+long clktime()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ out = OUT_IM(ccd)
+ nc = IM_LEN(out,1)
+ nl = IM_LEN(out,2)
+
+ # Set the data section if it is not the whole image.
+ if ((OUT_C1(ccd) != 1) || (OUT_C2(ccd) != nc) ||
+ (OUT_L1(ccd) != 1) || (OUT_L2(ccd) != nl)) {
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (OUT_C1(ccd))
+ call pargi (OUT_C2(ccd))
+ call pargi (OUT_L1(ccd))
+ call pargi (OUT_L2(ccd))
+ call hdmpstr (out, "datasec", Memc[str])
+ } else {
+ iferr (call hdmdelf (out, "datasec"))
+ ;
+ }
+
+ # Set the CCD section.
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (CCD_C1(ccd))
+ call pargi (CCD_C2(ccd))
+ call pargi (CCD_L1(ccd))
+ call pargi (CCD_L2(ccd))
+ call hdmpstr (out, "ccdsec", Memc[str])
+
+ # If trimming update the trim and bias section parameters.
+ if (CORS(ccd, TRIM) == YES) {
+ iferr (call hdmdelf (out, "trimsec"))
+ ;
+ iferr (call hdmdelf (out, "biassec"))
+ ;
+ BIAS_C1(ccd) = max (1, BIAS_C1(ccd) - TRIM_C1(ccd) + 1)
+ BIAS_C2(ccd) = min (nc, BIAS_C2(ccd) - TRIM_C1(ccd) + 1)
+ BIAS_L1(ccd) = max (1, BIAS_L1(ccd) - TRIM_L1(ccd) + 1)
+ BIAS_L2(ccd) = min (nl, BIAS_L2(ccd) - TRIM_L1(ccd) + 1)
+ if ((BIAS_C1(ccd)<=BIAS_C2(ccd)) && (BIAS_L1(ccd)<=BIAS_L2(ccd))) {
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (BIAS_C1(ccd))
+ call pargi (BIAS_C2(ccd))
+ call pargi (BIAS_L1(ccd))
+ call pargi (BIAS_L2(ccd))
+ call hdmpstr (out, "biassec", Memc[str])
+ }
+ }
+
+ # Set mean value if desired.
+ if (CORS(ccd, FINDMEAN) == YES) {
+ call hdmputr (out, "ccdmean", MEAN(ccd))
+ call hdmputi (out, "ccdmeant", int (clktime (long (0))))
+ }
+
+ # Mark image as processed.
+ call sprintf (Memc[str], SZ_LINE, "CCD processing done")
+ call timelog (Memc[str], SZ_LINE)
+ call hdmpstr (out, "ccdproc", Memc[str])
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setillum.x b/noao/imred/quadred/src/ccdproc/setillum.x
new file mode 100644
index 00000000..d1677301
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setillum.x
@@ -0,0 +1,132 @@
+include <imhdr.h>
+include "ccdred.h"
+include "ccdtypes.h"
+
+# SET_ILLUM -- Set parameters for illumination correction.
+#
+# 1. Return immediately if the illumination correction is not requested or
+# if the image has been previously corrected.
+# 2. Get the illumination image and return error if mkillum flag missing.
+# 3. Set the processing flags and record the operation in the output
+# image and write a log record.
+
+procedure set_illum (ccd)
+
+pointer ccd # CCD structure
+
+int nc, nl, c1, c2, cs, l1, l2, ls, data_c1, ccd_c1, data_l1, ccd_l1
+long time
+pointer sp, str, image, im
+
+bool clgetb(), ccdflag()
+long hdmgeti()
+real hdmgetr()
+pointer ccd_cache()
+errchk cal_image, ccd_cache, ccdproc, hdmgetr, hdmgeti
+
+begin
+ # Check if the user wants this operation or if it has been done.
+ if (!clgetb ("illumcor") || ccdflag (IN_IM(ccd), "illumcor"))
+ return
+
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the illumcor correction image.
+ call cal_image (IN_IM(ccd), ILLUM, 1, Memc[image], SZ_FNAME)
+
+ # If no processing is desired print illumination image name and return.
+ if (clgetb ("noproc")) {
+ call eprintf (
+ " [TO BE DONE] Illumination correction image is %s.\n")
+ call pargstr (Memc[image])
+ call sfree (sp)
+ return
+ }
+
+ # Return a warning if the illumination flag is missing.
+ im = ccd_cache (Memc[image], ILLUM)
+ if (!ccdflag (im, "mkillum")) {
+ call ccd_flush (im)
+ call error (0, "MKILLUM flag missing from illumination image")
+ }
+
+ # If no mean value for the scale factor compute it.
+ iferr (ILLUMSCALE(ccd) = hdmgetr (im, "ccdmean"))
+ ILLUMSCALE(ccd) = INDEF
+ iferr (time = hdmgeti (im, "ccdmeant"))
+ time = IM_MTIME(im)
+ if (IS_INDEF(ILLUMSCALE(ccd)) || time < IM_MTIME(im)) {
+ call ccd_flush (im)
+ call ccdmean (Memc[image])
+ im = ccd_cache (Memc[image], ILLUM)
+ }
+ iferr (ILLUMSCALE(ccd) = hdmgetr (im, "ccdmean"))
+ ILLUMSCALE(ccd) = 1.
+
+ # Set the processing parameters in the CCD structure.
+ nc = IM_LEN(im,1)
+ nl = IM_LEN(im,2)
+ c1 = 1
+ c2 = nc
+ l1 = 1
+ l2 = nl
+ cs = 1
+ ls = 1
+ call hdmgstr (im, "datasec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1)) {
+ call sprintf (Memc[str], SZ_LINE,
+ "Data section error: image=%s[%d,%d], datasec=[%d:%d,%d:%d]")
+ call pargstr (Memc[image])
+ call pargi (nc)
+ call pargi (nl)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+ data_c1 = c1
+ data_l1 = l1
+ call hdmgstr (im, "ccdsec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ ccd_c1 = c1
+ ccd_l1 = l1
+ if ((c1 > CCD_C1(ccd)) || (c2 < CCD_C2(ccd)) ||
+ (l1 > CCD_L1(ccd)) || (l2 < CCD_L2(ccd))) {
+ call sprintf (Memc[str], SZ_LINE,
+ "CCD section error: input=[%d:%d,%d:%d], %s=[%d:%d,%d:%d]")
+ call pargi (CCD_C1(ccd))
+ call pargi (CCD_C2(ccd))
+ call pargi (CCD_L1(ccd))
+ call pargi (CCD_L2(ccd))
+ call pargstr (Memc[image])
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+
+ ILLUM_IM(ccd) = im
+ ILLUM_C1(ccd) = CCD_C1(ccd) - ccd_c1 + data_c1
+ ILLUM_C2(ccd) = CCD_C2(ccd) - ccd_c1 + data_c1
+ ILLUM_L1(ccd) = CCD_L1(ccd) - ccd_l1 + data_l1
+ ILLUM_L2(ccd) = CCD_L2(ccd) - ccd_l1 + data_l1
+
+ CORS(ccd, ILLUMCOR) = I
+ COR(ccd) = YES
+
+ # Log the operation.
+ call sprintf (Memc[str], SZ_LINE,
+ "Illumination image is %s with scale=%g")
+ call pargstr (Memc[image])
+ call pargr (ILLUMSCALE(ccd))
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "illumcor", Memc[str])
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setinput.x b/noao/imred/quadred/src/ccdproc/setinput.x
new file mode 100644
index 00000000..3d3170db
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setinput.x
@@ -0,0 +1,48 @@
+include <error.h>
+include "ccdtypes.h"
+
+# SET_INPUT -- Set the input image and image type.
+#
+# 1. Open the input image. Return warning and NULL pointer for an error.
+# 2. Get the requested CCD image type.
+# a. If no type is requested then accept the image.
+# b. If a type is requested then match against the image type.
+# Unmap the image if no match.
+# 3. If the image is acceptable then get the CCD type code.
+
+procedure set_input (image, im, ccdtype)
+
+char image[ARB] # Input image name
+pointer im # IMIO pointer (returned)
+int ccdtype # CCD image type
+
+bool strne()
+int ccdtypei()
+pointer sp, str1, str2, immap()
+
+begin
+ # Open the image. Return a warning and NULL pointer for an error.
+ iferr (im = immap (image, READ_ONLY, 0)) {
+ call erract (EA_WARN)
+ im = NULL
+ return
+ }
+
+ call smark (sp)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+
+ # Get the requested CCD type.
+ call clgstr ("ccdtype", Memc[str1], SZ_LINE)
+ call xt_stripwhite (Memc[str1])
+ if (Memc[str1] != EOS) {
+ call ccdtypes (im, Memc[str2], SZ_LINE)
+ if (strne (Memc[str1], Memc[str2]))
+ call imunmap (im)
+ }
+
+ if (im != NULL)
+ ccdtype = ccdtypei (im)
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setinteract.x b/noao/imred/quadred/src/ccdproc/setinteract.x
new file mode 100644
index 00000000..05bc0f71
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setinteract.x
@@ -0,0 +1,31 @@
+include <pkg/xtanswer.h>
+
+# SET_INTERACTIVE -- Set the interactive flag. Query the user if necessary.
+#
+# This procedure initializes the interactive flag if there is no query.
+# If there is a query it is issued by XT_ANSWER. The four valued
+# interactive flag is returned.
+
+procedure set_interactive (query, interactive)
+
+char query[ARB] # Query prompt
+int interactive # Fit overscan interactively? (returned)
+
+int interact # Saves last value of interactive flag
+bool clgetb()
+
+begin
+ # If the query is null then initialize from the CL otherwise
+ # query the user. This response is four valued to allow the user
+ # to turn off the query when processing multiple images.
+
+ if (query[1] == EOS) {
+ if (clgetb ("interactive"))
+ interact = YES
+ else
+ interact = ALWAYSNO
+ } else
+ call xt_answer (query, interact)
+
+ interactive = interact
+end
diff --git a/noao/imred/quadred/src/ccdproc/setoutput.x b/noao/imred/quadred/src/ccdproc/setoutput.x
new file mode 100644
index 00000000..0c4e608f
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setoutput.x
@@ -0,0 +1,51 @@
+include <imhdr.h>
+include <imset.h>
+
+# SET_OUTPUT -- Setup the output image.
+# The output image is a NEW_COPY of the input image.
+# The user may select a pixel datatype with higher precision though not
+# lower.
+
+procedure set_output (in, out, output)
+
+pointer in # Input IMIO pointer to copy
+pointer out # Output IMIO pointer
+char output[SZ_FNAME] # Output image name
+
+int i, clscan(), nscan()
+char type[1]
+pointer immap()
+errchk immap
+
+begin
+ out = immap (output, NEW_COPY, in)
+ IM_PIXTYPE(out) = TY_REAL
+ if (clscan ("pixeltype") != EOF) {
+ call gargwrd (type, 1)
+ if (nscan() == 1) {
+ i = IM_PIXTYPE(in)
+ IM_PIXTYPE(out) = i
+ switch (type[1]) {
+ case 's':
+ ;
+ case 'u':
+ if (i == TY_SHORT)
+ IM_PIXTYPE(out) = TY_USHORT
+ case 'i':
+ if (i == TY_SHORT || i == TY_USHORT)
+ IM_PIXTYPE(out) = TY_INT
+ case 'l':
+ if (i == TY_SHORT || i == TY_USHORT || i == TY_INT)
+ IM_PIXTYPE(out) = TY_LONG
+ case 'r':
+ if (i != TY_DOUBLE)
+ IM_PIXTYPE(out) = TY_REAL
+ case 'd':
+ IM_PIXTYPE(out) = TY_DOUBLE
+ default:
+ call imunmap (out)
+ call error (0, "Unknown pixel type")
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/ccdproc/setoverscan.x b/noao/imred/quadred/src/ccdproc/setoverscan.x
new file mode 100644
index 00000000..2fef378a
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setoverscan.x
@@ -0,0 +1,344 @@
+include <imhdr.h>
+include <imset.h>
+include <pkg/gtools.h>
+include <pkg/xtanswer.h>
+include "ccdred.h"
+
+
+# SET_OVERSCAN -- Set the overscan vector.
+#
+# 1. Return immediately if the overscan correction is not requested or
+# if the image has been previously corrected.
+# 2. Determine the overscan columns or lines. This may be specifed
+# directly or indirectly through the image header or symbol table.
+# 3. Average the overscan columns or lines.
+# 4. Fit a function with the ICFIT routines to smooth the overscan vector.
+# 5. Set the processing flag.
+# 6. Log the operation (to user, logfile, and output image header).
+
+procedure set_overscan (ccd)
+
+pointer ccd # CCD structure pointer
+
+int i, j, nsec, navg, npts, first, last
+int nc, nl, c1, c2, l1, l2
+pointer sp, str, errstr, buf, overscan, x, y, z
+
+real asumr()
+bool clgetb(), ccdflag()
+pointer imgl2r()
+errchk imgl2r, fit_overscan
+
+begin
+ # Check if the user wants this operation or if it has been done.
+ if (!clgetb ("overscan") || ccdflag (IN_IM(ccd), "overscan"))
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (errstr, SZ_LINE, TY_CHAR)
+ call imstats (IN_IM(ccd), IM_IMAGENAME, Memc[str], SZ_LINE)
+
+ # Check bias section.
+ nc = IM_LEN(IN_IM(ccd),1)
+ nl = IM_LEN(IN_IM(ccd),2)
+
+ c1 = BIAS_C1(ccd)
+ c2 = BIAS_C2(ccd)
+ l1 = BIAS_L1(ccd)
+ l2 = BIAS_L2(ccd)
+ navg = c2 - c1 + 1
+ npts = CCD_L2(ccd) - CCD_L1(ccd) + 1
+
+ nsec = max (1, IN_NSEC(ccd))
+ do i = 1, nsec {
+ if (BIAS_SEC(ccd) != NULL) {
+ c1 = BIAS_SC1(ccd,i)
+ c2 = BIAS_SC2(ccd,i)
+ l1 = BIAS_SL1(ccd,i)
+ l2 = BIAS_SL2(ccd,i)
+ }
+ if ((c1 < 1) || (c2 > nc) || (l1 < 1) || (l2 > nl)) {
+ call sprintf (Memc[errstr], SZ_LINE,
+ "Error in bias section: image=%s[%d,%d], biassec=[%d:%d,%d:%d]")
+ call pargstr (Memc[str])
+ call pargi (nc)
+ call pargi (nl)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[errstr])
+ }
+ if ((c1 == 1) && (c2 == nc) && (l1 == 1) && (l2 == nl)) {
+ call error (0,
+ "Bias section not specified or given as full image")
+ }
+
+ # If no processing is desired then print overscan strip and return.
+ if (clgetb ("noproc")) {
+ call eprintf (
+ " [TO BE DONE] Overscan section is [%d:%d,%d:%d].\n")
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call sfree (sp)
+ return
+ }
+ }
+
+ # Determine the overscan section parameters. The readout axis
+ # determines the type of overscan. The step sizes are ignored.
+ # The limits in the long dimension are replaced by the trim limits.
+
+ if (READAXIS(ccd) == 1) {
+ call salloc (buf, nsec*nl, TY_REAL)
+ z = buf
+ do i = 1, nl {
+ y = imgl2r (IN_IM(ccd), i)
+ do j = 1, nsec {
+ if (BIAS_SEC(ccd) != NULL) {
+ l1 = BIAS_SL1(ccd,j)
+ l2 = BIAS_SL2(ccd,j)
+ if (i < l1 || i > l2)
+ next
+ c1 = BIAS_SC1(ccd,j)
+ c2 = BIAS_SC2(ccd,j)
+ navg = c2 - c1 + 1
+ z = buf + (j - 1) * nl
+ }
+ Memr[z+i-1] = asumr (Memr[y+c1-1], navg)
+ }
+ }
+
+ # Trim the overscan vector and set the pixel coordinate.
+ call salloc (x, nl, TY_REAL)
+ call malloc (overscan, nsec*nl, TY_REAL)
+ y = overscan
+ do i = 1, nsec {
+ if (BIAS_SEC(ccd) != NULL) {
+ c1 = BIAS_SC1(ccd,i)
+ c2 = BIAS_SC2(ccd,i)
+ l1 = BIAS_SL1(ccd,i)
+ l2 = BIAS_SL2(ccd,i)
+ navg = c2 - c1 + 1
+ npts = l2 - l1 + 1
+ y = overscan + (i - 1) * nl
+ z = buf + (i - 1) * nl
+ }
+ if (navg > 1)
+ call adivkr (Memr[z+l1-1], real (navg), Memr[z+l1-1],
+ npts)
+ call trim_overscan (Memr[z], npts, l1, Memr[x], Memr[y])
+ call fit_overscan (Memc[str], c1, c2, l1, l2, Memr[x],
+ Memr[y], npts)
+ }
+
+ } else {
+ first = l1
+ last = l2
+ navg = last - first + 1
+ npts = nc
+ call salloc (buf, npts, TY_REAL)
+ call aclrr (Memr[buf], npts)
+ do i = first, last
+ call aaddr (Memr[imgl2r(IN_IM(ccd),i)], Memr[buf], Memr[buf],
+ npts)
+ if (navg > 1)
+ call adivkr (Memr[buf], real (navg), Memr[buf], npts)
+
+ # Trim the overscan vector and set the pixel coordinate.
+ npts = CCD_C2(ccd) - CCD_C1(ccd) + 1
+ call malloc (overscan, npts, TY_REAL)
+ call salloc (x, npts, TY_REAL)
+ call trim_overscan (Memr[buf], npts, IN_C1(ccd), Memr[x],
+ Memr[overscan])
+
+ call fit_overscan (Memc[str], c1, c2, l1, l2, Memr[x],
+ Memr[overscan], npts)
+ }
+
+ # Set the CCD structure overscan parameters.
+ CORS(ccd, OVERSCAN) = O
+ COR(ccd) = YES
+ OVERSCAN_VEC(ccd) = overscan
+
+ # Log the operation.
+ call strcpy ("overscan", Memc[errstr], SZ_LINE)
+ y = overscan
+ do i = 1, nsec {
+ if (BIAS_SEC(ccd) != NULL) {
+ c1 = BIAS_SC1(ccd,i)
+ c2 = BIAS_SC2(ccd,i)
+ l1 = BIAS_SL1(ccd,i)
+ l2 = BIAS_SL2(ccd,i)
+ y = overscan + (i - 1) * nl
+ npts = c2 - c1 + 1
+ if (i > 1) {
+ call sprintf (Memc[errstr], SZ_LINE, "ovrscn%d")
+ call pargi (i)
+ }
+ }
+ call sprintf (Memc[str], SZ_LINE,
+ "Overscan section is [%d:%d,%d:%d] with mean=%g")
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call pargr (asumr (Memr[y], npts) / npts)
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), Memc[errstr], Memc[str])
+ }
+
+ call sfree (sp)
+end
+
+
+# FIT_OVERSCAN -- Fit a function to smooth the overscan vector.
+# The fitting uses the ICFIT procedures which may be interactive.
+# Changes to these parameters are "learned". The user is queried with a four
+# valued logical query (XT_ANSWER routine) which may be turned off when
+# multiple images are processed.
+
+procedure fit_overscan (image, c1, c2, l1, l2, x, overscan, npts)
+
+char image[ARB] # Image name for query and title
+int c1, c2, l1, l2 # Overscan strip
+real x[npts] # Pixel coordinates of overscan
+real overscan[npts] # Input overscan and output fitted overscan
+int npts # Number of data points
+
+int interactive, fd
+pointer sp, str, w, ic, cv, gp, gt
+
+int clgeti(), ic_geti(), open()
+real clgetr(), ic_getr()
+pointer gopen(), gt_init()
+errchk gopen, open
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (w, npts, TY_REAL)
+ call amovkr (1., Memr[w], npts)
+
+ # Open the ICFIT procedures, get the fitting parameters, and
+ # set the fitting limits.
+
+ call ic_open (ic)
+ call clgstr ("function", Memc[str], SZ_LINE)
+ call ic_pstr (ic, "function", Memc[str])
+ call ic_puti (ic, "order", clgeti ("order"))
+ call clgstr ("sample", Memc[str], SZ_LINE)
+ call ic_pstr (ic, "sample", Memc[str])
+ call ic_puti (ic, "naverage", clgeti ("naverage"))
+ call ic_puti (ic, "niterate", clgeti ("niterate"))
+ call ic_putr (ic, "low", clgetr ("low_reject"))
+ call ic_putr (ic, "high", clgetr ("high_reject"))
+ call ic_putr (ic, "grow", clgetr ("grow"))
+ call ic_putr (ic, "xmin", min (x[1], x[npts]))
+ call ic_putr (ic, "xmax", max (x[1], x[npts]))
+ call ic_pstr (ic, "xlabel", "Pixel")
+ call ic_pstr (ic, "ylabel", "Overscan")
+
+ # If the fitting is done interactively set the GTOOLS and GIO
+ # pointers. Also "learn" the fitting parameters since they may
+ # be changed when fitting interactively.
+
+ call sprintf (Memc[str], SZ_LINE,
+ "Fit overscan vector for %s[%d:%d,%d:%d] interactively")
+ call pargstr (image)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call set_interactive (Memc[str], interactive)
+ if ((interactive == YES) || (interactive == ALWAYSYES)) {
+ gt = gt_init ()
+ call sprintf (Memc[str], SZ_LINE,
+ "Overscan vector for %s from section [%d:%d,%d:%d]\n")
+ call pargstr (image)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call gt_sets (gt, GTTITLE, Memc[str])
+ call gt_sets (gt, GTTYPE, "line")
+ call gt_setr (gt, GTXMIN, x[1])
+ call gt_setr (gt, GTXMAX, x[npts])
+ call clgstr ("graphics", Memc[str], SZ_FNAME)
+ gp = gopen (Memc[str], NEW_FILE, STDGRAPH)
+
+ call icg_fit (ic, gp, "cursor", gt, cv, x, overscan, Memr[w], npts)
+
+ call ic_gstr (ic, "function", Memc[str], SZ_LINE)
+ call clpstr ("function", Memc[str])
+ call clputi ("order", ic_geti (ic, "order"))
+ call ic_gstr (ic, "sample", Memc[str], SZ_LINE)
+ call clpstr ("sample", Memc[str])
+ call clputi ("naverage", ic_geti (ic, "naverage"))
+ call clputi ("niterate", ic_geti (ic, "niterate"))
+ call clputr ("low_reject", ic_getr (ic, "low"))
+ call clputr ("high_reject", ic_getr (ic, "high"))
+ call clputr ("grow", ic_getr (ic, "grow"))
+
+ call gclose (gp)
+ call gt_free (gt)
+ } else
+ call ic_fit (ic, cv, x, overscan, Memr[w], npts, YES, YES, YES, YES)
+
+ # Make a log of the fit in the plot file if given.
+ call clgstr ("plotfile", Memc[str], SZ_LINE)
+ call xt_stripwhite (Memc[str])
+ if (Memc[str] != EOS) {
+ fd = open (Memc[str], APPEND, BINARY_FILE)
+ gp = gopen ("stdvdm", NEW_FILE, fd)
+ gt = gt_init ()
+ call sprintf (Memc[str], SZ_LINE,
+ "Overscan vector for %s from section [%d:%d,%d:%d]\n")
+ call pargstr (image)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call gt_sets (gt, GTTITLE, Memc[str])
+ call gt_sets (gt, GTTYPE, "line")
+ call gt_setr (gt, GTXMIN, 1.)
+ call gt_setr (gt, GTXMAX, real (npts))
+ call icg_graphr (ic, gp, gt, cv, x, overscan, Memr[w], npts)
+ call gclose (gp)
+ call close (fd)
+ call gt_free (gt)
+ }
+
+ # Replace the raw overscan vector with the smooth fit.
+ call cvvector (cv, x, overscan, npts)
+
+ # Finish up.
+ call ic_closer (ic)
+ call cvfree (cv)
+ call sfree (sp)
+end
+
+
+# TRIM_OVERSCAN -- Trim the overscan vector.
+
+procedure trim_overscan (data, npts, start, x, overscan)
+
+real data[ARB] # Full overscan vector
+int npts # Length of trimmed vector
+int start # Trim start
+real x[npts] # Trimmed pixel coordinates (returned)
+real overscan[npts] # Trimmed overscan vector (returned)
+
+int i, j
+
+begin
+ do i = 1, npts {
+ j = start + i - 1
+ x[i] = j
+ overscan[i] = data[j]
+ }
+end
diff --git a/noao/imred/quadred/src/ccdproc/setproc.x b/noao/imred/quadred/src/ccdproc/setproc.x
new file mode 100644
index 00000000..595acd76
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setproc.x
@@ -0,0 +1,80 @@
+include <imhdr.h>
+include "ccdred.h"
+
+# SET_PROC -- Set the processing parameter structure pointer.
+
+procedure set_proc (in, out, ccd)
+
+pointer in # Input IMIO pointer
+pointer out # Output IMIO pointer
+pointer ccd # CCD structure (returned)
+
+int clgwrd(), clscan(), nscan()
+real clgetr()
+pointer sp, str
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Allocate the ccd structure.
+ call calloc (ccd, LEN_CCD, TY_STRUCT)
+
+ IN_IM(ccd) = in
+ OUT_IM(ccd) = out
+ COR(ccd) = NO
+ CORS(ccd, FIXPIX) = NO
+ CORS(ccd, OVERSCAN) = NO
+ CORS(ccd, TRIM) = NO
+ READAXIS(ccd) = clgwrd ("readaxis",Memc[str],SZ_LINE,"|line|columns|")
+ MINREPLACE(ccd) = clgetr ("minreplace")
+
+ CALCTYPE(ccd) = TY_REAL
+ if (clscan ("pixeltype") != EOF) {
+ call gargwrd (Memc[str], SZ_LINE)
+ call gargwrd (Memc[str], SZ_LINE)
+ if (nscan() == 2) {
+ if (Memc[str] == 'r')
+ CALCTYPE(ccd) = TY_REAL
+ else if (Memc[str] == 's')
+ CALCTYPE(ccd) = TY_SHORT
+ else
+ call error (1, "Invalid calculation datatype")
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# FREE_PROC -- Free the processing structure pointer.
+
+procedure free_proc (ccd)
+
+pointer ccd # CCD structure
+
+begin
+ # Unmap calibration images.
+ if (ZERO_IM(ccd) != NULL)
+ call ccd_unmap (ZERO_IM(ccd))
+ if (DARK_IM(ccd) != NULL)
+ call ccd_unmap (DARK_IM(ccd))
+ if (FLAT_IM(ccd) != NULL)
+ call ccd_unmap (FLAT_IM(ccd))
+ if (ILLUM_IM(ccd) != NULL)
+ call ccd_unmap (ILLUM_IM(ccd))
+ if (FRINGE_IM(ccd) != NULL)
+ call ccd_unmap (FRINGE_IM(ccd))
+
+ # Free memory
+ if (BADCOLS(ccd) != NULL)
+ call mfree (BADCOLS(ccd), TY_SHORT)
+ if (BADLINES(ccd) != NULL)
+ call mfree (BADLINES(ccd), TY_SHORT)
+ if (OVERSCAN_VEC(ccd) != NULL)
+ call mfree (OVERSCAN_VEC(ccd), TY_REAL)
+ call mfree (IN_SEC(ccd), TY_INT)
+ call mfree (OUT_SEC(ccd), TY_INT)
+ call mfree (BIAS_SEC(ccd), TY_INT)
+ call mfree (ccd, TY_STRUCT)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setsections.x b/noao/imred/quadred/src/ccdproc/setsections.x
new file mode 100644
index 00000000..b83a9d13
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setsections.x
@@ -0,0 +1,327 @@
+include <imhdr.h>
+include "ccdred.h"
+
+# SET_SECTIONS -- Set the data section, ccd section, trim section and
+# bias section.
+
+procedure set_sections (ccd)
+
+pointer ccd # CCD structure (returned)
+
+pointer sp, str
+int nc, nl, c1, c2, cs, l1, l2, ls
+bool streq()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ nc = IM_LEN(IN_IM(ccd),1)
+ nl = IM_LEN(IN_IM(ccd),2)
+
+ # The default data section is the entire image.
+ c1 = 1
+ c2 = nc
+ cs = 1
+ l1 = 1
+ l2 = nl
+ ls = 1
+ call hdmgstr (IN_IM(ccd), "datasec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1))
+ call error (0, "Error in DATASEC parameter")
+ IN_C1(ccd) = c1
+ IN_C2(ccd) = c2
+ IN_L1(ccd) = l1
+ IN_L2(ccd) = l2
+
+ # The default trim section is the data section.
+ # Defer limit checking until actually used.
+ c1 = IN_C1(ccd)
+ c2 = IN_C2(ccd)
+ l1 = IN_L1(ccd)
+ l2 = IN_L2(ccd)
+ call clgstr ("trimsec", Memc[str], SZ_LINE)
+ if (streq (Memc[str], "image"))
+ call hdmgstr (IN_IM(ccd), "trimsec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((cs!=1)||(ls!=1))
+ call error (0, "Error in TRIMSEC parameter")
+ TRIM_C1(ccd) = c1
+ TRIM_C2(ccd) = c2
+ TRIM_L1(ccd) = l1
+ TRIM_L2(ccd) = l2
+
+ # The default bias section is the whole image.
+ # Defer limit checking until actually used.
+ c1 = 1
+ c2 = nc
+ l1 = 1
+ l2 = nl
+ call clgstr ("biassec", Memc[str], SZ_LINE)
+ if (streq (Memc[str], "image"))
+ call hdmgstr (IN_IM(ccd), "biassec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((cs!=1)||(ls!=1))
+ call error (0, "Error in BIASSEC parameter")
+ BIAS_C1(ccd) = c1
+ BIAS_C2(ccd) = c2
+ BIAS_L1(ccd) = l1
+ BIAS_L2(ccd) = l2
+
+ # The default ccd section is the size of the data section.
+ c1 = 1
+ c2 = IN_C2(ccd) - IN_C1(ccd) + 1
+ l1 = 1
+ l2 = IN_L2(ccd) - IN_L1(ccd) + 1
+ call hdmgstr (IN_IM(ccd), "ccdsec", Memc[str], SZ_LINE)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((cs != 1) || (ls != 1))
+ call error (0, "Error in CCDSEC parameter")
+ CCD_C1(ccd) = c1
+ CCD_C2(ccd) = c2
+ CCD_L1(ccd) = l1
+ CCD_L2(ccd) = l2
+ if ((IN_C2(ccd)-IN_C1(ccd) != CCD_C2(ccd)-CCD_C1(ccd)) ||
+ (IN_L2(ccd)-IN_L1(ccd) != CCD_L2(ccd)-CCD_L1(ccd)))
+ call error (0, "Size of DATASEC and CCDSEC do not agree")
+
+ # The default output data section is the input data section.
+ OUT_C1(ccd) = IN_C1(ccd)
+ OUT_C2(ccd) = IN_C2(ccd)
+ OUT_L1(ccd) = IN_L1(ccd)
+ OUT_L2(ccd) = IN_L2(ccd)
+
+ # Set ARCON style sections.
+ call set_arcon (ccd)
+
+ call sfree (sp)
+end
+
+
+# SET_ARCON -- Set the data section, ccd section, trim section and
+# bias section.
+
+procedure set_arcon (ccd)
+
+pointer ccd # CCD structure (returned)
+
+pointer sp, amplist, amp, key, str
+int i, ip, nc, nl, c1, c2, cs, l1, l2, ls, ctowrd()
+int xt1, xt2, yt1, yt2
+bool trim, clgetb()
+
+begin
+ call smark (sp)
+ call salloc (amplist, SZ_LINE, TY_CHAR)
+ call salloc (amp, SZ_LINE, TY_CHAR)
+ call salloc (key, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ trim = clgetb ("trim")
+
+ # Get AMPLIST and determine the number of amplifiers.
+ # If there is no AMPLIST or missing BSEC keywords return.
+ call hdmgstr (IN_IM(ccd), "amplist", Memc[amplist], SZ_LINE)
+ if (Memc[amplist] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ ip = 1
+ for (i=0; ctowrd(Memc[amplist],ip,Memc[amp],SZ_LINE)!=0; i=i+1) {
+ call sprintf (Memc[key], SZ_LINE, "bsec%s")
+ call pargstr (Memc[amp])
+ call hdmgstr (IN_IM(ccd), Memc[key], Memc[str], SZ_LINE)
+ if (Memc[str] == EOS) {
+ call sfree (sp)
+ return
+ }
+ }
+ if (i == 0) {
+ call sfree (sp)
+ return
+ }
+
+ IN_NSEC(ccd) = i
+ call malloc (IN_SEC(ccd), 4*i, TY_INT)
+ call malloc (OUT_SEC(ccd), 4*i, TY_INT)
+ call malloc (BIAS_SEC(ccd), 4*i, TY_INT)
+
+ nc = IM_LEN(IN_IM(ccd),1)
+ nl = IM_LEN(IN_IM(ccd),2)
+
+ ip = 1
+ for (i=1; ctowrd(Memc[amplist],ip,Memc[amp],SZ_LINE)!=0; i=i+1) {
+
+ # Use amp section if no trim and data section if trim.
+ c1 = 1; c2 = nc; cs = 1; l1 = 1; l2 = nl; ls = 1
+ if (trim)
+ call sprintf (Memc[key], SZ_LINE, "dsec%s")
+ else
+ call sprintf (Memc[key], SZ_LINE, "asec%s")
+ call pargstr (Memc[amp])
+ call hdmgstr (IN_IM(ccd), Memc[key], Memc[str], SZ_LINE)
+ if (Memc[str] == EOS) {
+ call sprintf (Memc[str], SZ_LINE, "Keyword %s not found")
+ call pargstr (Memc[key])
+ call error (0, Memc[str])
+ }
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)) {
+ call sprintf (Memc[str], SZ_LINE, "Error in %s parameter")
+ call pargstr (Memc[key])
+ call error (0, Memc[str])
+ }
+ IN_SC1(ccd,i) = c1
+ IN_SC2(ccd,i) = c2
+ IN_SL1(ccd,i) = l1
+ IN_SL2(ccd,i) = l2
+
+ # If trimming match dsec with csec and then use tsec.
+ if (trim) {
+ c1 = IN_SC1(ccd,i); c2 = IN_SC2(ccd,i); cs = 1
+ l1 = IN_SL1(ccd,i); l2 = IN_SL2(ccd,i); ls = 1
+ call sprintf (Memc[key], SZ_LINE, "tsec%s")
+ call pargstr (Memc[amp])
+ call hdmgstr (IN_IM(ccd), Memc[key], Memc[str], SZ_LINE)
+ if (Memc[str] != EOS)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<IN_SC1(ccd,i))||(c2>IN_SC2(ccd,i))||
+ (l1<IN_SL1(ccd,i))||(l2>IN_SL2(ccd,i))) {
+ call sprintf (Memc[str], SZ_LINE, "Error in %s parameter")
+ call pargstr (Memc[key])
+ call error (0, Memc[str])
+ }
+ xt1 = max (0, c1 - IN_SC1(ccd,i))
+ xt2 = min (0, c2 - IN_SC2(ccd,i))
+ yt1 = max (0, l1 - IN_SL1(ccd,i))
+ yt2 = min (0, l2 - IN_SL2(ccd,i))
+
+ call sprintf (Memc[key], SZ_LINE, "csec%s")
+ call pargstr (Memc[amp])
+ call hdmgstr (IN_IM(ccd), Memc[key], Memc[str], SZ_LINE)
+ if (Memc[str] == EOS) {
+ call sprintf (Memc[str], SZ_LINE, "Keyword %s not found")
+ call pargstr (Memc[key])
+ call error (0, Memc[str])
+ }
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c2-c1) != (IN_SC2(ccd,i)-IN_SC1(ccd,i)) ||
+ (l2-l1) != (IN_SL2(ccd,i)-IN_SL1(ccd,i)))
+ call error (1, "DSEC and CSEC are different sizes")
+
+ IN_SC1(ccd,i) = IN_SC1(ccd,i) + xt1
+ IN_SC2(ccd,i) = IN_SC2(ccd,i) + xt2
+ IN_SL1(ccd,i) = IN_SL1(ccd,i) + yt1
+ IN_SL2(ccd,i) = IN_SL2(ccd,i) + yt2
+ OUT_SC1(ccd,i) = c1 + xt1
+ OUT_SC2(ccd,i) = c2 + xt2
+ OUT_SL1(ccd,i) = l1 + yt1
+ OUT_SL2(ccd,i) = l2 + yt2
+
+ } else {
+ OUT_SC1(ccd,i) = c1
+ OUT_SC2(ccd,i) = c2
+ OUT_SL1(ccd,i) = l1
+ OUT_SL2(ccd,i) = l2
+ }
+
+ # The default bias section is the whole image.
+ # Defer limit checking until actually used.
+ c1 = 1
+ c2 = nc
+ l1 = 1
+ l2 = nl
+ call sprintf (Memc[key], SZ_LINE, "bsec%s")
+ call pargstr (Memc[amp])
+ call hdmgstr (IN_IM(ccd), Memc[key], Memc[str], SZ_LINE)
+ if (Memc[str] == EOS) {
+ call sprintf (Memc[str], SZ_LINE, "Keyword %s not found")
+ call pargstr (Memc[key])
+ call error (0, Memc[str])
+ }
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((cs!=1)||(ls!=1))
+ call error (0, "Error in BSEC parameter")
+ BIAS_SC1(ccd,i) = c1
+ BIAS_SC2(ccd,i) = c2
+ BIAS_SL1(ccd,i) = l1
+ BIAS_SL2(ccd,i) = l2
+
+ if (trim) {
+ #iferr (call hdmdelf (OUT_IM(ccd), "amplist"))
+ # ;
+ #call sprintf (Memc[key], SZ_LINE, "asec%s")
+ # call pargstr (Memc[amp])
+ #iferr (call hdmdelf (OUT_IM(ccd), Memc[key]))
+ # ;
+ call sprintf (Memc[key], SZ_LINE, "bsec%s")
+ call pargstr (Memc[amp])
+ iferr (call hdmdelf (OUT_IM(ccd), Memc[key]))
+ ;
+ call sprintf (Memc[key], SZ_LINE, "csec%s")
+ call pargstr (Memc[amp])
+ iferr (call hdmdelf (OUT_IM(ccd), Memc[key]))
+ ;
+ call sprintf (Memc[key], SZ_LINE, "dsec%s")
+ call pargstr (Memc[amp])
+ iferr (call hdmdelf (OUT_IM(ccd), Memc[key]))
+ ;
+ call sprintf (Memc[key], SZ_LINE, "tsec%s")
+ call pargstr (Memc[amp])
+ iferr (call hdmdelf (OUT_IM(ccd), Memc[key]))
+ ;
+ }
+ }
+
+ # Set global sections.
+ IN_C1(ccd) = IN_SC1(ccd,1)
+ IN_C2(ccd) = IN_SC2(ccd,1)
+ IN_L1(ccd) = IN_SL1(ccd,1)
+ IN_L2(ccd) = IN_SL2(ccd,1)
+ CCD_C1(ccd) = OUT_SC1(ccd,1)
+ CCD_C2(ccd) = OUT_SC2(ccd,1)
+ CCD_L1(ccd) = OUT_SL1(ccd,1)
+ CCD_L2(ccd) = OUT_SL2(ccd,1)
+ do i = 2, IN_NSEC(ccd) {
+ IN_C1(ccd) = min (IN_SC1(ccd,i), IN_C1(ccd))
+ IN_C2(ccd) = max (IN_SC2(ccd,i), IN_C2(ccd))
+ IN_L1(ccd) = min (IN_SL1(ccd,i), IN_L1(ccd))
+ IN_L2(ccd) = max (IN_SL2(ccd,i), IN_L2(ccd))
+ CCD_C1(ccd) = min (OUT_SC1(ccd,i), CCD_C1(ccd))
+ CCD_C2(ccd) = max (OUT_SC2(ccd,i), CCD_C2(ccd))
+ CCD_L1(ccd) = min (OUT_SL1(ccd,i), CCD_L1(ccd))
+ CCD_L2(ccd) = max (OUT_SL2(ccd,i), CCD_L2(ccd))
+ }
+ if (trim) {
+ OUT_C1(ccd) = CCD_C1(ccd) - CCD_C1(ccd) + 1
+ OUT_C2(ccd) = CCD_C2(ccd) - CCD_C1(ccd) + 1
+ OUT_L1(ccd) = CCD_L1(ccd) - CCD_L1(ccd) + 1
+ OUT_L2(ccd) = CCD_L2(ccd) - CCD_L1(ccd) + 1
+ ip = 1
+ for (i=1; ctowrd(Memc[amplist],ip,Memc[amp],SZ_LINE)!=0; i=i+1) {
+ OUT_SC1(ccd,i) = OUT_SC1(ccd,i) - CCD_C1(ccd) + 1
+ OUT_SC2(ccd,i) = OUT_SC2(ccd,i) - CCD_C1(ccd) + 1
+ OUT_SL1(ccd,i) = OUT_SL1(ccd,i) - CCD_L1(ccd) + 1
+ OUT_SL2(ccd,i) = OUT_SL2(ccd,i) - CCD_L1(ccd) + 1
+ call sprintf (Memc[key], SZ_LINE, "asec%s")
+ call pargstr (Memc[amp])
+ call sprintf (Memc[str], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (OUT_SC1(ccd,i))
+ call pargi (OUT_SC2(ccd,i))
+ call pargi (OUT_SL1(ccd,i))
+ call pargi (OUT_SL2(ccd,i))
+ call hdmpstr (OUT_IM(ccd), Memc[key], Memc[str])
+ }
+ IM_LEN(OUT_IM(ccd),1) = OUT_C2(ccd)
+ IM_LEN(OUT_IM(ccd),2) = OUT_L2(ccd)
+ } else {
+ OUT_C1(ccd) = IN_C1(ccd)
+ OUT_C2(ccd) = IN_C2(ccd)
+ OUT_L1(ccd) = IN_L1(ccd)
+ OUT_L2(ccd) = IN_L2(ccd)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/settrim.x b/noao/imred/quadred/src/ccdproc/settrim.x
new file mode 100644
index 00000000..1aef62c3
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/settrim.x
@@ -0,0 +1,115 @@
+include <imhdr.h>
+include <imset.h>
+include "ccdred.h"
+
+# SET_TRIM -- Set the trim parameters.
+#
+# 1. Return immediately if the trim correction is not requested or
+# if the image has been previously corrected.
+# 2. Determine the trim section. This may be specifed directly or
+# indirectly through the image header or symbol table.
+# 3. Parse the trim section and apply it to the output image.
+# 4. If the image is trimmed then log the operation and reset the output
+# image size.
+
+procedure set_trim (ccd)
+
+pointer ccd # CCD structure
+
+int xt1, xt2, yt1, yt2
+int nc, nl, c1, c2, l1, l2
+pointer sp, str, image
+bool clgetb(), ccdflag()
+define log_ 10
+
+begin
+ # Check if the user wants this operation or it has been done.
+ if (!clgetb ("trim") || ccdflag (IN_IM(ccd), "trim"))
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ if (IN_SEC(ccd) != NULL)
+ goto log_
+
+ # Check trim section.
+ nc = IM_LEN(IN_IM(ccd),1)
+ nl = IM_LEN(IN_IM(ccd),2)
+ c1 = TRIM_C1(ccd)
+ c2 = TRIM_C2(ccd)
+ l1 = TRIM_L1(ccd)
+ l2 = TRIM_L2(ccd)
+ if ((c1 < 1) || (c2 > nc) || (l1 < 1) || (l2 > nl)) {
+ call salloc (image, SZ_LINE, TY_CHAR)
+ call imstats (IN_IM(ccd), IM_IMAGENAME, Memc[image], SZ_FNAME)
+ call sprintf (Memc[str], SZ_LINE,
+ "Error in trim section: image=%s[%d,%d], trimsec=[%d:%d,%d:%d]")
+ call pargstr (Memc[image])
+ call pargi (nc)
+ call pargi (nl)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+
+ # If no processing is desired print trim section and return.
+ if (clgetb ("noproc")) {
+ call eprintf (" [TO BE DONE] Trim section is [%d:%d,%d:%d].\n")
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call sfree (sp)
+ return
+ }
+
+ xt1 = max (0, c1 - IN_C1(ccd))
+ xt2 = min (0, c2 - IN_C2(ccd))
+ yt1 = max (0, l1 - IN_L1(ccd))
+ yt2 = min (0, l2 - IN_L2(ccd))
+
+ CCD_C1(ccd) = CCD_C1(ccd) + xt1
+ CCD_C2(ccd) = CCD_C2(ccd) + xt2
+ CCD_L1(ccd) = CCD_L1(ccd) + yt1
+ CCD_L2(ccd) = CCD_L2(ccd) + yt2
+ IN_C1(ccd) = IN_C1(ccd) + xt1
+ IN_C2(ccd) = IN_C2(ccd) + xt2
+ IN_L1(ccd) = IN_L1(ccd) + yt1
+ IN_L2(ccd) = IN_L2(ccd) + yt2
+ OUT_C1(ccd) = IN_C1(ccd) - c1 + 1
+ OUT_C2(ccd) = IN_C2(ccd) - c1 + 1
+ OUT_L1(ccd) = IN_L1(ccd) - l1 + 1
+ OUT_L2(ccd) = IN_L2(ccd) - l1 + 1
+ IM_LEN(OUT_IM(ccd),1) = c2 - c1 + 1
+ IM_LEN(OUT_IM(ccd),2) = l2 - l1 + 1
+
+log_
+ if (IN_SEC(ccd) == NULL) {
+ CORS(ccd, TRIM) = YES
+ COR(ccd) = YES
+
+ call sprintf (Memc[str], SZ_LINE,
+ "Trim data section is [%d:%d,%d:%d]")
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "trim", Memc[str])
+ } else {
+ CORS(ccd, TRIM) = NO
+ COR(ccd) = YES
+
+ call sprintf (Memc[str], SZ_LINE,
+ "Trim multiple overscan sections")
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "trim", Memc[str])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/setzero.x b/noao/imred/quadred/src/ccdproc/setzero.x
new file mode 100644
index 00000000..610aeee7
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/setzero.x
@@ -0,0 +1,141 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "ccdred.h"
+include "ccdtypes.h"
+
+# SET_ZERO -- Set parameters for zero level correction.
+# 1. Return immediately if the zero level correction is not requested or
+# if the image has been previously corrected.
+# 2. Get the zero level correction image. Return an error if not found.
+# 3. If the zero level image has not been processed call ZEROPROC.
+# 4. Set the processing flag.
+# 5. Log the operation (to user, logfile, and output image header).
+
+procedure set_zero (ccd)
+
+pointer ccd # CCD structure
+
+int nscan, nc, nl, c1, c2, cs, l1, l2, ls, data_c1, ccd_c1, data_l1, ccd_l1
+pointer sp, str, image, im, ccd_cache()
+bool clgetb(), ccdflag(), ccdcheck()
+int ccdtypei(), ccdnscan()
+errchk cal_image, ccd_cache, ccdproc
+
+begin
+ # Check if the user wants this operation or it has been done.
+ if (!clgetb ("zerocor") || ccdflag (IN_IM(ccd), "zerocor"))
+ return
+
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the zero level correction image.
+ if (clgetb ("scancor"))
+ nscan = ccdnscan (IN_IM(ccd), ccdtypei(IN_IM(ccd)))
+ else
+ nscan = 1
+ call cal_image (IN_IM(ccd), ZERO, nscan, Memc[image], SZ_FNAME)
+
+ # If no processing is desired print zero correction image and return.
+ if (clgetb ("noproc")) {
+ call eprintf (" [TO BE DONE] Zero level correction image is %s.\n")
+ call pargstr (Memc[image])
+ call sfree (sp)
+ return
+ }
+
+ # Map the image and return on an error.
+ # Process the zero image if necessary.
+ # If nscan > 1 then the zero may not yet exist so create it
+ # from the unscanned zero.
+
+ iferr (im = ccd_cache (Memc[image], ZERO)) {
+ call cal_image (IN_IM(ccd), ZERO, 1, Memc[str], SZ_LINE)
+ im = ccd_cache (Memc[str], ZERO)
+ if (ccdcheck (im, ZERO)) {
+ call ccd_flush (im)
+ call ccdproc (Memc[str], ZERO)
+ }
+ call scancor (Memc[str], Memc[image], nscan, INDEF)
+ im = ccd_cache (Memc[image], ZERO)
+ }
+
+ if (ccdcheck (im, ZERO)) {
+ call ccd_flush (im)
+ call ccdproc (Memc[image], ZERO)
+ im = ccd_cache (Memc[image], ZERO)
+ }
+
+ # Set the processing parameters in the CCD structure.
+ nc = IM_LEN(im,1)
+ nl = IM_LEN(im,2)
+ c1 = 1
+ c2 = nc
+ l1 = 1
+ l2 = nl
+ cs = 1
+ ls = 1
+ call hdmgstr (im, "datasec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if ((c1<1)||(c2>nc)||(l1<1)||(l2>nl)||(cs!=1)||(ls!=1)) {
+ call sprintf (Memc[str], SZ_LINE,
+ "Data section error: image=%s[%d,%d], datasec=[%d:%d,%d:%d]")
+ call pargstr (Memc[image])
+ call pargi (nc)
+ call pargi (nl)
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+ data_c1 = c1
+ data_l1 = l1
+ call hdmgstr (im, "ccdsec", Memc[str], SZ_FNAME)
+ call ccd_section (Memc[str], c1, c2, cs, l1, l2, ls)
+ if (nc == 1) {
+ c1 = CCD_C1(ccd)
+ c2 = CCD_C2(ccd)
+ }
+ if (nl == 1) {
+ l1 = CCD_L1(ccd)
+ l2 = CCD_L2(ccd)
+ }
+ ccd_c1 = c1
+ ccd_l1 = l1
+ if ((c1 > CCD_C1(ccd)) || (c2 < CCD_C2(ccd)) ||
+ (l1 > CCD_L1(ccd)) || (l2 < CCD_L2(ccd))) {
+ call sprintf (Memc[str], SZ_LINE,
+ "CCD section error: input=[%d:%d,%d:%d], %s=[%d:%d,%d:%d]")
+ call pargi (CCD_C1(ccd))
+ call pargi (CCD_C2(ccd))
+ call pargi (CCD_L1(ccd))
+ call pargi (CCD_L2(ccd))
+ call pargstr (Memc[image])
+ call pargi (c1)
+ call pargi (c2)
+ call pargi (l1)
+ call pargi (l2)
+ call error (0, Memc[str])
+ }
+
+ ZERO_IM(ccd) = im
+ ZERO_C1(ccd) = CCD_C1(ccd) - ccd_c1 + data_c1
+ ZERO_C2(ccd) = CCD_C2(ccd) - ccd_c1 + data_c1
+ ZERO_L1(ccd) = CCD_L1(ccd) - ccd_l1 + data_l1
+ ZERO_L2(ccd) = CCD_L2(ccd) - ccd_l1 + data_l1
+
+ CORS(ccd, ZEROCOR) = Z
+ COR(ccd) = YES
+
+ # Log the operation.
+ call sprintf (Memc[str], SZ_LINE, "Zero level correction image is %s")
+ call pargstr (Memc[image])
+ call timelog (Memc[str], SZ_LINE)
+ call ccdlog (IN_IM(ccd), Memc[str])
+ call hdmpstr (OUT_IM(ccd), "zerocor", Memc[str])
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/t_ccdproc.x b/noao/imred/quadred/src/ccdproc/t_ccdproc.x
new file mode 100644
index 00000000..8d256046
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/t_ccdproc.x
@@ -0,0 +1,155 @@
+include <imhdr.h>
+include <error.h>
+include "ccdred.h"
+include "ccdtypes.h"
+
+define CACHEUNIT 1000000. # Units of max_cache parameter
+
+# T_CCDPROC -- Process CCD images
+#
+# This is the main procedure for processing CCD images. The images are
+# corrected for bad pixels, overscan levels, zero levels, dark counts,
+# flat field response, illumination errors, and fringe response. They
+# may also be trimmed. The input is a list of images to be processed.
+# Each image must match any image type requested. The checking of
+# whether to apply each correction, getting the required parameters, and
+# logging the operations is left to separate procedures, one for each
+# correction. The actual processing is done by a specialized procedure
+# designed to be very efficient. These procedures may also process
+# calibration images if necessary. There are two data type paths; one
+# for short pixel types and one for all other pixel types (usually
+# real).
+
+procedure t_ccdproc ()
+
+int list # List of CCD images to process
+int ccdtype # CCD image type
+int interactive # Fit overscan interactively?
+int max_cache # Maximum image cache size
+
+bool clgetb()
+real clgetr()
+int imtopenp(), imtgetim(), imtlen()
+pointer sp, input, output, str, in, out, ccd
+errchk set_input, set_output, ccddelete, cal_open
+errchk set_fixpix, set_zero, set_dark, set_flat, set_illum, set_fringe
+
+begin
+ call smark (sp)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the list and instrument translation file. Open the translation
+ # file. Initialize the interactive flag and the calibration images.
+
+ list = imtopenp ("images")
+ call clgstr ("instrument", Memc[input], SZ_FNAME)
+ call hdmopen (Memc[input])
+ call set_interactive ("", interactive)
+ call cal_open (list)
+ if (imtlen (list) < 3)
+ max_cache = 0.
+ else
+ max_cache = CACHEUNIT * clgetr ("max_cache")
+ call ccd_open (max_cache)
+
+ # Process each image.
+ while (imtgetim (list, Memc[input], SZ_FNAME) != EOF) {
+ if (clgetb ("noproc")) {
+ call printf ("%s:\n")
+ call pargstr (Memc[input])
+ }
+ call set_input (Memc[input], in, ccdtype)
+ if (in == NULL)
+ next
+
+ # Use a temporary image for output which will replace the input
+ # image after processing.
+
+ call mktemp ("tmp", Memc[output], SZ_FNAME)
+ call set_output (in, out, Memc[output])
+
+ # Set processing parameters applicable to all images.
+ call set_proc (in, out, ccd)
+ call set_sections (ccd)
+ call set_trim (ccd)
+ call set_fixpix (ccd)
+ call set_overscan (ccd)
+
+ # Set processing parameters for the standard CCD image types.
+ switch (ccdtype) {
+ case ZERO:
+ case DARK:
+ call set_zero (ccd)
+ case FLAT:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ CORS(ccd, FINDMEAN) = YES
+ CORS(ccd, MINREP) = YES
+ case ILLUM:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ call set_flat (ccd)
+ case OBJECT, COMP:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ call set_flat (ccd)
+ iferr {
+ call set_illum (ccd)
+ call set_fringe (ccd)
+ } then
+ call erract (EA_WARN)
+ default:
+ call set_zero (ccd)
+ call set_dark (ccd)
+ call set_flat (ccd)
+ iferr {
+ call set_illum (ccd)
+ call set_fringe (ccd)
+ } then
+ call erract (EA_WARN)
+ CORS(ccd, FINDMEAN) = YES
+ }
+
+ # Do the processing if the COR flag is set.
+
+ if (COR(ccd) == YES) {
+ call doproc (ccd)
+ call set_header (ccd)
+
+ # Replace the input image by the corrected image.
+ call imunmap (in)
+ call imunmap (out)
+ iferr (call ccddelete (Memc[input])) {
+ call imdelete (Memc[output])
+ call error (1,
+ "Can't delete or make backup of original image")
+ }
+ call imrename (Memc[output], Memc[input])
+ } else {
+ # Delete the temporary output image leaving the input unchanged.
+ call imunmap (in)
+ iferr (call imunmap (out))
+ ;
+ iferr (call imdelete (Memc[output]))
+ ;
+ }
+ call free_proc (ccd)
+
+ # Do special processing on certain image types.
+ switch (ccdtype) {
+ case ZERO:
+ call readcor (Memc[input])
+ case FLAT:
+ call ccdmean (Memc[input])
+ }
+ }
+
+ # Finish up.
+ call hdmclose ()
+ call imtclose (list)
+ call cal_close ()
+ call ccd_close ()
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/timelog.x b/noao/imred/quadred/src/ccdproc/timelog.x
new file mode 100644
index 00000000..7a8d969f
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/timelog.x
@@ -0,0 +1,29 @@
+include <time.h>
+
+
+# TIMELOG -- Prepend a time stamp to the given string.
+#
+# For the purpose of a history logging prepend a short time stamp to the
+# given string. Note that the input string is modified.
+
+procedure timelog (str, max_char)
+
+char str[max_char] # String to be time stamped
+int max_char # Maximum characters in string
+
+pointer sp, time, temp
+long clktime()
+
+begin
+ call smark (sp)
+ call salloc (time, SZ_DATE, TY_CHAR)
+ call salloc (temp, max_char, TY_CHAR)
+
+ call cnvdate (clktime(0), Memc[time], SZ_DATE)
+ call sprintf (Memc[temp], max_char, "%s %s")
+ call pargstr (Memc[time])
+ call pargstr (str)
+ call strcpy (Memc[temp], str, max_char)
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/ccdproc/x_quadred.x b/noao/imred/quadred/src/ccdproc/x_quadred.x
new file mode 100644
index 00000000..a603d0d5
--- /dev/null
+++ b/noao/imred/quadred/src/ccdproc/x_quadred.x
@@ -0,0 +1 @@
+task ccdproc = t_ccdproc
diff --git a/noao/imred/quadred/src/mkpkg b/noao/imred/quadred/src/mkpkg
new file mode 100644
index 00000000..bd2bdbc0
--- /dev/null
+++ b/noao/imred/quadred/src/mkpkg
@@ -0,0 +1,4 @@
+update:
+ $call update@ccdproc
+ $call update@quad
+ ;
diff --git a/noao/imred/quadred/src/quad/Revisions b/noao/imred/quadred/src/quad/Revisions
new file mode 100644
index 00000000..55b490ed
--- /dev/null
+++ b/noao/imred/quadred/src/quad/Revisions
@@ -0,0 +1,92 @@
+---------------------------------------+--------------------------------------
+ Revisions started with version 1.1 of the QUAD package
+ 19/Mar/93
+
+ This package was written by Steve Heathcote!
+---------------------------------------+--------------------------------------
+
+quadgeom.x
+ Modified call to the ccd_section() routine (SH 19/Mar/93).
+
+ccdtypes.h
+ccdtypes.x
+ccdgetparam.x
+ Added routines to retrieve the image type from the image header,
+ and added special case to translate the image type to the
+ corresponding package name in ccdgetparam() (SH 19/May/93).
+
+quadproc.cl
+ Added check to see if image is of type to be processed (SH 24/May/93).
+
+mkpkg
+quad.cl
+quadscale.x
+x_quad.x
+ Installed QUADSCALE task (SH,PG 24/May/93).
+
+
+________________________________________________________________________________
+ Version 2.0 29 March 94
+
+________________________________________________________________________________
+
+quadproc.cl
+qproc.cl
+ Fitting parameters adjusted interactively where not being saved if
+ quadproc aborted at a later stage. In interactive mode these parameters
+ are now written in qproc after each image has been processed and are
+ updated on disk. (SRH 30/Mar/94)
+
+quadproc.cl
+ When running with noproc+, if the calibration images supplied in the
+ input list, and these have already been processed through [OT] task
+ would complain that the calibration images where missing when the test
+ for second stage [ZF...] procesing was performed. Added calibration
+ images to list to be considered.n this case. This means that the
+ calibration images may appear twice in the output list but ....
+ (SRH 30/Mar/94)
+
+quadproc.cl
+ complained about missing calibration images if the process flags
+ where set and no calibrations where specified, even when no images in
+ the list required the calibration step (e.g. all were zeros). Switched
+ off the check for existance in the qpcalimage call. This means the
+ task will not report the absence of required calibration images until
+ they come to be used but ccdproc does that too. (SRH 30/Mar/94)
+
+ccddb/ctio/instruments.men
+ /Xfccd_f1.dat
+ /Xfccd_f2.dat
+ /Xfccd_bith.dat
+ Added specific instrument files for the different filter subsets.
+ (SRH 30/Mar/94)
+
+qghdr2.x, quadsections.x
+ All quadrants in reduced images were being flagged as phantoms
+ causing quadsections to return no sections. (SRH 10/Jun/94)
+
+quad/ccdproc.par
+ Updated for V2.11.2. This should be backwards compatible.
+ (10/8/99, Valdes)
+
+________________________________________________________________________________
+ Version 2.1 29 October 99
+
+________________________________________________________________________________
+
+qnoproc.cl
+qproc.cl
+ Removed explicit dependence on "imh". The image extension is that
+ given by the imtype environment variable. (FV 20/Oct/99)
+
+________________________________________________________________________________
+ Version 2.2 20 June 00
+
+________________________________________________________________________________
+
+qnoproc.cl
+qproc.cl
+ Changed "len" to "i" in the clause that is executed when
+ imtype contains a ','. This caused the error
+ "Attempt to access undefined local variable `len'.
+ (6/20/00, Valdes)
diff --git a/noao/imred/quadred/src/quad/ccd.dat b/noao/imred/quadred/src/quad/ccd.dat
new file mode 100644
index 00000000..9ed9a970
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccd.dat
@@ -0,0 +1,27 @@
+# CCD.DAT -- Instrument file to be used with ccdred when reducing direct
+# imageing data obtained with ArCon.
+
+# Uncomment ONE of the following 3 lines to select the
+# header keyword to use when grouping images into subsets by filter.
+#subset filters
+#subset filter1
+subset filter2
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" other
+COMPARISON other
+ZERO zero # New software
+#BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
+FOCUS object
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_both.dat b/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_both.dat
new file mode 100644
index 00000000..37991738
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_both.dat
@@ -0,0 +1,27 @@
+# CFCCD.DAT -- Instrument file to be used with quad when reducing direct
+# imageing data obtained with ArCon.
+
+# Uncomment ONE of the following 3 lines to select the
+# header keyword to use when grouping images into subsets by filter.
+subset filters
+#subset filter1
+#subset filter2
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f1.dat b/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f1.dat
new file mode 100644
index 00000000..68cd2063
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f1.dat
@@ -0,0 +1,27 @@
+# CFCCD.DAT -- Instrument file to be used with quad when reducing direct
+# imageing data obtained with ArCon.
+
+# Uncomment ONE of the following 3 lines to select the
+# header keyword to use when grouping images into subsets by filter.
+#subset filters
+subset filter1
+#subset filter2
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f2.dat b/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f2.dat
new file mode 100644
index 00000000..c4d03cb8
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/cfccd_f2.dat
@@ -0,0 +1,27 @@
+# CFCCD.DAT -- Instrument file to be used with quad when reducing direct
+# imageing data obtained with ArCon.
+
+# Uncomment ONE of the following 3 lines to select the
+# header keyword to use when grouping images into subsets by filter.
+#subset filters
+#subset filter1
+subset filter2
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/csccd.dat b/noao/imred/quadred/src/quad/ccddb/ctio/csccd.dat
new file mode 100644
index 00000000..000f8c07
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/csccd.dat
@@ -0,0 +1,23 @@
+# CCD.DAT -- Instrument file to be used with ccdred when reducing spectroscopic
+# data obtained with ArCon.
+
+subset none
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON object
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/echccd.dat b/noao/imred/quadred/src/quad/ccddb/ctio/echccd.dat
new file mode 100644
index 00000000..90d08173
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/echccd.dat
@@ -0,0 +1,23 @@
+# ECHCCD.DAT -- Instrument file to be used with ccdred when reducing echelle
+# spectroscopic data obtained with ArCon.
+
+subset none
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
+FOCUS object
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/instruments.men b/noao/imred/quadred/src/quad/ccddb/ctio/instruments.men
new file mode 100644
index 00000000..144c41d5
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/instruments.men
@@ -0,0 +1,9 @@
+cfccd_f1 - Cassegrain focus CCD direct subset=filter1
+cfccd_f2 - Cassegrain focus CCD direct subset=filter2
+cfccd_both - Cassegrain focus CCD direct subset=filters
+csccd - Cassegrain focus spectroscopy
+echccd - Echelle spectroscopy
+nfccd - Newtonian focus CCD direct (Schmidt)
+pfccd_f1 - Prime focus CCD direct subset=filter1
+pfccd_f2 - Prime focus CCD direct subset=filter2
+pfccd_both - Prime focus CCD direct subset=filters
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/nfccd.dat b/noao/imred/quadred/src/quad/ccddb/ctio/nfccd.dat
new file mode 100644
index 00000000..06a173cf
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/nfccd.dat
@@ -0,0 +1,23 @@
+# NFCCD.DAT -- Instrument file to be used with ccdred when reducing direct
+# imageing data obtained with ArCon.
+
+subset filter1
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_both.dat b/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_both.dat
new file mode 100644
index 00000000..ac8e03a6
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_both.dat
@@ -0,0 +1,27 @@
+# PFCCD.DAT -- Instrument file to be used with quad when reducing direct
+# imageing data obtained with ArCon.
+
+# Uncomment ONE of the following 3 lines to select the
+# header keyword to use when grouping images into subsets by filter.
+subset filters
+#subset filter1
+#subset filter2
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f1.dat b/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f1.dat
new file mode 100644
index 00000000..9893d7f1
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f1.dat
@@ -0,0 +1,27 @@
+# PFCCD.DAT -- Instrument file to be used with quad when reducing direct
+# imageing data obtained with ArCon.
+
+# Uncomment ONE of the following 3 lines to select the
+# header keyword to use when grouping images into subsets by filter.
+#subset filters
+subset filter1
+#subset filter2
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f2.dat b/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f2.dat
new file mode 100644
index 00000000..89028468
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddb/ctio/pfccd_f2.dat
@@ -0,0 +1,27 @@
+# PFCCD.DAT -- Instrument file to be used with quad when reducing direct
+# imageing data obtained with ArCon.
+
+# Uncomment ONE of the following 3 lines to select the
+# header keyword to use when grouping images into subsets by filter.
+#subset filters
+#subset filter1
+subset filter2
+
+exptime exptime
+darktime darktime
+imagetyp imagetyp
+biassec biassec
+datasec datasec
+trimsec trimsec
+fixfile fixfile
+
+FOCUS object
+OBJECT object
+DARK dark
+"PROJECTOR FLAT" flat
+"SKY FLAT" flat
+COMPARISON other
+ZERO zero # New software
+BIAS zero # Old software
+"DOME FLAT" flat
+MASK other
diff --git a/noao/imred/quadred/src/quad/ccddelete.par b/noao/imred/quadred/src/quad/ccddelete.par
new file mode 100644
index 00000000..eaa63a22
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddelete.par
@@ -0,0 +1 @@
+image,s,a,"",,,Image to be delete (backed up)
diff --git a/noao/imred/quadred/src/quad/ccddelete.x b/noao/imred/quadred/src/quad/ccddelete.x
new file mode 100644
index 00000000..8a72796d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccddelete.x
@@ -0,0 +1,65 @@
+procedure t_ccddelete ()
+
+char image[SZ_LINE] # Image to delete (backup)
+
+begin
+
+ call clgstr ("image", image, SZ_LINE)
+ call ccddelete (image)
+end
+
+# CCDDELETE -- Delete an image by renaming it to a backup image.
+#
+# 1. Get the backup prefix which may be a path name.
+# 2. If no prefix is specified then delete the image without a backup.
+# 3. If there is a prefix then make a backup image name.
+# Rename the image to the backup image name.
+#
+# The backup image name is formed by prepending the backup prefix to the
+# image name. If a previous backup exist append integers to the backup
+# prefix until a nonexistant image name is created.
+
+procedure ccddelete (image)
+
+char image[ARB] # Image to delete (backup)
+
+int i, imaccess()
+pointer sp, prefix, backup
+errchk imdelete, imrename
+
+begin
+ call smark (sp)
+ call salloc (prefix, SZ_FNAME, TY_CHAR)
+ call salloc (backup, SZ_FNAME, TY_CHAR)
+
+ # Get the backup prefix.
+ call clgstr ("backup", Memc[prefix], SZ_FNAME)
+ call xt_stripwhite (Memc[prefix])
+
+ # If there is no prefix then simply delete the image.
+ if (Memc[prefix] == EOS)
+ call imdelete (image)
+
+ # Otherwise create a backup image name which does not exist and
+ # rename the image to the backup image.
+
+ else {
+ i = 0
+ repeat {
+ if (i == 0) {
+ call sprintf (Memc[backup], SZ_FNAME, "%s%s")
+ call pargstr (Memc[prefix])
+ call pargstr (image)
+ } else {
+ call sprintf (Memc[backup], SZ_FNAME, "%s%d%s")
+ call pargstr (Memc[prefix])
+ call pargi (i)
+ call pargstr (image)
+ }
+ i = i + 1
+ } until (imaccess (Memc[backup], READ_ONLY) == NO)
+ call imrename (image, Memc[backup])
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/quad/ccdgetparam.par b/noao/imred/quadred/src/quad/ccdgetparam.par
new file mode 100644
index 00000000..8647c9a9
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdgetparam.par
@@ -0,0 +1,2 @@
+image,s,a,"",,,Image whose parameter is to be fetched
+parameter,s,a,"",,,Parameter to be listed
diff --git a/noao/imred/quadred/src/quad/ccdgetparam.x b/noao/imred/quadred/src/quad/ccdgetparam.x
new file mode 100644
index 00000000..a032b553
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdgetparam.x
@@ -0,0 +1,48 @@
+procedure ccdgetparam ()
+
+char image[SZ_FNAME] # Image whose parameter is to be fetched
+char parameter[SZ_LINE] # Parameter whose value is required.
+char instrument[SZ_FNAME] # CCD intrument file.
+
+char buffer[SZ_LINE]
+pointer im
+
+pointer immap()
+int hdmaccf()
+bool streq()
+
+begin
+
+ call clgstr ("image", image, SZ_FNAME)
+ im = immap (image, READ_ONLY, 0)
+
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ call clgstr ("parameter", parameter, SZ_LINE)
+
+ # Handle special cases where we must translate the parameter value
+ # to the corresponding package name.
+ if (streq (parameter, "imagetyp")) {
+ call ccdtypes (im, buffer, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (buffer)
+
+ } else if (streq (parameter, "subset")) {
+ call ccdsubset (im, buffer, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (buffer)
+
+ } else {
+
+ if (hdmaccf (im, parameter) == NO) {
+ call printf ("UNDEFINED!\n")
+ } else {
+ call hdmgstr (im, parameter, buffer, SZ_LINE)
+ call printf ("%s\n")
+ call pargstr (buffer)
+ }
+ }
+
+ call imunmap (im)
+end
diff --git a/noao/imred/quadred/src/quad/ccdlog.x b/noao/imred/quadred/src/quad/ccdlog.x
new file mode 100644
index 00000000..61bbff10
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdlog.x
@@ -0,0 +1,42 @@
+
+# CCDLOG -- Log information about the processing with the image name.
+#
+# 1. If the package "verbose" parameter is set print the string preceded
+# by the image name.
+# 2. If the package "logfile" parameter is not null append the string,
+# preceded by the image name, to the file.
+
+procedure ccdlog (image, str)
+
+char image[ARB] # Image name
+char str[ARB] # Log string
+
+int fd, open()
+bool clgetb()
+pointer sp, fname
+errchk open
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+
+ # Write to the standard error output if "verbose".
+ if (clgetb ("verbose")) {
+ call eprintf ("%s: %s\n")
+ call pargstr (image)
+ call pargstr (str)
+ }
+
+ # Append to the "logfile" if not null.
+ call clgstr ("logfile", Memc[fname], SZ_FNAME)
+ call xt_stripwhite (Memc[fname])
+ if (Memc[fname] != EOS) {
+ fd = open (Memc[fname], APPEND, TEXT_FILE)
+ call fprintf (fd, "%s: %s\n")
+ call pargstr (image)
+ call pargstr (str)
+ call close (fd)
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/quad/ccdprcselect.par b/noao/imred/quadred/src/quad/ccdprcselect.par
new file mode 100644
index 00000000..453f4b4d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdprcselect.par
@@ -0,0 +1,4 @@
+input,s,a,"",,,Input image list
+output,s,h,"STDOUT",,,Output image list
+procflag,s,h,"",,,Processing flag for filter action
+ccdtype,s,h,"",,,CCD image type to be listed
diff --git a/noao/imred/quadred/src/quad/ccdprcselect.x b/noao/imred/quadred/src/quad/ccdprcselect.x
new file mode 100644
index 00000000..11b4e2ef
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdprcselect.x
@@ -0,0 +1,90 @@
+# CCD_PRCSELECT -- Filter a list of image names passing on only those that
+# do (or don't) have a specified processing flag set.
+
+include "ccdtypes.h"
+
+define PROCFLAGS "|fixpix|overscan|trim|zerocor|darkcor|flatcor|illumcor\
+ |fringecor|ccdproc|"
+
+procedure t_ccdprcselect ()
+
+pointer inlist #TI List of input image name.
+char output[SZ_FNAME] #TI List of output image names.
+char instrument[SZ_FNAME] #TI Instrument translation file.
+char procflag[SZ_LINE] #TI List of proc flags.
+char ccdtype[SZ_LINE] #TI ccdtype to select.
+
+int flag, ip, type
+char image[SZ_LINE], buffer[SZ_LINE]
+pointer fdout, im
+
+int strdic(), imtopenp(), imtgetim(), hdmaccf(), ctowrd(), imaccess()
+int ccdtypei()
+
+pointer open(), immap()
+
+begin
+ # Open input and output image lists
+ inlist = imtopenp ("input")
+ call clgstr ("output", output, SZ_LINE)
+ fdout = open (output, APPEND, TEXT_FILE)
+
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Get processing flag.
+ # If the first character is "!" pass all images for which the specified
+ # flag is not set. If the processing flag is "" we pass al images.
+ flag = 0
+ call clgstr ("procflag", buffer, SZ_LINE)
+ ip = 1
+ if (ctowrd (buffer, ip, procflag, SZ_LINE) != 0) {
+ if (procflag[1] == '!') {
+ flag = -1 * strdic (procflag[2], procflag, SZ_LINE, PROCFLAGS)
+ } else {
+ flag = strdic (procflag, procflag, SZ_LINE, PROCFLAGS)
+ }
+ if (flag == 0)
+ call error (0, "Unknown processing flag")
+ }
+
+ # Get ccdtype to select.
+ call clgstr ("ccdtype", ccdtype, SZ_LINE)
+ type = strdic (ccdtype, ccdtype, SZ_LINE, CCDTYPES)
+
+ while (imtgetim (inlist, image, SZ_LINE) != EOF) {
+
+ # Silently skip any non-existant images
+ if (imaccess (image, READ_ONLY) == NO)
+ next
+
+ im = immap (image, READ_ONLY, 0)
+
+ if ((ccdtype[1] != EOS) && (type != ccdtypei (im))) {
+ call imunmap (im)
+ next
+ }
+
+ if (flag < 0) {
+ if (hdmaccf (im, procflag) == NO) {
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+ }
+ } else if (flag > 0) {
+ if (hdmaccf (im, procflag) == YES) {
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+ }
+ } else {
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+ }
+ call imunmap (im)
+ }
+
+ # Tidy up
+ call close (fdout)
+ call hdmclose ()
+ call imtclose (inlist)
+end
diff --git a/noao/imred/quadred/src/quad/ccdproc.par b/noao/imred/quadred/src/quad/ccdproc.par
new file mode 100644
index 00000000..01065e28
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdproc.par
@@ -0,0 +1,43 @@
+images,s,a,"",,,List of CCD images to correct
+output,s,h,"",,,List of output CCD images
+ccdtype,s,h,"other",,,CCD image type to correct
+max_cache,i,h,0,0,,Maximum image caching memory (in Mbytes)
+noproc,b,h,no,,,"List processing steps only?
+"
+fixpix,b,h,no,,,Fix bad CCD lines and columns?
+overscan,b,h,no,,,Apply overscan strip correction?
+trim,b,h,no,,,Trim the image?
+zerocor,b,h,no,,,Apply zero level correction?
+darkcor,b,h,no,,,Apply dark count correction?
+flatcor,b,h,no,,,Apply flat field correction?
+illumcor,b,h,no,,,Apply illumination correction?
+fringecor,b,h,no,,,Apply fringe correction?
+readcor,b,h,no,,,Convert zero level image to readout correction?
+scancor,b,h,no,,,"Convert flat field image to scan correction?
+"
+readaxis,s,h,"line","column|line",, Read out axis (column|line)
+fixfile,s,h,"",,,File describing the bad lines and columns
+biassec,s,h,"",,,Overscan strip image section
+trimsec,s,h,"",,,Trim data section
+zero,s,h,"",,,Zero level calibration image
+dark,s,h,"",,,Dark count calibration image
+flat,s,h,"",,,Flat field images
+illum,s,h,"",,,Illumination correction images
+fringe,s,h,"",,,Fringe correction images
+minreplace,r,h,1.,,,Minimum flat field value
+scantype,s,h,"shortscan","shortscan|longscan",,Scan type (shortscan|longscan)
+nscan,i,h,1,1,,"Number of short scan lines
+"
+interactive,b,h,no,,,Fit overscan interactively?
+function,s,h,"legendre",,,Fitting function
+order,i,h,1,1,,Number of polynomial terms or spline pieces
+sample,s,h,"*",,,Sample points to fit
+naverage,i,h,1,,,Number of sample points to combine
+niterate,i,h,1,0,,Number of rejection iterations
+low_reject,r,h,3.,0.,,Low sigma rejection factor
+high_reject,r,h,3.,0.,,High sigma rejection factor
+grow,r,h,0.,0.,,"Rejection growing radius
+"
+backup,s,h,"",,,Backup directory or prefix
+logfile,s,h,"",,,Text log file
+verbose,b,h,no,,,Print log information to the standard output?
diff --git a/noao/imred/quadred/src/quad/ccdsection.par b/noao/imred/quadred/src/quad/ccdsection.par
new file mode 100644
index 00000000..ff8ae7ed
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdsection.par
@@ -0,0 +1 @@
+section,s,a,,,,Section to decode
diff --git a/noao/imred/quadred/src/quad/ccdsection.x b/noao/imred/quadred/src/quad/ccdsection.x
new file mode 100644
index 00000000..d6b0d6a7
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdsection.x
@@ -0,0 +1,119 @@
+include <ctype.h>
+
+# CCD_SECTION -- Parse a 2D image section into its elements.
+# 1. The default values must be set by the caller.
+# 2. A null image section is OK.
+# 3. The first nonwhitespace character must be '['.
+# 4. The last interpreted character must be ']'.
+#
+# This procedure should be replaced with an IMIO procedure at some
+# point.
+
+
+# Cl callable entry point
+
+procedure t_ccdsection ()
+
+char section[SZ_LINE] #T Section to parse
+
+int x1, x2, y1, y2, xstep, ystep
+
+begin
+ call clgstr ("section", section, SZ_LINE)
+ call ccd_section (section, x1, x2, xstep, y1, y2, ystep)
+ call printf ("%d %d %d %d \n")
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+end
+
+procedure ccd_section (section, x1, x2, xstep, y1, y2, ystep)
+
+char section[ARB] # Image section
+int x1, x2, xstep # X image section parameters
+int y1, y2, ystep # X image section parameters
+
+int i, ip, a, b, c, temp, ctoi()
+define error_ 99
+
+begin
+ # Decode the section string.
+ ip = 1
+ while (IS_WHITE(section[ip]))
+ ip = ip + 1
+ if (section[ip] == '[')
+ ip = ip + 1
+ else if (section[ip] == EOS)
+ return
+ else
+ goto error_
+
+ do i = 1, 2 {
+ while (IS_WHITE(section[ip]))
+ ip = ip + 1
+
+ # Default values
+ if (i == 1) {
+ a = x1
+ b = x2
+ c = xstep
+ } else {
+ a = y1
+ b = y2
+ c = ystep
+ }
+
+ # Get a:b:c. Allow notation such as "-*:c"
+ # (or even "-:c") where the step is obviously negative.
+
+ if (ctoi (section, ip, temp) > 0) { # a
+ a = temp
+ if (section[ip] == ':') {
+ ip = ip + 1
+ if (ctoi (section, ip, b) == 0) # a:b
+ goto error_
+ } else
+ b = a
+ } else if (section[ip] == '-') { # -*
+ temp = a
+ a = b
+ b = temp
+ ip = ip + 1
+ if (section[ip] == '*')
+ ip = ip + 1
+ } else if (section[ip] == '*') # *
+ ip = ip + 1
+ if (section[ip] == ':') { # ..:step
+ ip = ip + 1
+ if (ctoi (section, ip, c) == 0)
+ goto error_
+ else if (c == 0)
+ goto error_
+ }
+ if (a > b && c > 0)
+ c = -c
+
+ if (i == 1) {
+ x1 = a
+ x2 = b
+ xstep = c
+ } else {
+ y1 = a
+ y2 = b
+ ystep = c
+ }
+
+ while (IS_WHITE(section[ip]))
+ ip = ip + 1
+ if (section[ip] == ',')
+ ip = ip + 1
+ }
+
+ if (section[ip] != ']')
+ goto error_
+
+ return
+error_
+ call error (0, "Error in image section specification")
+end
diff --git a/noao/imred/quadred/src/quad/ccdssselect.par b/noao/imred/quadred/src/quad/ccdssselect.par
new file mode 100644
index 00000000..8499900d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdssselect.par
@@ -0,0 +1,4 @@
+input,s,a,"",,,Input image list
+output,s,h,"STDOUT",,,Output image list
+subset,s,h,"",,,Subset to be listed
+ccdtype,s,h,"",,,CCD image type to be listed
diff --git a/noao/imred/quadred/src/quad/ccdssselect.x b/noao/imred/quadred/src/quad/ccdssselect.x
new file mode 100644
index 00000000..65a7248f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdssselect.x
@@ -0,0 +1,73 @@
+# CCDSUBSETSELECT -- Filter a list of image names passing on only those that
+# belong to a specified subset.
+
+include "ccdtypes.h"
+
+procedure t_ccdssselect ()
+
+pointer inlist #TI List of input image name.
+char output[SZ_FNAME] #TI List of output image names.
+char instrument[SZ_FNAME] #TI Instrument translation file.
+char subset[SZ_LINE] #TI Subset required.
+char ccdtype[SZ_LINE] #TI ccdtype required.
+
+int type
+char image[SZ_LINE], buffer[SZ_LINE]
+pointer fdout, im
+
+int strdic(), imtopenp(), imtgetim(), ccdtypei(), imaccess()
+pointer open(), immap()
+bool strne()
+
+begin
+ # Open input and output image lists
+ inlist = imtopenp ("input")
+ call clgstr ("output", output, SZ_LINE)
+ fdout = open (output, APPEND, TEXT_FILE)
+
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Get subset required.
+ call clgstr ("subset", subset, SZ_LINE)
+
+ # Get ccdtype required.
+ call clgstr ("ccdtype", ccdtype, SZ_LINE)
+ type = strdic (ccdtype, ccdtype, SZ_LINE, CCDTYPES)
+
+ while (imtgetim (inlist, image, SZ_LINE) != EOF) {
+
+ # Silently skip non-existant images
+ if (imaccess (image, READ_ONLY) == NO)
+ next
+
+ im = immap (image, READ_ONLY, 0)
+
+ # Skip images of the wrong type
+ if ((ccdtype[1] != EOS) && (type != ccdtypei (im))) {
+ call imunmap (im)
+ next
+ }
+
+ # Skip images of the wrong subset
+ if (subset[1] != EOS) {
+ call ccdsubset (im, buffer, SZ_LINE)
+ if (strne (subset, buffer)) {
+ call imunmap (im)
+ next
+ }
+ }
+
+ # print names of any images which pass the test.
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+
+ call imunmap (im)
+ }
+
+ # Tidy up
+ call close (fdout)
+ call hdmclose ()
+ call imtclose (inlist)
+end
diff --git a/noao/imred/quadred/src/quad/ccdsubsets.x b/noao/imred/quadred/src/quad/ccdsubsets.x
new file mode 100644
index 00000000..6152897f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdsubsets.x
@@ -0,0 +1,92 @@
+# CCDSUBSET -- Return the CCD subset identifier.
+#
+# 1. Get the subset string and search the subset record file for the ID string.
+# 2. If the subset string is not in the record file define a default ID string
+# based on the first word of the subset string. If the first word is not
+# unique append a integer to the first word until it is unique.
+# 3. Add the new subset string and identifier to the record file.
+# 4. Since the ID string is used to generate image names replace all
+# nonimage name characters with '_'.
+#
+# It is an error if the record file cannot be created or written when needed.
+
+procedure ccdsubset (im, subset, sz_name)
+
+pointer im # Image
+char subset[sz_name] # CCD subset identifier
+int sz_name # Size of subset string
+
+bool streq()
+int i, fd, ctowrd(), open(), fscan()
+pointer sp, fname, str1, str2, subset1, subset2, subset3
+errchk open
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+ call salloc (subset1, SZ_LINE, TY_CHAR)
+ call salloc (subset2, SZ_LINE, TY_CHAR)
+ call salloc (subset3, SZ_LINE, TY_CHAR)
+
+ # Get the subset record file and the subset string.
+ call clgstr ("ssfile", Memc[fname], SZ_LINE)
+ call hdmgstr (im, "subset", Memc[str1], SZ_LINE)
+
+ # The default subset identifier is the first word of the subset string.
+ i = 1
+ i = ctowrd (Memc[str1], i, Memc[subset1], SZ_LINE)
+
+ # A null subset string is ok. If not null check for conflict
+ # with previous subset IDs.
+ if (Memc[str1] != EOS) {
+ call strcpy (Memc[subset1], Memc[subset3], SZ_LINE)
+
+ # Search the subset record file for the same subset string.
+ # If found use the ID string. If the subset ID has been
+ # used for another subset string then increment an integer
+ # suffix to the default ID and check the list again.
+
+ i = 1
+ ifnoerr (fd = open (Memc[fname], READ_ONLY, TEXT_FILE)) {
+ while (fscan (fd) != EOF) {
+ call gargwrd (Memc[str2], SZ_LINE)
+ call gargwrd (Memc[subset2], SZ_LINE)
+ if (streq (Memc[str1], Memc[str2])) {
+ i = 0
+ call strcpy (Memc[subset2], Memc[subset1], SZ_LINE)
+ break
+ } if (streq (Memc[subset1], Memc[subset2])) {
+ call sprintf (Memc[subset1], SZ_LINE, "%s%d")
+ call pargstr (Memc[subset3])
+ call pargi (i)
+ i = i + 1
+ call seek (fd, BOF)
+ }
+ }
+ call close (fd)
+ }
+
+ # If the subset is not in the record file add it.
+ if (i > 0) {
+ fd = open (Memc[fname], APPEND, TEXT_FILE)
+ call fprintf (fd, "'%s'\t%s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[subset1])
+ call close (fd)
+ }
+ }
+
+ # Set the subset ID string and replace magic characters by '_'
+ # since the subset ID is used in forming image names.
+
+ call strcpy (Memc[subset1], subset, sz_name)
+ for (i=1; subset[i]!=EOS; i=i+1)
+ switch (subset[i]) {
+ case '-','+','?','*','[',']',' ','\t':
+ subset[i] = '_'
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/quad/ccdtypes.h b/noao/imred/quadred/src/quad/ccdtypes.h
new file mode 100644
index 00000000..0d5d4caf
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdtypes.h
@@ -0,0 +1,14 @@
+# Standard CCD image types.
+
+define CCDTYPES "|object|zero|dark|flat|illum|fringe|other|comp|"
+
+define NONE -1
+define UNKNOWN 0
+define OBJECT 1
+define ZERO 2
+define DARK 3
+define FLAT 4
+define ILLUM 5
+define FRINGE 6
+define OTHER 7
+define COMP 8
diff --git a/noao/imred/quadred/src/quad/ccdtypes.x b/noao/imred/quadred/src/quad/ccdtypes.x
new file mode 100644
index 00000000..bf6d29e2
--- /dev/null
+++ b/noao/imred/quadred/src/quad/ccdtypes.x
@@ -0,0 +1,72 @@
+include "ccdtypes.h"
+
+# CCDTYPES -- Return the CCD type name string.
+# CCDTYPEI -- Return the CCD type code.
+
+
+# CCDTYPES -- Return the CCD type name string.
+
+procedure ccdtypes (im, name, sz_name)
+
+pointer im # Image
+char name[sz_name] # CCD type name
+int sz_name # Size of name string
+
+int strdic()
+pointer sp, str
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the image type string. If none then return "none".
+ # Otherwise get the corresponding package image type string.
+ # If the image type is unknown return "unknown" otherwise return
+ # the package name.
+
+ call hdmgstr (im, "imagetyp", Memc[str], SZ_LINE)
+ if (Memc[str] == EOS) {
+ call strcpy ("none", name, sz_name)
+ } else {
+ call hdmname (Memc[str], name, sz_name)
+ if (name[1] == EOS)
+ call strcpy (Memc[str], name, sz_name)
+ if (strdic (name, name, sz_name, CCDTYPES) == UNKNOWN)
+ call strcpy ("unknown", name, sz_name)
+ }
+
+ call sfree (sp)
+end
+
+
+# CCDTYPEI -- Return the CCD type code.
+
+int procedure ccdtypei (im)
+
+pointer im # Image
+int ccdtype # CCD type (returned)
+
+pointer sp, str1, str2
+int strdic()
+
+begin
+ call smark (sp)
+ call salloc (str1, SZ_LINE, TY_CHAR)
+ call salloc (str2, SZ_LINE, TY_CHAR)
+
+ # Get the image type and if there is none then return the NONE code.
+ call hdmgstr (im, "imagetyp", Memc[str1], SZ_LINE)
+ if (Memc[str1] == EOS) {
+ ccdtype = NONE
+
+ # Otherwise get the package type and convert to an image type code.
+ } else {
+ call hdmname (Memc[str1], Memc[str2], SZ_LINE)
+ if (Memc[str2] == EOS)
+ call strcpy (Memc[str1], Memc[str2], SZ_LINE)
+ ccdtype = strdic (Memc[str2], Memc[str2], SZ_LINE, CCDTYPES)
+ }
+
+ call sfree (sp)
+ return (ccdtype)
+end
diff --git a/noao/imred/quadred/src/quad/detpars.par b/noao/imred/quadred/src/quad/detpars.par
new file mode 100644
index 00000000..bbb9f8aa
--- /dev/null
+++ b/noao/imred/quadred/src/quad/detpars.par
@@ -0,0 +1,6 @@
+xskip1,i,h,INDEF,0,,X pixels to skip at start of overscan
+xskip2,i,h,INDEF,0,,X pixels to skip at end of overscan
+xtrim1,i,h,INDEF,0,,X pixels to trim at start of data
+xtrim2,i,h,INDEF,0,,X pixels to trim at end of data
+ytrim1,i,h,INDEF,0,,Y pixels to trim at start of data
+ytrim2,i,h,INDEF,0,,Y pixels to trim at end of data
diff --git a/noao/imred/quadred/src/quad/doc/Geometry.fig b/noao/imred/quadred/src/quad/doc/Geometry.fig
new file mode 100644
index 00000000..429d987f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/Geometry.fig
@@ -0,0 +1,91 @@
+# The following diagrams show the CCD geometry for the different readout modes.
+#
+# Single readout:
+# G
+# <-------------------------------->
+# A F
+# <----------------------><-------->
+# B C D E
+# <-> <--><> <>
+# ^ ^ +-----------------------+--------+ ^ ^
+# | | | | | | e |
+# | c | | |--------| v |
+# | v | +----------------+ || || |
+# | | | | || o || |
+# | | | | || v || |
+# | | | | || e || |
+# a | | | | || r || | f
+# | | | | || s || |
+# | | | | || c || |
+# | | | | || a || |
+# | | +----------------+ || n || |
+# | ^ | |--------| |
+# | b | | | | ^ |
+# | | | | | | d |
+# v V *-----------------------+--------+ v v
+#
+# Quad readout (single frame):
+# G'
+# <--------------------------------->
+# A/2 F/2 F/2 A/2
+# <---------><---><---><----------->
+# B D 2*E D C
+# <-> <> < > <> <-->
+# ^ ^ *----------+----.----+------------* ^ ^
+# | | | | . | | | e |
+# | c | | |----.----| | v |
+# | v | +-------+| |.| |+--------+ | |
+# a/2 | | | ||o |.|o || | | | f/2
+# | | | 3 ||v |.|v || 4 | | |
+# | | | || |.| || | | |
+# | | | ||3 |.|4 || | | |
+# V ................................... v
+# ^ | | ||o |.|o || | | ^
+# | | | 1 ||v |.|v || 2 | | |
+# | | | || |.| || | | |
+# a/2 | | +-------+|1 |.|2 |+--------+ | | f/2
+# | ^ | || |.| || | |
+# | b | | |----.----| | ^ |
+# | | | | . | | | d |
+# v v *----------+----.----+------------* v V
+#
+#
+# Quad readout (four frames):
+#
+# G" G"
+# <--------------> <---------------->
+# A/2 F/2 F/2 A/2
+# <---------><----> <----><---------->
+# B D E E D C
+# <-> <> <> <> <> <-->
+# ^ ^ *----------+----+ +----+------------* ^ ^
+# | | | | | | | | | e |
+# | c | | |----| |----| | v |
+# a/2 | v | +-------+| || || |+--------+ | ^ |
+# | | | ||o || ||o || | | | | f/2
+# | | | 3 ||v || ||v || 4 | | | |
+# | | | || || || || | | | |
+# V | | ||3 || ||4 || | | | |
+# +---------------+ +-----------------+ v v
+#
+#
+# +---------------+ +-----------------+ ^ ^
+# ^ | | ||o || ||o || | | | |
+# | | | 1 ||v || ||v || 2 | | | |
+# | | | || || || || | | | |
+# | | +-------+|1 || ||2 |+--------+ | | | f/2
+# a/2 | ^ | || || || || | v |
+# | b | | |----| |----| | ^ |
+# | | | | | | | | | d |
+# v v *----------+----+ +----+------------* v v
+#
+# Where
+# A = xdata a = ydata
+# B = txskip1 b = tyskip1
+# C = txskip2 c = tyskip2
+# D = bxskip1 d = byskip1
+# E = bxskip2 e = byskip2
+# F = xover f = yover = a
+# G = A + F
+# G' = A + F
+# G" = (A + F) / 2
diff --git a/noao/imred/quadred/src/quad/doc/badpiximage.hlp b/noao/imred/quadred/src/quad/doc/badpiximage.hlp
new file mode 100644
index 00000000..46e13160
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/badpiximage.hlp
@@ -0,0 +1,51 @@
+.help badpiximage Jun87 noao.imred.ccdred
+.ih
+NAME
+badpiximage -- Create a bad pixel mask image from a bad pixel file
+.ih
+USAGE
+badpiximage fixfile template image
+.ih
+PARAMETERS
+.ls fixfile
+Bad pixel file.
+.le
+.ls template
+Template image used to define the size of the bad pixel mask image.
+.le
+.ls image
+Bad pixel mask image to be created.
+.le
+.ls goodvalue = 1
+Integer value assigned to the good pixels.
+.le
+.ls badvalue = 0
+Integer value assigned to the bad pixels.
+.le
+.ih
+DESCRIPTION
+A bad pixel mask image is created from the specified bad pixel file.
+The format of the bad pixel file is that used by \fBccdproc\fR to
+correct CCD defects (see instruments). The bad pixel image is of pixel type short and
+has the value given by the parameter \fBgoodvalue\fR for the good
+pixels and the value given by the parameter \fBbadvalue\fR for the bad pixels.
+The image size and header parameters are taken from the specified
+template image. The bad pixel mask image may be used to view the
+location of the bad pixels and blink against an data image using an
+image display, to mask or flag bad pixels later by image arithmetic,
+and to propagate the positions of the bad pixels through the
+reductions.
+.ih
+EXAMPLES
+1. To make a bad pixel mask image from the bad pixel file "cryocambp.dat"
+using the image "ccd005" as the template:
+
+ cl> badpiximage cryocambp.dat ccd005 cryocambp
+
+2. To make the bad pixel mask image with good values of 0 and bad values of 1:
+
+ cl> badpixim cryomapbp.dat ccd005 cryocambp good=0 bad=1
+.ih
+SEE ALSO
+ccdproc, instruments
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdgeometry.hlp b/noao/imred/quadred/src/quad/doc/ccdgeometry.hlp
new file mode 100644
index 00000000..c01a09c8
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdgeometry.hlp
@@ -0,0 +1,70 @@
+.help ccdgeometry Sep87 noao.imred.ccdred
+.ih
+NAME
+ccdgeometry - Discussion of CCD geometry and header parameters
+.ih
+DESCRIPTION
+The \fBccdred\fR package maintains and updates certain geometry
+information about the images. This geometry is described by four image
+header parameters which may be present. These are defined below by the
+parameter names used in the package. Note that these names may be
+different in the image header using the image header translation
+feature of the package.
+
+.ls DATASEC
+The section of the image containing the CCD data. If absent the
+entire image is assumed to be data. Only the pixels within the
+data section are modified during processing. Therefore, there may be
+additional calibration or observation information in the image.
+If after processing, the data section is the entire image it is
+not recorded in the image header.
+.le
+.ls CCDSEC
+The section of the CCD to corresponding to the data section. This
+refers to the physical format, columns and lines, of the detector. This is
+the coordinate system used during processing to relate calibration
+data to the image data; i.e. image data pixels are calibrated by
+calibration pixels at the same CCD coordinates regardless of image pixel
+coordinates. This allows recording only parts of the CCD during data
+taking and calibrating with calibration frames covering some or all of
+the CCD. The CCD section is maintained during trimming operations.
+Note that changing the format of the images by image operators outside
+of the \fBccdred\fR package will invalidate this coordinate system.
+The size of the CCD section must agree with that of the data section.
+If a CCD section is absent then it defaults to the data section such
+that the first pixel of the data section has CCD coordinate (1,1).
+.le
+.ls BIASSEC
+The section of the image containing prescan or overscan bias information.
+It consists of a strip perpendicular to the readout axis. There may be
+both a prescan and overscan but the package currently only uses one.
+This parameter may be overridden during processing by the parameter
+\fIccdproc.biassec\fR.
+.le
+.ls TRIMSEC
+The section of the image extracted during processing when the trim
+operation is selected (\fIccdproc.trim\fR). If absent when the trim
+operation is selected it defaults to the data section; i.e. the processed
+image consists only of the data section. This parameter may be overridden
+during processing by the parameter \fIccdproc.trimsec\fR. After trimming
+this parameter, if present, is removed from the image header. The
+CCD section, data section, and bias section parameters are also modified
+by trimming.
+.le
+
+The geometry is as follows. When a CCD image is recorded it consists
+of a data section corresponding to part or all of the CCD detector.
+Regions outside of the data section may contain additional information
+which are not affected except by trimming. Most commonly this consists
+of prescan and overscan bias data. When recording only part of the
+full CCD detector the package maintains information about that part and
+correctly applies calibrations for that part of the detector. Also any
+trimming operation updates the CCD coordinate information. If the
+images include the data section, bias section, trim section, and ccd
+section the processing may be performed entirely automatically.
+
+The sections are specified using the notation [c1:c2,l1:l2] where c1
+and c2 are the first and last columns and l1 and l2 are the first and
+last lines. Currently c1 and l1 must be less than c2 and l2
+respectively and no subsampling is allowed. This may be added later.
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdgroups.hlp b/noao/imred/quadred/src/quad/doc/ccdgroups.hlp
new file mode 100644
index 00000000..48c29b99
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdgroups.hlp
@@ -0,0 +1,163 @@
+.help ccdgroups Jun87 noao.imred.ccdred
+.ih
+NAME
+ccdgroups -- Group CCD images into image lists
+.ih
+USAGE
+ccdgroups images output
+.ih
+PARAMETERS
+.ls images
+List of CCD images to be grouped.
+.le
+.ls output
+Output root group filename. The image group lists will be put in files
+with this root name followed by a number.
+.le
+.ls group = "ccdtype"
+Group type. There are currently four grouping types:
+.ls ccdtype
+Group by CCD image type.
+.le
+.ls subset
+Group by subset parameter.
+.le
+.ls position
+Group by position in right ascension (in hours) and declination (in degrees).
+The groups are defined by a radius parameter (in arc seconds).
+.le
+.ls title
+Group by identical titles.
+.le
+.ls date
+Group by identical dates.
+.le
+.le
+.ls radius = 60.
+Grouping radius when grouping by positions. This is given in arc seconds.
+.le
+.ls ccdtype = ""
+CCD image types to select from the input image list. If null ("") then
+all image types are used.
+.le
+.ih
+DESCRIPTION
+The input images, possible restricted to a particular CCD image type,
+are grouped into image lists. The "ccdtype" or "subset" groups
+produce output image lists with the given root name and the CCD type
+or subset as an extension (without a period). For the other group
+types the
+image lists have file names given by
+the root output name and a numeric extension (without a period).
+If the package parameter \fIccdred.verbose\fR is yes then the
+image name and output group list is printed for each image. The image lists can
+be used with the @ list feature for processing separate groups of observations.
+Note that grouping by CCD image type and subset is often not necessary since
+the \fBccdred\fR tasks automatically use this information (see
+\fBccdtypes\fR and \fBsubsets\fR).
+
+Besides CCD image type and subsets there are currently three ways to
+group images. These are by position in the sky, by title, and by
+date. Further groups may be added as suggested. The title grouping is
+useful if consistent titles are used when taking data. The date
+grouping is useful if multiple nights of observations are not organized
+by directories (it is recommended that data from separate nights be
+kept in separate directories). The position grouping finds
+observations within a given radius on the sky of the first member of
+the group (this is not a clustering algorithm). The right ascension
+and declination coordinates must be in standard units, hours and
+degrees respectively. The grouping radius is in arc seconds. This
+grouping type is useful for making sets of data in which separate
+calibration images are taken at each position.
+
+The date, title, and coordinates are accessed through the instrument
+translation file. The standard names used are "date-obs", "title", "ra",
+and "dec".
+.ih
+EXAMPLES
+1. For each object 5 exposures were taken to be combined in order to remove
+cosmic rays. If the titles are the same then (with ccdred.verbose=yes):
+
+.nf
+ cl> ccdgroups *.imh group group=title ccdtype=object
+ ccd005.imh --> group1
+ ccd006.imh --> group1
+ ccd007.imh --> group1
+ ccd008.imh --> group1
+ ccd009.imh --> group1
+ ccd012.imh --> group2
+ ccd013.imh --> group2
+ ccd014.imh --> group2
+ ccd015.imh --> group2
+ ccd016.imh --> group2
+ [... etc ...]
+ cl> combine @group1 obj1 proc+
+ cl> combine @group2 obj2 proc+
+ [... etc ...]
+.fi
+
+Note the numeric suffixes to the output root name "group".
+
+2. CCD observations were made in groups with a flat field, the object, and
+a comparison spectrum at each position. To group and process this data:
+
+.nf
+ cl> ccdgroups *.imh obs group=position >> logfile
+ cl> ccdproc @obs1
+ cl> ccdproc @obs2
+ cl> ccdproc @obs3
+.fi
+
+Since no flat field is specified for the parameter \fIccdproc.flat\fR
+the flat field is taken from the input image list.
+
+3. If for some reason you want to group by date and position it is possible
+to use two steps.
+
+.nf
+ cl> ccdgroups *.imh date group=date
+ cl> ccdgroups @data1 pos1
+ cl> ccdgroups @data2 pos2
+.fi
+
+4. To get groups by CCD image type:
+
+.nf
+ cl> ccdgroups *.imh "" group=ccdtype
+ ccd005.imh --> zero
+ ccd006.imh --> zero
+ ccd007.imh --> zero
+ ccd008.imh --> dark
+ ccd009.imh --> flat
+ ccd012.imh --> flat
+ ccd013.imh --> object
+ ccd014.imh --> object
+ ccd015.imh --> object
+ ccd016.imh --> object
+ [... etc ...]
+.fi
+
+Note the use of a null root name and the extension is the standard
+CCDRED types (not necessarily those used in the image header).
+
+5. To get groups by subset:
+
+.nf
+ cl> ccdgroups *.imh filt group=subset
+ ccd005.imh --> filt
+ ccd006.imh --> filtB
+ ccd007.imh --> filtB
+ ccd008.imh --> filtB
+ ccd009.imh --> filtV
+ ccd012.imh --> filtV
+ ccd013.imh --> filtV
+ ccd014.imh --> filtB
+ ccd015.imh --> filtB
+ ccd016.imh --> filtB
+ [... etc ...]
+.fi
+
+.ih
+SEE ALSO
+ccdlist, ccdtypes, instruments, subsets
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdhedit.hlp b/noao/imred/quadred/src/quad/doc/ccdhedit.hlp
new file mode 100644
index 00000000..1bc27d29
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdhedit.hlp
@@ -0,0 +1,108 @@
+.help ccdhedit Jun87 noao.imred.ccdred
+.ih
+NAME
+ccdhedit -- CCD image header editor
+.ih
+USAGE
+ccdhedit images parameter value
+.ih
+PARAMETERS
+.ls images
+List of CCD images to be edited.
+.le
+.ls parameter
+Image header parameter. The image header parameter will be translated by
+the header translation file for the images.
+.le
+.ls value
+The parameter value. If the null string ("") is specified then the
+parameter is deleted from the image header, otherwise it is added or
+modified. If the parameter is "imagetyp" then the value string giving
+the CCD image type is translated from the package CCD type to the
+instrument specific string.
+.le
+.ls type = "string"
+The parameter type. The parameter types are "string", "real", or "integer".
+.le
+.ih
+DESCRIPTION
+The image headers of the specified CCD images are edited to add, modify,
+or delete a parameter. The parameters may be those used by the \fBccdred\fR
+package. The parameter name is translated to an image header parameter by the
+instrument translation file (see \fBinstruments\fR) if a translation is
+given. Otherwise the parameter is that in the image header. If the parameter
+is "imagetyp" the parameter value for the CCD image type may be that
+used by the package; i.e. dark, object, flat, etc. The value string will be
+translated to the instrument image string in this case. The translation
+facility allows use of this task in an instrument independent way.
+
+The value string is used to determine whether to delete or modify the
+image parameter. If the null string, "", is given the specified parameter
+is deleted. If parameters are added the header type must be specified
+as a string, real, or integer parameter. The numeric types convert the
+value string to a number.
+.ih
+EXAMPLES
+The \fBccdred\fR package is usable even with little image header information.
+However, if desired the header information can be added to images which
+lack it. In all the examples the parameters used are those of the package
+and apply equally well to any image header format provided there is an
+instrument translation file.
+
+.nf
+1. cl> ccdhedit obj* imagetyp object
+2. cl> ccdhedit flat* imagetyp flat
+3. cl> ccdhedit zero* imagetyp zero
+4. cl> ccdhedit obj0![1-3]* subset "V filter"
+5. cl> ccdhedit obj0![45]* subset "R filter"
+6. cl> ccdhedit flat001 subset "R filter"
+7. cl> ccdhedit obj* exptime 500 type=integer
+.fi
+
+8. The following is an example of a CL script which sets the CCD image type,
+the subset, and the exposure time simultaneously. The user may expand
+on this example to include other parameters or other initialization
+operations.
+
+.nf
+ cl> edit ccdheader.cl
+
+ ----------------------------------------------------------------
+ # Program to set CCD header parameters.
+
+ procedure ccdheader (images)
+
+ string images {prompt="CCD images"}
+ string imagetyp {prompt="CCD image type"}
+ string subset {prompt="CCD subset"}
+ string exptime {prompt="CCD exposure time"}
+
+ begin
+ string ims
+
+ ims = images
+ ccdhedit (ims, "imagetyp", imagetyp, type="string")
+ ccdhedit (ims, "subset", subset, type="string")
+ ccdhedit (ims, "exptime", exptime, type="real")
+ end
+ ----------------------------------------------------------------
+
+ cl> task ccdheader=ccdheader.cl
+ cl> ccdheader obj* imagetyp=object subset="V" exptime=500
+.fi
+
+9. The image header may be changed to force processing a calibration image
+as an object. For example to flatten a flat field:
+
+.nf
+ cl> ccdhedit testflat imagetyp other
+ cl> ccdproc testflat
+.fi
+
+10. To delete processing flags:
+
+ cl> ccdhedit obj042 flatcor ""
+.ih
+SEE ALSO
+hedit, instruments, ccdtypes, subsets
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdinst.hlp b/noao/imred/quadred/src/quad/doc/ccdinst.hlp
new file mode 100644
index 00000000..23ebea60
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdinst.hlp
@@ -0,0 +1,389 @@
+.help ccdinstrument Nov90 noao.imred.ccdred
+.ih
+NAME
+ccdinstrument -- Setup and verify CCD instrument translation files
+.ih
+USAGE
+ccdinstrument images
+.ih
+PARAMETERS
+.ls images
+List of images to be verified or used to setup a CCD instrument translation
+file.
+.le
+.ls instrument = ")_.instrument"
+CCD instrument translation file. The default is to use the translation
+file defined in the \fBccdred\fR package parameters. Note that one would
+need write permission to update this file though the task has a write
+command to save any changes to a different file.
+.le
+.ls ssfile = ")_.ssfile"
+Subset translation file. The default is to use the file defined in
+the \fBccdred\fR package parameters.
+.le
+.ls edit = yes
+Edit the instrument translation file? If "yes" an interactive
+mode is entered allowing translation parameters to be modified while if
+"no" the task is simply used to verify the translations noninteractively.
+.le
+.ls parameters = "basic"
+Parameters to be displayed. The choices are "basic" to display only the
+most basic parameters (those needed for the simplest automation of
+\fBccdred\fR tasks), "common" to display the common parameters used
+by the package (most of these are keywords to be written to the image
+rather than translated), and "all" to display all the parameters
+referenced by the package including the most obscure. For most uses
+the "basic" set is all that is important and the other options are
+included for completeness.
+.le
+.ih
+DESCRIPTION
+The purpose of this task is to provide an interface to simplify setting
+up CCD instrument translation files and to verify the translations
+for a set of images. Before this task was written users who needed to
+set up translation files for new instruments and observatories had
+to directly create the files with an editor. Many people encountered
+difficulties and were prone to errors. Also there was no task that
+directly verified the translations though \fBccdlist\fR provided some
+clues.
+
+The \fBccdred\fR package was designed to make intelligent use of
+information in image headers for determining things such as image
+calibration or object type and exposure times. While the package may
+be used without this capability it is much more convenient to be
+able to use information from the image. The package was also intended
+to be used with many different instruments, detectors, and observatories.
+The key to providing image header access across different observatories
+is the ability to translate the needs of the package to the appropriate
+keywords in the image header. This is done through a file called
+an "instrument translation file". For a complete description of
+this file and other instrument setup features of the package see
+\fBccdred.instruments\fR.
+
+The instrument translation file translates the parameter names used by
+the \fBccdred\fR package into image specific parameters and also
+supplies default values for parameters. The translation proceeds as
+follows. When a package task needs a parameter for an image, for
+example "imagetyp", it looks in the instrument translation file. If
+the file is not found or none is specified then the image header
+keyword that is requested is assumed to have the same name. If an
+instrument translation file is defined then the requested parameter is
+translated to an image header keyword, provided a translation entry is
+given. If no translation is given the package name is used. For
+example the package parameter "imagetyp" might be translated to
+"data-typ" (the old NOAO CCD keyword). If the parameter is not found
+then the default value specified in the translation file, if present,
+is returned.
+
+For recording parameter information in the header, such
+as processing flags, translation is also used. For example, if the
+flag specifying that the image has been corrected by a flat field is to
+be set then the package parameter name "flatcor" might be translated to
+"ff-flag". If no translation is given then the new image header
+parameter is entered as "flatcor".
+
+The CCD image type requires a second level of translation also defined
+in the translation file. Once the image keyword which identifies the
+type of CCD image, for example a flat field or object, is translated
+to an imahe keyword the specific
+string value must be translated to one of the CCD image types used
+by the package. The translation works in the same way, the specific
+string found is translated to the \fBccdred\fR type and returned to
+the task. This translation is tricky in that the exact string
+including all spaces and capitalizations must be correctly defined
+in the translation file. The \fBccdinstrument\fR allows doing
+this automatically thus minimizing typing errors.
+
+The basic display format of the task is a table of five columns
+giving the parameter name used by the package, the image keyword
+to which it is translated, the default value (if any), the value
+the task will receive for the current image after translation,
+and the actual keyword value in the image. A "?" is printed if
+a value cannot be determined. The idea of the task is to make sure
+that the value a \fBccdred\fR task sees is the correct one and if not
+to modify the translation appropriately. In verify mode when the
+\fBedit\fR parameter is not set the translation table is simply
+printed for each input image.
+
+In edit mode the user interactively gives commands at the ccdinstrument
+prompt to display or modify keywords. The modifications can then be
+written to the instrument file or saved in a private copy. The
+list of commands is shown below and may be printed using ? or help.
+
+.in 4
+.nf
+ CCDINSTRUMENT COMMANDS
+
+? Print command summary
+help Print command summary
+imheader Page image header
+instrument Print current instrument translation file
+next Next image
+newimage Select a new image
+quit Quit
+read Read instrument translation file
+show Show current translations
+write Write instrument translation file
+
+translate Translate image string selected by the imagetyp
+ parameter to one of the CCDRED types given as an
+ argument or queried:
+ object, zero, dark, flat, comp, illum, fringe, other
+
+.fi
+The following are CCDRED parameters which may be translated. You are
+queried for the image keyword to use or it may be typed after the command.
+An optional default value (returned if the image does not contain the
+keyword) may be typed as the second argument of the command.
+.nf
+
+ BASIC PARAMETERS
+imagetyp Image type parameter (see also translate)
+subset Subset or filter parameter
+exptime Exposure time
+darktime Dark time (may be same as the exposure time)
+.fi
+.in -4
+
+The commands may be followed by values such as file names for some of
+the general commands or the keyword and default value for the parameters
+to be translated. Note this is the only way to specify a default value.
+If no arguments are given the user is prompted with the current value
+which may then be changed.
+
+The set of parameters shown above are only those considered "basic".
+In order to avoid confusion the task can limit the set of parameters
+displayed. Without going into great detail, it is only the basic
+parameters which are generally required to have valid translations to
+allow the package to work well. However, for completeness, and if someone
+wants to go wild with translations, further parameters may be displayed
+and changed. The parameters displayed is controlled by the \fIparameters\fR
+keyword. The additional parameters not shown above are:
+
+.in 4
+.nf
+ USEFUL DEFAULT GEOMETRY PARAMETERS
+biassec Bias section (often has a default value)
+trimsec Trim section (often has a default value)
+
+ COMMON PROCESSING FLAGS
+fixpix Bad pixel replacement flag
+overscan Overscan correction flag
+trim Trim flag
+zerocor Zero level correction flag
+darkcor Dark count correction flag
+flatcor Flat field correction flag
+
+ RARELY TRANSLATED PARAMETERS
+ccdsec CCD section
+datasec Data section
+fixfile Bad pixel file
+
+fringcor Fringe correction flag
+illumcor Ilumination correction flag
+readcor One dimensional zero level read out correction
+scancor Scan mode correction flag
+
+illumflt Ilumination flat image
+mkfringe Fringe image
+mkillum Iillumination image
+skyflat Sky flat image
+
+ccdmean Mean value
+fringscl Fringe scale factor
+ncombine Number of images combined
+date-obs Date of observations
+dec Declination
+ra Right Ascension
+title Image title
+.fi
+.in -4
+.ih
+EXAMPLES
+1. To verify the translations for a set of images using the default
+translation file:
+
+.nf
+ cl> setinst "" review-
+ cl> ccdinst dev$pix edit-
+ Image: dev$pix
+ Instrument file:
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ --------------------------------
+ imagetyp imagetyp none ?
+ subset subset ?
+ exptime exptime ? ?
+ darktime darktime ? ?
+
+ cl> setinst "" site=kpno dir=ccddb$ review-
+ cl> ccdinst dev$pix edit-
+ Image: dev$pix
+
+ Instrument file: ccddb$kpno/camera.dat
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ --------------------------------
+ imagetyp data-typ object OBJECT (0)
+ subset f1pos 2 2
+ exptime otime 600 600
+ darktime ttime 600 600
+.fi
+
+2. Set up an instrument translation file from scratch.
+
+.nf
+ ccdinst ech???.imh instr=myccd edit+
+ Warning: OPEN: File does not exist (myccd)
+ Image: ech001.imh
+ Instrument file: myccd
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ ------------------------------------------------------
+ imagetyp imagetyp none ?
+ subset subset ?
+ exptime exptime ? ?
+ darktime darktime ? ?
+
+ ccdinstrument> imagetyp
+ Image keyword for image type (imagetyp): ccdtype
+ imagetyp ccdtype unknown BIAS
+ ccdinstrument> translate
+ CCDRED image type for 'BIAS' (unknown): zero
+ imagetyp ccdtype zero BIAS
+ ccdinstrument> subset
+ Image keyword for subset parameter (subset): filters
+ subset filters 1 1 0
+ ccdinstrument> exptime integ
+ exptime integ 0. 0.
+ ccdinstrument> darktime integ
+ darktime integ 0. 0.
+ ccdinstrument> show
+ Image: ech001.imh
+ Instrument file: myccd
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ ------------------------------------------------------
+ imagetyp ccdtype zero BIAS
+ subset filters 1 1 0
+ exptime integ 0. 0.
+ darktime integ 0. 0.
+
+ ccdinstrument> next
+ Image: ech002.imh
+ Instrument file: myccd
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ ------------------------------------------------------
+ imagetyp ccdtype unknown PROJECTOR FLAT
+ subset filters 1 1 0
+ exptime integ 20. 20.
+ darktime integ 20. 20.
+
+ ccdinstrument> trans
+ CCDRED image type for 'PROJECTOR FLAT' (unknown): flat
+ imagetyp ccdtype flat PROJECTOR FLAT
+ ccdinstrument> next
+ Image: ech003.imh
+ Instrument file: myccd
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ ------------------------------------------------------
+ imagetyp ccdtype unknown COMPARISON
+ subset filters 1 1 0
+ exptime integ 300 300
+ darktime integ 300 300
+
+ ccdinstrument> translate comp
+ imagetyp ccdtype comp COMPARISON
+ ccdinstrument> next
+ Image: ech004.imh
+ Instrument file: myccd
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ ------------------------------------------------------
+ imagetyp ccdtype unknown OBJECT
+ subset filters 1 1 0
+ exptime integ 3600 3600
+ darktime integ 3600 3600
+
+ ccdinstrument> translate object
+ imagetyp ccdtype object OBJECT
+ ccdinstrument> inst
+ imagetyp ccdtype
+ BIAS zero
+ subset filters
+ exptime integ
+ darktime integ
+ 'PROJECTOR FLAT' flat
+ COMPARISON comp
+ OBJECT object
+
+ ccdinstrument> next
+ Update instrument file myccd (yes)?
+.fi
+
+3. Set default geometry parameters. Note that to set a default the
+arguments must be on the command line.
+
+.nf
+ cc> ccdinst ech001 instr=myccd param=common edit+
+ Image: ech001
+ Instrument file: myccd
+ Subset file: subsets
+
+ CCDRED IMAGE DEFAULT CCDRED IMAGE
+ PARAM KEYWORD VALUE VALUE VALUE
+ ------------------------------------------------------
+ imagetyp ccdtype zero BIAS
+ subset filters 1 1 0
+ exptime integ 0. 0.
+ darktime integ 0. 0.
+
+ biassec biassec ? ?
+ trimsec trimsec ? ?
+
+ fixpix fixpix no ?
+ overscan overscan no ?
+ trim trim no ?
+ zerocor zerocor no ?
+ darkcor darkcor no ?
+ flatcor flatcor no ?
+
+ ccdinstrument> biassec biassec [803:830,*]
+ biassec biassec [803:830,*] [803:830,*] ?
+ ccdinstrument> trimsec trimsec [2:798,2:798]
+ trimsec trimsec [2:798,2:798] [2:798,2:798] ?
+ ccdinstrument> instr
+ trimsec trimsec [2:798,2:798]
+ biassec biassec [803:830,*]
+ imagetyp ccdtype
+ BIAS zero
+ subset filters
+ exptime integ
+ darktime integ
+ 'PROJECTOR FLAT' flat
+ COMPARISON comp
+ OBJECT object
+
+ ccdinstrument> q
+ Update instrument file myccd (yes)?
+.fi
+.ih
+SEE ALSO
+instruments, setinstrument
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdlist.hlp b/noao/imred/quadred/src/quad/doc/ccdlist.hlp
new file mode 100644
index 00000000..9ce7dfdd
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdlist.hlp
@@ -0,0 +1,133 @@
+.help ccdlist Jun87 noao.imred.ccdred
+.ih
+NAME
+ccdlist -- List CCD processing information
+.ih
+USAGE
+ccdlist images
+.ih
+PARAMETERS
+.ls images
+CCD images to be listed. A subset of the these may be selected using the
+CCD image type parameter.
+.le
+.ls ccdtype = ""
+CCD image type to be listed. If no type is specified then all the images
+are listed. If an image type is specified then only images
+of that type are listed. See \fBccdtypes\fR for a list of the package
+image types.
+.le
+.ls names = no
+List the image names only? Used with the CCD image type parameter to make
+a list of the images of the specified type.
+.le
+.ls long = no
+Long format listing? The images are listed in a long format containing some
+image parameters and the processing history.
+.le
+.ls ccdproc (pset)
+CCD processing parameter set.
+.le
+.ih
+DESCRIPTION
+Information from the specified input images is listed on the standard
+output. A specific CCD image type may be selected from the input
+images by the parameter \fIccdtype\fR. There are three list formats;
+the default one line per image format, an image name only format, and a
+multi-line long format. The default one line format consists of the
+image name, image size, image pixel type, CCD image type, subset ID (if
+defined), processing flags, and title. This format contains the same
+information as that produced by \fBimheader\fR as well as CCD specific
+information. The processing flags identifying the processing operations
+performed on the image are given by the following single letter codes.
+
+.nf
+ B - Bad pixel replacement
+ O - Overscan bias subtraction
+ T - Trimming
+ Z - Zero level subtraction
+ D - Dark count subtraction
+ F - Flat field calibration
+ I - Iillumination correction
+ Q - Fringe correction
+.fi
+
+The long format has the same first line as the default format plus additional
+instrument information such as the exposure time and the full processing
+history. In addition to listing the completed processing, the operations
+not yet done (as specified by the \fBccdproc\fR parameters) are also
+listed.
+
+The image name only format is intended to be used to generate lists of
+images of the same CCD image type. These lists may be used as "@" file
+lists in IRAF tasks.
+.ih
+EXAMPLES
+1. To list the default format for all images:
+
+.nf
+ cl> ccdlist *.imh
+ ccd001.imh[544,512][short][unknown][V]:FOCUS L98-193
+ ccd007.imh[544,512][short][object][V]:N2968 V 600s
+ ccd015.imh[544,512][short][object][B]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R]:N4036 R 600s
+ ccd045.imh[544,512][short][flat][V]:dflat 6v+blue 5s
+ ccd066.imh[544,512][short][flat][B]:dflat 6v+blue 5s
+ ccd103.imh[544,512][short][flat][R]:dflat 6v+blue 5s
+ ccd104.imh[544,512][short][zero][]:bias
+ ccd105.imh[544,512][short][dark][]:dark 3600s
+.fi
+
+These images have not been processed.
+
+2. To restrict the listing to just the object images:
+
+.nf
+ cl> ccdlist *.imh ccdtype=object
+ ccd007.imh[544,512][short][object][V]:N2968 V 600s
+ ccd015.imh[544,512][short][object][B]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R]:N4036 R 600s
+.fi
+
+3. The long list for image "ccd007" is obtained by:
+
+.nf
+ cl> ccdlist ccd007 l+
+ ccd007[544,512][short][object][V]:N2968 R 600s
+ exptime = 200. darktime = 200.
+ [TO BE DONE] Overscan strip is [520:540,*]
+ [TO BE DONE] Trim image section is [3:510,3:510]
+ [TO BE DONE] Flat field correction
+.fi
+
+4. After processing the images have the short listing:
+
+.nf
+ cl> ccdlist *.imh ccdtype=object
+ ccd007.imh[508,508][real][object][V][OTF]:N2968 V 600s
+ ccd015.imh[508,508][real][object][B][OTF]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R][OTF]:N4036 R 600s
+.fi
+
+The processing indicated is overscan subtraction, trimming, and flat fielding.
+
+5. The long listing for "ccd007" after processing is:
+
+.nf
+ cl> ccdlist ccd007 l+
+ ccd007[508,508][real][object][V][OTF]:N2968 R 600s
+ exptime = 200. darktime = 200.
+ Jun 2 18:18 Overscan section is [520:540,*] with mean=481.8784
+ Jun 2 18:18 Trim data section is [3:510,3:510]
+ Jun 2 18:19 Flat field image is FlatV.imh with scale=138.2713
+.fi
+
+6. To make a list file containing all the flat field images:
+
+ cl> ccdlist *.imh ccdtype=flat name+ > flats
+
+This file can be used as an @ file for processing.
+.ih
+SEE ALSO
+ccdtypes ccdgroups
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdproc.hlp b/noao/imred/quadred/src/quad/doc/ccdproc.hlp
new file mode 100644
index 00000000..4be65f73
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdproc.hlp
@@ -0,0 +1,720 @@
+.help ccdproc Oct90 noao.imred.ccdred
+.ih
+NAME
+ccdproc -- Process CCD images
+.ih
+USAGE
+ccdproc images
+.ih
+PARAMETERS
+.ls images
+List of input CCD images to process. The list may include processed
+images and calibration images.
+.le
+.ls ccdtype = ""
+CCD image type to select from the input image list. If no type is given
+then all input images will be selected. The recognized types are described
+in \fBccdtypes\fR.
+.le
+.ls max_cache = 0
+Maximum image caching memory (in Mbytes). If there is sufficient memory
+the calibration images, such as zero level, dark count, and flat fields,
+will be cached in memory when processing many input images. This
+reduces the disk I/O and makes the task run a little faster. If the
+value is zero image caching is not used.
+.le
+.ls noproc = no
+List processing steps only?
+.le
+
+.ce
+PROCESSING SWITCHES
+.ls fixpix = yes
+Fix bad CCD lines and columns by linear interpolation from neighboring
+lines and columns? If yes then a bad pixel file must be specified.
+.le
+.ls overscan = yes
+Apply overscan or prescan bias correction? If yes then the overscan
+image section and the readout axis must be specified.
+.le
+.ls trim = yes
+Trim the image of the overscan region and bad edge lines and columns?
+If yes then the data section must be specified.
+.le
+.ls zerocor = yes
+Apply zero level correction? If yes a zero level image must be specified.
+.le
+.ls darkcor = yes
+Apply dark count correction? If yes a dark count image must be specified.
+.le
+.ls flatcor = yes
+Apply flat field correction? If yes flat field images must be specified.
+.le
+.ls illumcor = no
+Apply iillumination correction? If yes iillumination images must be specified.
+.le
+.ls fringecor = no
+Apply fringe correction? If yes fringe images must be specified.
+.le
+.ls readcor = no
+Convert zero level images to readout correction images? If yes then
+zero level images are averaged across the readout axis to form one
+dimensional zero level readout correction images.
+.le
+.ls scancor = no
+Convert flat field images to scan mode flat field images? If yes then the
+form of scan mode correction is specified by the parameter \fIscantype\fR.
+.le
+
+.ce
+PROCESSING PARAMETERS
+.ls readaxis = "line"
+Read out axis specified as "line" or "column".
+.le
+.ls fixfile
+File describing the bad lines and columns. If "image" is specified then
+the file is specified in the image header or instrument translation file.
+.le
+.ls biassec
+Overscan bias strip image section. If "image" is specified then the overscan
+bias section is specified in the image header or instrument translation file.
+.le
+.ls trimsec
+image section for trimming. If "image" is specified then the trim
+image section is specified in the image header or instrument translation file.
+.le
+.ls zero = ""
+Zero level calibration image. The zero level image may be one or two
+dimensional. The CCD image type and subset are not checked for these
+images and they take precedence over any zero level calibration images
+given in the input list.
+.le
+.ls dark = ""
+Dark count calibration image. The CCD image type and subset are not checked
+for these images and they take precedence over any dark count calibration
+images given in the input list.
+.le
+.ls flat = ""
+Flat field calibration images. The flat field images may be one or
+two dimensional. The CCD image type is not checked for these
+images and they take precedence over any flat field calibration images given
+in the input list. The flat field image with the same subset as the
+input image being processed is selected.
+.le
+.ls illum = ""
+Iillumination correction images. The CCD image type is not checked for these
+images and they take precedence over any iillumination correction images given
+in the input list. The iillumination image with the same subset as the
+input image being processed is selected.
+.le
+.ls fringe = ""
+Fringe correction images. The CCD image type is not checked for these
+images and they take precedence over any fringe correction images given
+in the input list. The fringe image with the same subset as the
+input image being processed is selected.
+.le
+.ls minreplace = 1.
+When processing flat fields, pixel values below this value (after
+all other processing such as overscan, zero, and dark corrections) are
+replaced by this value. This allows flat fields processed by \fBccdproc\fR
+to be certain to avoid divide by zero problems when applied to object
+images.
+.le
+.ls scantype = "shortscan"
+Type of scan format used in creating the CCD images. The modes are:
+.ls "shortscan"
+The CCD is scanned over a number of lines and then read out as a regular
+two dimensional image. In this mode unscanned flat fields are numerically
+scanned to form scanned flat fields comparable to the observations. If
+the flat field calibration images are taken in scanned mode then
+\fIscancor\fR should be no and the processing performed in the same manner
+as in unscanned mode.
+.le
+.ls "longscan"
+In this mode the CCD is clocked and read out continuously to form a long
+strip. Flat fields are averaged across the readout axis to
+form a one dimensional flat field readout correction image. This assumes
+that all recorded image lines are clocked over the entire active area of the
+CCD.
+.le
+.le
+.ls nscan
+Number of scan readout lines used in short scan mode. This parameter is used
+when the scan type is "shortscan".
+.le
+
+
+.ce
+OVERSCAN FITTING PARAMETERS
+.ls interactive = no
+Fit the overscan vector interactively? If yes the overscan vector is fit
+interactively using the \fBicfit\fR package. If no then the fitting parameters
+given below are used.
+.le
+.ls function = "legendre"
+Overscan fitting function. The function types are "legendre" polynomial,
+"chebyshev" polynomial, "spline1" linear spline, and "spline3" cubic
+spline.
+.le
+.ls order = 1
+Number of polynomial terms or spline pieces in the overscan fit.
+.le
+.ls sample = "*"
+Sample points to use in the overscan fit. The string "*" specified all
+points otherwise an \fBicfit\fR range string is used.
+.le
+.ls naverage = 1
+Number of points to average or median to form fitting points. Positive
+numbers specify averages and negative numbers specify medians.
+.le
+.ls niterate = 1
+Number of rejection iterations to remove deviant points from the overscan fit.
+If 0 then no points are rejected.
+.le
+.ls low_reject = 3., high_reject = 3.
+Low and high sigma rejection factors for rejecting deviant points from the
+overscan fit.
+.le
+.ls grow = 0.
+One dimensional growing radius for rejection of neighbors to deviant points.
+.le
+.ih
+DESCRIPTION
+\fBCcdproc\fR processes CCD images to correct and calibrate for
+detector defects, readout bias, zero level bias, dark counts,
+response, iillumination, and fringing. It also trims unwanted
+lines and columns and changes the pixel datatype. It is efficient
+and easy to use; all one has to do is set the parameters and then
+begin processing the images. The task takes care of most of the
+record keeping and automatically does the prerequisite processing
+of calibration images. Beneath this simplicity there is much that
+is going on. In this section a simple description of the usage is
+given. The following sections present more detailed discussions
+on the different operations performed and the order and logic
+of the processing steps. For a user's guide to the \fBccdred\fR
+package see \fBguide\fR. Much of the ease of use derives from using
+information in the image header. If this information is missing
+see section 13.
+
+One begins by setting the task parameters. There are many parameters
+but they may be easily reviewed and modified using the task \fBeparam\fR.
+The input CCD images to be processed are given as an image list.
+Previously processed images are ignored and calibration images are
+recognized, provided the CCD image types are in the image header (see
+\fBinstruments\fR and \fBccdtypes\fR). Therefore it is permissible to
+use simple image templates such as "*.imh". The \fIccdtype\fR parameter
+may be used to select only certain types of CCD images to process
+(see \fBccdtypes\fR).
+
+The processing operations are selected by boolean (yes/no) parameters.
+Because calibration images are recognized and processed appropriately,
+the processing operations for object images should be set.
+Any combination of operations may be specified and the operations are
+performed simultaneously. While it is possible to do operations in
+separate steps this is much less efficient. Two of the operation
+parameters apply only to zero level and flat field images. These
+are used for certain types of CCDs and modes of operation.
+
+The processing steps selected have related parameters which must be
+set. These are things like image sections defining the overscan and
+trim regions and calibration images. There are a number of parameters
+used for fitting the overscan or prescan bias section. These are
+parameters used by the standard IRAF curve fitting package \fBicfit\fR.
+The parameters are described in more detail in the following sections.
+
+In addition to the task parameters there are package parameters
+which affect \fBccdproc\fR. These include the instrument and subset
+files, the text and plot log files, the output pixel datatype,
+the amount of memory available for calibration image caching,
+the verbose parameter for logging to the terminal, and the backup
+prefix. These are described in \fBccdred\fR.
+
+Calibration images are specified by task parameters and/or in the
+input image list. If more than one calibration image is specified
+then the first one encountered is used and a warning is issued for the
+extra images. Calibration images specified by
+task parameters take precedence over calibration images in the input list.
+These images also need not have a CCD image type parameter since the task
+parameter identifies the type of calibration image. This method is
+best if there is only one calibration image for all images
+to be processed. This is almost always true for zero level and dark
+count images. If no calibration image is specified by task parameter
+then calibration images in the input image list are identified and
+used. This requires that the images have CCD image types recognized
+by the package. This method is useful if one may simply say "*.imh"
+as the image list to process all images or if the images are broken
+up into groups, in "@" files for example, each with their own calibration
+frames.
+
+When an input image is processed the task first determines the processing
+parameters and calibration images. If a requested operation has been
+done it is skipped and if all requested operations have been completed then
+no processing takes place. When it determines that a calibration image
+is required it checks for the image from the task parameter and then
+for a calibration image of the proper type in the input list.
+
+Having
+selected a calibration image it checks if it has been processed by
+looking for the image header flag CCDPROC. If it is not present then
+the calibration image is processed. When any image has been processed
+the CCDPROC flag is added. For images processed directly by \fBccdproc\fR
+the individual processing flags are checked even if the CCDPROC flag is
+present. However, the automatic processing of the calibration images is
+only done if the CCDPROC flag is absent! This is to make the task more
+efficient by not having to check every flag for every calibration image
+for every input image. Thus, if additional processing
+steps are added after images have been partially reduced then input images
+will be processed for the new steps but calibration images will not be
+processed automatically.
+
+After the calibration images have been identified, and processed if
+necessary, the images may be cached in memory. This is done when there
+are more than two input images (it is actually less efficient to
+cache the calibration images for one or two input images) and the parameter
+\fImax_cache\fR is greater than zero. When caching, as many calibration
+images as allowed by the specified memory are read into memory and
+kept there for all the input images. Cached images are, therefore,
+only read once from disk which reduces the amount of disk I/O. This
+makes a modest decrease in the execution time. It is not dramatic
+because the actual processing is fairly CPU intensive.
+
+Once the processing parameters and calibration images have been determined
+the input image is processed for all the desired operations in one
+step; i.e. there are no intermediate results or images. This makes
+the task efficient. The corrected image is output as a temporary image
+until the entire image has been processed. When the image has been
+completely processed then the original image is deleted (or renamed
+using the specified backup prefix) and the corrected image replaces
+the original image. Using a temporary image protects the data in the
+event of an abort or computer failure. Keeping the original image name
+eliminates much of the record keeping and the need to generate new
+image names.
+.sh
+1. Fixpix
+Regions of bad lines and columns may be replaced by linear
+interpolation from neighboring lines and columns when the parameter
+\fIfixpix\fR is set. The bad regions are specified in a bad pixel
+file. The file consists of lines with four fields, the starting and
+ending columns and the starting and ending lines. Any number of
+regions may be specified. Comment lines beginning with the character
+'#' may be included. If a comment line preceding the bad regions
+contains the word "untrimmed" then the coordinate system refers to the
+original format of the images; i.e. before trimming. If an image has
+been trimmed previously then the trim region specified in the image
+header is used to convert the coordinates in the bad pixel file to
+those of the trimmed image. If the file does not contain the word
+"untrimmed" then the coordinate system must match that of the image
+being corrected; i.e. untrimmed coordinates if the image has not been
+trimmed and trimmed coordinates if the image has been trimmed.
+Standard bad pixel files should always be specified in terms of the
+original format.
+
+The bad pixel file may be specified explicitly with the parameter \fIfixfile\fR
+or indirectly if the parameter has the value "image". In the latter case
+the instrument file must contain the name of the file.
+.sh
+2. Overscan
+If an overscan or prescan correction is specified (\fIoverscan\fR
+parameter) then the image section (\fIbiassec\fR parameter) is averaged
+along the readout axis (\fIreadaxis\fR parameter) to form a
+correction vector. A function is fit to this vector and for each readout
+line (image line or column) the function value for that line is
+subtracted from the image line. The fitting function is generally
+either a constant (polynomial of 1 term) or a high order function
+which fits the large scale shape of the overscan vector. Bad pixel
+rejection is also used to eliminate cosmic ray events. The function
+fitting may be done interactively using the standard \fBicfit\fR
+iteractive graphical curve fitting tool. Regardless of whether the fit
+is done interactively, the overscan vector and the fit may be recorded
+for later review in a metacode plot file named by the parameter
+\fIccdred.plotfile\fR. The mean value of the bias function is also recorded in
+the image header and log file.
+.sh
+3. Trim
+When the parameter \fItrim\fR is set the input image will be trimmed to
+the image section given by the parameter \fItrimsec\fR. This trim
+should, of course, be the same as that used for the calibration images.
+.sh
+4. Zerocor
+After the readout bias is subtracted, as defined by the overscan or prescan
+region, there may still be a zero level bias. This level may be two
+dimensional or one dimensional (the same for every readout line). A
+zero level calibration is obtained by taking zero length exposures;
+generally many are taken and combined. To apply this zero
+level calibration the parameter \fIzerocor\fR is set. In addition if
+the zero level bias is only readout dependent then the parameter \fIreadcor\fR
+is set to reduce two dimensional zero level images to one dimensional
+images. The zero level images may be specified by the parameter \fIzero\fR
+or given in the input image list (provided the CCD image type is defined).
+
+When the zero level image is needed to correct an input image it is checked
+to see if it has been processed and, if not, it is processed automatically.
+Processing of zero level images consists of bad pixel replacement,
+overscan correction, trimming, and averaging to one dimension if the
+readout correction is specified.
+.sh
+5. Darkcor
+Dark counts are subtracted by scaling a dark count calibration image to
+the same exposure time as the input image and subtracting. The
+exposure time used is the dark time which may be different than the
+actual integration or exposure time. A dark count calibration image is
+obtained by taking a very long exposure with the shutter closed; i.e.
+an exposure with no light reaching the detector. The dark count
+correction is selected with the parameter \fIdarkcor\fR and the dark
+count calibration image is specified either with the parameter
+\fIdark\fR or as one of the input images. The dark count image is
+automatically processed as needed. Processing of dark count images
+consists of bad pixel replacement, overscan and zero level correction,
+and trimming.
+.sh
+6. Flatcor
+The relative detector pixel response is calibrated by dividing by a
+scaled flat field calibration image. A flat field image is obtained by
+exposure to a spatially uniform source of light such as an lamp or
+twilight sky. Flat field images may be corrected for the spectral
+signature in spectroscopic images (see \fBresponse\fR and
+\fBapnormalize\fR), or for iillumination effects (see \fBmkillumflat\fR
+or \fBmkskyflat\fR). For more on flat fields and iillumination corrections
+see \fBflatfields\fR. The flat field response is dependent on the
+wavelength of light so if different filters or spectroscopic wavelength
+coverage are used a flat field calibration for each one is required.
+The different flat fields are automatically selected by a subset
+parameter (see \fBsubsets\fR).
+
+Flat field calibration is selected with the parameter \fBflatcor\fR
+and the flat field images are specified with the parameter \fBflat\fR
+or as part of the input image list. The appropriate subset is automatically
+selected for each input image processed. The flat field image is
+automatically processed as needed. Processing consists of bad pixel
+replacement, overscan subtraction, zero level subtraction, dark count
+subtraction, and trimming. Also if a scan mode is used and the
+parameter \fIscancor\fR is specified then a scan mode correction is
+applied (see below). The processing also computes the mean of the
+flat field image which is used later to scale the flat field before
+division into the input image. For scan mode flat fields the ramp
+part is included in computing the mean which will affect the level
+of images processed with this flat field. Note that there is no check for
+division by zero in the interest of efficiency. If division by zero
+does occur a fatal error will occur. The flat field can be fixed by
+replacing small values using a task such as \fBimreplace\fR or
+during processing using the \fIminreplace\fR parameter. Note that the
+\fIminreplace\fR parameter only applies to flat fields processed by
+\fBccdproc\fR.
+.sh
+7. Illumcor
+CCD images processed through the flat field calibration may not be
+completely flat (in the absence of objects). In particular, a blank
+sky image may still show gradients. This residual nonflatness is called
+the iillumination pattern. It may be introduced even if the detector is
+uniformly illuminated by the sky because the flat field lamp
+iillumination may be nonuniform. The iillumination pattern is found from a
+blank sky, or even object image, by heavily smoothing and rejecting
+objects using sigma clipping. The iillumination calibration image is
+divided into the data being processed to remove the iillumination
+pattern. The iillumination pattern is a function of the subset so there
+must be an iillumination correction image for each subset to be
+processed. The tasks \fBmkillumcor\fR and \fBmkskycor\fR are used to
+create the iillumination correction images. For more on iillumination
+corrections see \fBflatfields\fR.
+
+An alternative to treating the iillumination correction as a separate
+operation is to combine the flat field and iillumination correction
+into a corrected flat field image before processing the object
+images. This will save some processing time but does require creating
+the flat field first rather than correcting the images at the same
+time or later. There are two methods, removing the large scale
+shape of the flat field and combining a blank sky image iillumination
+with the flat field. These methods are discussed further in the
+tasks which create them; \fBmkillumcor\fR and \fBmkskycor\fR.
+.sh
+8. Fringecor
+There may be a fringe pattern in the images due to the night sky lines.
+To remove this fringe pattern a blank sky image is heavily smoothed
+to produce an iillumination image which is then subtracted from the
+original sky image. The residual fringe pattern is scaled to the
+exposure time of the image to be fringe corrected and then subtracted.
+Because the intensity of the night sky lines varies with time an
+additional scaling factor may be given in the image header.
+The fringe pattern is a function of the subset so there must be
+a fringe correction image for each subset to be processed.
+The task \fBmkfringecor\fR is used to create the fringe correction images.
+.sh
+9. Readcor
+If a zero level correction is desired (\fIzerocor\fR parameter)
+and the parameter \fIreadcor\fR is yes then a single zero level
+correction vector is applied to each readout line or column. Use of a
+readout correction rather than a two dimensional zero level image
+depends on the nature of the detector or if the CCD is operated in
+longscan mode (see below). The readout correction is specified by a
+one dimensional image (\fIzero\fR parameter) and the readout axis
+(\fIreadaxis\fR parameter). If the zero level image is two dimensional
+then it is automatically processed to a one dimensional image by
+averaging across the readout axis. Note that this modifies the zero
+level calibration image.
+.sh
+10. Scancor
+CCD detectors may be operated in several modes in astronomical
+applications. The most common is as a direct imager where each pixel
+integrates one point in the sky or spectrum. However, the design of most CCD's
+allows the sky to be scanned across the CCD while shifting the
+accumulating signal at the same rate. \fBCcdproc\fR provides for two
+scanning modes called "shortscan" and "longscan". The type of scan
+mode is set with the parameter \fIscanmode\fR.
+
+In "shortscan" mode the detector is scanned over a specified number of
+lines (not necessarily at sideral rates). The lines that scroll off
+the detector during the integration are thrown away. At the end of the
+integration the detector is read out in the same way as an unscanned
+observation. The advantage of this mode is that the small scale flat
+field response is averaged in one dimension over the number of lines
+scanned. A flat field may be observed in the same way in which case
+there is no difference in the processing from unscanned imaging and the
+parameter \fIscancor\fR should be no. However, one obtains an increase
+in the statistical accuracy of the flat fields if they are not scanned
+during the observation but digitally scanned during the processing. In
+shortscan mode with \fIscancor\fR set to yes, flat field images are
+digitally scanned, if needed, by the specified number of scan lines
+(\fInscan\fR parameter).
+
+In "longscan" mode the detector is continuously read out to produce
+an arbitrarily long strip. Provided data which has not passed over
+the entire detector is thrown away, the flat field corrections will
+be one dimensional. If \fIscancor\fR is specified and the
+scan mode is "longscan" then a one dimensional flat field correction
+will be applied. If the specified flat field (\fIflat\fR parameter)
+is a two dimensional image then when the flat field image is processed
+it will be averaged across the readout axis to form a one dimensional
+correction image.
+.sh
+11. Processing Steps
+The following describes the steps taken by the task. This detailed
+outline provides the most detailed specification of the task.
+
+.ls 5 (1)
+An image to be processed is first checked that it is of the specified
+CCD image type. If it is not the desired type then go on to the next image.
+.le
+.ls (2)
+A temporary output image is created of the specified pixel data type
+(\fBccdred.pixeltype\fR). The header parameters are copied from the
+input image.
+.le
+.ls (3)
+If trimming is specified and the image has not been trimmed previously,
+the trim section is determined.
+.le
+.ls (4)
+If bad pixel replacement is specified and this has not been done
+previously, the bad pixel file is determined either from the task
+parameter or the instrument translation file. The bad pixel regions
+are read. If the image has been trimmed previously and the bad pixel
+file contains the word "untrimmed" then the bad pixel coordinates are
+translated to those of the trimmed image.
+.le
+.ls (5)
+If an overscan correction is specified and this correction has not been
+applied, the overscan section is averaged along the readout axis. If
+trimming is to be done the overscan section is trimmed to the same
+limits. A function is fit either interactively or noninteractively to
+the overscan vector. The function is used to produce the overscan
+vector to be subtracted from the image. This is done in real
+arithmetic.
+.le
+.ls (6)
+If the image is a zero level image go to processing step 12.
+If a zero level correction is desired and this correction has not been
+performed, find the zero level calibration image. If the zero level
+calibration image has not been processed it is processed at this point.
+This is done by going to processing step 1 for this image. After the
+calibration image has been processed, processing of the input image
+continues from this point.
+The processed calibration image may be
+cached in memory if it has not been previously and if there is enough memory.
+.le
+.ls (7)
+If the image is a dark count image go to processing step 12.
+If a dark count correction is desired and this correction has not been
+performed, find the dark count calibration image. If the dark count
+calibration image has not been processed it is processed at this point.
+This is done by going to processing step 1 for this image. After the
+calibration image has been processed, processing of the input image
+continues from this point. The ratio of the input image dark time
+to the dark count image dark time is determined to be multiplied with
+each pixel of the dark count image before subtracting from the input
+image.
+The processed calibration image may be
+cached in memory if it has not been previously and if there is enough memory.
+.le
+.ls (8)
+If the image is a flat field image go to processing step 12. If a flat
+field correction is desired and this correction has not been performed,
+find the flat field calibration image of the appropriate subset. If
+the flat field calibration image has not been processed it is processed
+at this point. This is done by going to processing step 1 for this
+image. After the calibration image has been processed, processing of
+the input image continues from this point. The mean of the image
+is determined from the image header to be used for scaling. If no
+mean is found then a unit scaling is used.
+The processed calibration image may be
+cached in memory if it has not been previously and if there is enough memory.
+.le
+.ls (9)
+If the image is an iillumination image go to processing step 12. If an
+iillumination correction is desired and this correction has not been performed,
+find the iillumination calibration image of the appropriate subset.
+The iillumination image must have the "mkillum" processing flag or the
+\fBccdproc\fR will abort with an error. The mean of the image
+is determined from the image header to be used for scaling. If no
+mean is found then a unit scaling is used. The processed calibration
+image may be
+cached in memory if it has not been previously and there is enough memory.
+.le
+.ls (10)
+If the image is a fringe image go to processing step 12. If a fringe
+correction is desired and this correction has not been performed,
+find the fringe calibration image of the appropriate subset.
+The iillumination image must have the "mkfringe" processing flag or the
+\fBccdproc\fR will abort with an error. The ratio of the input
+image exposure time to the fringe image exposure time is determined.
+If there is a fringe scaling in the image header then this factor
+is multiplied by the exposure time ratio. This factor is used
+for scaling. The processed calibration image may be
+cached in memory if it has not been previously and there is enough memory.
+.le
+.ls (11)
+If there are no processing operations flagged, delete the temporary output
+image, which has been opened but not used, and go to 14.
+.le
+.ls (12)
+The input image is processed line by line with trimmed lines ignored.
+A line of the input image is read. Bad pixel replacement and trimming
+is applied to the image. Image lines from the calibration images
+are read from disk or the image cache. If the calibration is one
+dimensional (such as a readout zero
+level correction or a longscan flat field correction) then the image
+vector is read only once. Note that IRAF image I/O is buffered for
+efficiency and accessing a line at a time does not mean that image
+lines are read from disk a line at a time. Given the input line, the
+calibration images, the overscan vector, and the various scale factors
+a special data path for each combination of corrections is used to
+perform all the processing in the most efficient manner. If the
+image is a flat field any pixels less than the \fIminreplace\fR
+parameter are replaced by that minimum value. Also a mean is
+computed for the flat field and stored as the CCDMEAN keyword.
+.le
+.ls (13)
+The input image is deleted or renamed to a backup image. The temporary
+output image is renamed to the input image name.
+.le
+.ls (14)
+If the image is a zero level image and the readout correction is specified
+then it is averaged to a one dimensional readout correction.
+.le
+.ls (15)
+If the image is a flat field image and the scan mode correction is specified
+then the correction is applied. For shortscan mode a
+modified two dimensional image is produced while for longscan mode a
+one dimensional average image is produced.
+.le
+.ls (16)
+The processing is completed and either the next input image is processed
+beginning at step 1 or, if it is a calibration image which is being
+processed for an input image, control returns to the step which initiated
+the calibration image processing.
+.le
+.sh
+12. Processing Arithmetic
+The \fBccdproc\fR task has two data paths, one for real image pixel datatypes
+and one for short integer pixel datatype. In addition internal arithmetic
+is based on the rules of FORTRAN. For efficiency there is
+no checking for division by zero in the flat field calibration.
+The following rules describe the processing arithmetic and data paths.
+
+.ls (1)
+If the input, output, or any calibration image is of type real the
+real data path is used. This means all image data is converted to
+real on input. If all the images are of type short all input data
+is kept as short integers. Thus, if all the images are of the same type
+there is no datatype conversion on input resulting in greater
+image I/O efficiency.
+.le
+.ls (2)
+In the real data path the processing arithmetic is always real and,
+if the output image is of short pixel datatype, the result
+is truncated.
+.le
+.ls (3)
+The overscan vector and the scale factors for dark count, flat field,
+iillumination, and fringe calibrations are always of type real. Therefore,
+in the short data path any processing which includes these operations
+will be coerced to real arithmetic and the result truncated at the end
+of the computation.
+.le
+.sh
+13. In the Absence of Image Header Information
+The tasks in the \fBccdred\fR package are most convenient to use when
+the CCD image type, subset, and exposure time are contained in the
+image header. The ability to redefine which header parameters contain
+this information makes it possible to use the package at many different
+observatories (see \fBinstruments\fR). However, in the absence of any
+image header information the tasks may still be used effectively.
+There are two ways to proceed. One way is to use \fBccdhedit\fR
+to place the information in the image header.
+
+The second way is to specify the processing operations more explicitly
+than is needed when the header information is present. The parameter
+\fIccdtype\fR is set to "" or to "none". The calibration images are
+specified explicitly by task parameter since they cannot be recognized
+in the input list. Only one subset at a time may be processed.
+
+If dark count and fringe corrections are to be applied the exposure
+times must be added to all the images. Alternatively, the dark count
+and fringe images may be scaled explicitly for each input image. This
+works because the exposure times default to 1 if they are not given in
+the image header.
+.ih
+EXAMPLES
+The user's \fBguide\fR presents a tutorial in the use of this task.
+
+1. In general all that needs to be done is to set the task parameters
+and enter
+
+ cl> ccdproc *.imh &
+
+This will run in the background and process all images which have not
+been processed previously.
+.ih
+TIME REQUIREMENTS
+.nf
+o SUN-3, 15 MHz 68020 with 68881 floating point hardware (no FPA)
+o 8 Mb RAM, 2 Fuji Eagle disks.
+o Input images = 544 x 512 short
+o Output image = 500 x 500 real
+o Operations are overscan subtraction (O), trimming to 500x500 (T),
+ zero level subtraction (Z), dark count scaling and subtraction (D),
+ and flat field scaling and subtraction (F).
+o UNIX statistics
+ (user, system, and clock time, and misc. memory and i/o statistics):
+
+[OTF] One calibration image and 9 object images:
+No caching: 110.6u 25.5s 3:18 68% 28+ 40K 3093+1645io 9pf+0w
+Caching: 111.2u 23.0s 2:59 74% 28+105K 2043+1618io 9pf+0w
+
+[OTZF] Two calibration images and 9 object images:
+No caching: 119.2u 29.0s 3:45 65% 28+ 50K 4310+1660io 9pf+0w
+Caching: 119.3u 23.0s 3:07 75% 28+124K 2179+1601io 9pf+0w
+
+[OTZDF] Three calibration images and 9 object images:
+No caching: 149.4u 31.6s 4:41 64% 28+ 59K 5501+1680io 19pf+0w
+Caching: 151.5u 29.0s 4:14 70% 27+227K 2346+1637io 148pf+0w
+
+[OTZF] 2 calibration images and 20 images processed:
+No caching: 272.7u 63.8u 8:47 63% 28+ 50K 9598+3713io 12pf+0w
+Caching: 271.2u 50.9s 7:00 76% 28+173K 4487+3613io 51pf+0w
+.fi
+.ih
+SEE ALSO
+.nf
+instruments, ccdtypes, flatfields, icfit, ccdred, guide, mkillumcor,
+mkskycor, mkfringecor
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdred.hlp b/noao/imred/quadred/src/quad/doc/ccdred.hlp
new file mode 100644
index 00000000..0300bd38
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdred.hlp
@@ -0,0 +1,98 @@
+.help package Jun87 noao.imred
+.ih
+NAME
+ccdred -- CCD image reduction package
+.ih
+USAGE
+ccdred
+.ih
+PARAMETERS
+.ls pixeltype = "real real"
+Output pixel datatype and calculation datatype. When images are processed
+or created the output pixel datatype is determined by this parameter.
+The allowed types are "short" for short integer, and "real" for real
+floating point. Note that if short input images are processed into
+real images the disk space required will generally increase.
+The calculation datatypes are also short and real with a default of
+real if none is specified.
+.le
+.ls verbose = no
+Print log information to the standard output?
+.le
+.ls logfile = "logfile"
+Text log file. If no filename is specified then no log file is kept.
+.le
+.ls plotfile = ""
+Log metacode plot file for the overscan bias vector fits. If
+no filename is specified then no metacode plot file is kept.
+.le
+.ls backup = ""
+Backup prefix for backup images. If no prefix is specified then no backup
+images are kept when processing. If specified then the backup image
+has the specified prefix.
+.le
+.ls instrument = ""
+CCD instrument translation file. This is usually set with \fBsetinstrument\fR.
+.le
+.ls ssfile = "subsets"
+Subset translation file used to define the subset identifier. See
+\fBsubsets\fR for more.
+.le
+.ls graphics = "stdgraph"
+Interactive graphics output device when fitting the overscan bias vector.
+.le
+.ls cursor = ""
+Graphics cursor input. The default is the standard graphics cursor.
+.le
+.ls version = "June 1987"
+Package version.
+.le
+.ih
+DESCRIPTION
+The CCD reduction package is loaded when this command is entered. The
+package contains parameters which affect the operation of the tasks
+it defines. When images are processed or new image are created the
+output pixel datatype is that specified by the parameter \fBpixeltype\fR.
+Note that CCD processing replaces the original image by the processed
+image so the pixel type of the CCD images may change during processing.
+It is unlikely that real images will be processed to short images but
+the reverse is quite likely. Processing images from short to real
+pixel datatypes will generally increase the amount of disk space
+required (a factor of 2 on most computers).
+
+The tasks produce log output which may be printed on the standard
+output (the terminal unless redirected) and appended to a file. The
+parameter \fIverbose\fR determines whether processing information
+is printed. This may be desirable initially, but when using background
+jobs the verbose output should be turned off. The user may look at
+the end of the log file (for example with \fBtail\fR) to determine
+the status of the processing.
+
+The package was designed to work with data from many different observatories
+and instruments. In order to accomplish this an instrument translation
+file is used to define a mapping between the package parameters and
+the particular image header format. The instrument translation file
+is specified to the package by the parameter \fIinstrument\fR. This
+parameter is generally set by the task \fBsetinstrument\fR. The other
+file used is a subset file. This is generally created and maintained
+by the package and the user need not do anything. For more sophisticated
+users see \fBinstruments\fR and \fBsubsets\fR.
+
+The package has very little graphics
+output. The exception is the overscan bias subtraction. The bias
+vector is logged in the metacode plot file if given. The plot file
+may be examined with the tasks in the \fBplot\fR package such as
+\fBgkimosaic\fR. When interactively fitting the overscan vector
+the graphics input and output devices must be specified. The defaults
+should apply in most cases.
+
+Because processing replaces the input image by the processed image it
+may be desired to save the original image. This may be done by
+specifying a backup prefix with the parameter \fIbackup\fR. For
+example, if the prefix is "orig" and the image is "ccd001", the backup
+image will be "origccd001". The prefix may be a directory but it must
+end with '/' or '$' (for logical directories).
+.ih
+SEE ALSO
+instruments, setinstrument, subsets
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/ccdred.ms b/noao/imred/quadred/src/quad/doc/ccdred.ms
new file mode 100644
index 00000000..645514ec
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdred.ms
@@ -0,0 +1,787 @@
+.RP
+.TL
+The IRAF CCD Reduction Package -- CCDRED
+.AU
+Francisco Valdes
+.AI
+IRAF Group - Central Computer Services
+.K2
+P.O. Box 26732, Tucson, Arizona 85726
+September 1987
+.AB
+The IRAF\(dg CCD reduction package, \fBccdred\fR, provides tools
+for the easy and efficient reduction of CCD images. The standard
+reduction operations are replacement of bad pixels, subtraction of an
+overscan or prescan bias, subtraction of a zero level image,
+subtraction of a dark count image, division by a flat field calibration
+image, division by an illumination correction, subtraction of a fringe
+image, and trimming unwanted lines or columns. Another common
+operation provided by the package is scaling and combining images with
+a number of algorithms for rejecting cosmic rays. Data in the image
+header is used to make the reductions largely automated and
+self-documenting though the package may still be used in the absence of
+this data. Also a translation mechanism is used to relate image header
+parameters to those used by the package to allow data from a variety of
+observatories and instruments to be processed. This paper describes
+the design goals for the package and the main tasks and algorithms
+which satisfy these goals.
+.PP
+This paper is to be published as part of the proceedings of the
+Santa Cruz Summer Workshop in Astronomy and Astrophysics,
+\fIInstrumentation for Ground-Based Optical Astronomy: Present and
+Future\fR, edited by Lloyd B. Robinson and published by
+Springer-Verlag.
+.LP
+\(dgImage Reduction and Analysis Facility (IRAF), a software system
+distributed by the National Optical Astronomy Observatories (NOAO).
+.AE
+.NH
+Introduction
+.PP
+The IRAF CCD reduction package, \fBccdred\fR, provides tools
+for performing the standard instrumental corrections and calibrations
+to CCD images. The major design goals were:
+.IP
+.nf
+\(bu To be easy to use
+\(bu To be largely automated
+\(bu To be image header driven if the data allows
+\(bu To be usable for a variety of instruments and observatories
+\(bu To be efficient and capable of processing large volumes of data
+.fi
+.LP
+This paper describes the important tasks and algorithms and shows how
+these design goals were met. It is not intended to describe every
+task, parameter, and usage in detail; the package has full
+documentation on each task plus a user's guide.
+.PP
+The standard CCD correction and calibration operations performed are
+replacement of bad columns and lines by interpolation from neighboring
+columns and lines, subtraction of a bias level determined from overscan
+or prescan columns or lines, subtraction of a zero level using a zero
+length exposure calibration image, subtraction of a dark count
+calibration image appropriately scaled to the dark time exposure of the
+image, division by a scaled flat field calibration image, division by
+an illumination image (derived from a blank sky image), subtraction of
+a scaled fringe image (also derived from a blank sky image), and
+trimming the image of unwanted lines or columns such as the overscan
+strip. The processing may change the pixel datatype on disk (IRAF allows
+seven image datatypes); usually from 16 bit integer to real format.
+Two special operations are also supported for scan mode and one
+dimensional zero level and flat field calibrations; i.e. the same
+calibration is applied to each CCD readout line. Any set of operations
+may be done simultaneously over a list of images in a highly efficient
+manner. The reduction operations are recorded in the image header and
+may also be logged on the terminal and in a log file.
+.PP
+The package also provides tools for combining multiple exposures
+of object and calibration images to improve the statistical accuracy of
+the observations and to remove transient bad pixels. The combining
+operation scales images of different exposure times, adjusts for
+variable sky background, statistically weights the images by their
+signal-to-noise, and provides a number of useful algorithms for
+detecting and rejecting transient bad pixels.
+.PP
+Other tasks are provided for listing reduction information about
+the images, deriving secondary calibration images (such as sky
+corrected flat fields or illumination correction images), and easily
+setting the package parameters for different instruments.
+.PP
+This paper is organized as follows. There is a section giving an
+overview of how the package is used to reduce CCD data. This gives the
+user's perspective and illustrates the general ease of use. The next
+section describes many of the features of the package contributing to
+its ease of use, automation, and generality. The next two sections
+describe the major tools and algorithms in some detail. This includes
+discussions about achieving high efficiency. Finally the status of the
+package and its use at NOAO is given. References to additional
+documentation about IRAF and the CCD reduction package and an appendix
+listing the individual tasks in the package are found at the end of
+this paper.
+.NH
+A User's Overview
+.PP
+This section provides an overview of reducing data with the IRAF CCD
+reduction package. There are many variations in usage depending on the
+type of data, whether the image headers contain information about the
+data which may be used by the tasks, and the scientific goal. Only a
+brief example is given. A more complete discussion of usage and
+examples is given in \fIA User's Guide to the IRAF CCDRED Package\fR.
+The package was developed within the IRAF system and so makes use of
+all the sophisticated features provided. These features are also
+summarized here for those not familiar with IRAF since they are an
+important part of using the package.
+.PP
+Since the IRAF system is widely distributed and runs on a wide variety
+of computers, the site of the CCD reductions might be at the telescope,
+a system at the observatory provided for this purpose, or at the
+user's home computer. The CCD images to be processed are either
+available immediately as the data is taken, transferred from the data taking
+computer via a network link (the method adopted at NOAO), or transferred
+to the reduction computer via a medium such as magnetic tape in FITS
+format. The flexibility in reduction sites and hardware is one of the
+virtues of the IRAF-based CCD reduction package.
+.PP
+IRAF tasks typically have a number of parameters which give the user
+control over most aspects of the program. This is possible since the
+parameters are kept in parameter files so that the user need not enter
+a large number of parameters every time the task is run. The user may
+change any of these parameters as desired in several ways, such as by
+explicit assignment and using an easy to learn and use,
+fill-in-the-value type of screen editor. The parameter values are
+\fIlearned\fR so that once a user sets the values they are maintained
+until the user changes them again; even between login sessions.
+.PP
+The first step in using the CCD reduction package is to set the default
+processing parameters for the data to be reduced. These parameters include
+a database file describing the image header keyword translations and
+default values, the processing operations desired (operations
+required vary with instrument and observer), the calibration image names,
+and certain special parameters for special types of observations such
+as scan mode. A special script task (a command procedure) is available
+to automatically set the default values, given the instrument name, to standard
+values defined by the support staff. Identifying the instrument in this
+way may be all the novice user need do though most people quickly learn
+to adjust parameters at will.
+.PP
+As an example suppose there is an instrument identified as \fLrca4m\fR
+for an RCA CCD at the NOAO 4 meter telescope. The user gives the command
+
+.ft L
+ cl> setinstrument rca4m
+.ft R
+
+which sets the default parameters to values suggested by the support staff
+for this instrument. The user may then change these suggested values if
+desired. In this example the processing switches are set to perform
+overscan bias subtraction, zero level image subtraction, flat fielding,
+and trimming.
+.PP
+The NOAO image headers contain information identifying the type of
+image, such as object, zero level, and flat field, the filter used to
+match flat fields with object images, the location of the overscan bias
+data, the trim size for the data, and whether the image has been
+processed. With this information the user need not worry about
+selecting images, pairing object images with calibration images, or
+inadvertently reprocessing an image.
+.PP
+The first step is to combine multiple zero level and flat field observations
+to reduce the effects of statistical noise. This is done by the
+commands
+
+.nf
+.ft L
+ cl> zerocombine *.imh
+ cl> flatcombine *.imh
+.ft R
+.fi
+
+The "cl> " is the IRAF command language prompt. The first command says
+look through all the images and combine the zero level images. The
+second command says look through all the images and combine the flat
+field images by filter. What could be simpler? Some \fIhidden\fR (default)
+parameters the user may modify are the combined image name, whether to
+process the images first, and the type of combining algorithm to use.
+.PP
+The next step is to process the images using the combined calibration
+images. The command is
+
+.ft L
+ cl> ccdproc *.imh
+.ft R
+
+This command says look through all the images, find the object images,
+find the overscan data based on the image header and subtract the
+bias, subtract the zero level calibration image, divide by the flat field
+calibration image, and trim the bias data and edge lines and columns.
+During this operation the task recognizes that the
+zero level and flat field calibration images have not been processed
+and automatically processes them when they are needed. The log output
+of this task, which may be to the terminal, to a file, or both, shows
+how this works.
+
+.nf
+.ft L
+ ccd003: Jun 1 15:12 Trim data section is [3:510,3:510]
+ ccd003: Jun 1 15:12 Overscan section is [520:540,*], mean=485.0
+ Dark: Jun 1 15:12 Trim data section is [3:510,3:510]
+ Dark: Jun 1 15:13 Overscan section is [520:540,*], mean=484.6
+ ccd003: Jun 1 15:13 Dark count image is Dark.imh
+ FlatV: Jun 1 15:13 Trim data section is [3:510,3:510]
+ FlatV: Jun 1 15:14 Overscan section is [520:540,*], mean=486.4
+ ccd003: Jun 1 15:15 Flat field image is FlatV.imh, scale=138.2
+ ccd004: Jun 1 15:16 Trim data section is [3:510,3:510]
+ ccd004: Jun 1 15:16 Overscan section is [520:540,*], mean=485.2
+ ccd004: Jun 1 15:16 Dark count image is Dark.imh
+ ccd004: Jun 1 15:16 Flat field image is FlatV.imh, scale=138.2
+ \fI<... more ...>\fL
+ ccd013: Jun 1 15:22 Trim data section is [3:510,3:510]
+ ccd013: Jun 1 15:23 Overscan section is [520:540,*], mean=482.4
+ ccd013: Jun 1 15:23 Dark count image is Dark.imh
+ FlatB: Jun 1 15:23 Trim data section is [3:510,3:510]
+ FlatB: Jun 1 15:23 Overscan section is [520:540,*], mean=486.4
+ ccd013: Jun 1 15:24 Flat field image is FlatB.imh, scale=132.3
+ \fI<... more ...>\fL
+.ft R
+.fi
+
+.PP
+The log gives the name of the image and a time stamp for each entry.
+The first image is ccd003. It is to be trimmed to the specified
+size given as an \fIimage section\fR, an array notation used commonly
+in IRAF to specify subsections of images. The location of the
+overscan data is also given by an image section which, in this case,
+was found in the image header. The mean bias level of the overscan
+is also logged though the overscan is actually a function of the
+readout line with the order of the function selected by the user.
+.PP
+When the task comes to subtracting the zero level image it first
+notes that the calibration image has not been processed and switches
+to processing the zero level image. Since it knows it is a zero level
+image the task does not attempt to zero level or flat field correct
+this image. After the zero level image has been processed the task
+returns to the object image only to find that the flat field image
+also has not been processed. It determines that the object image was
+obtained with a V filter and selects the flat field image having the same
+filter. The flat field image is processed through the zero level correction
+and then the task again returns to the object image, ccd003, which it
+finishes processing.
+.PP
+The next image, ccd004, is also a V filter
+observation. Since the zero level and V filter flat field have been
+processed the object image is processed directly. This continues
+for all the object images except for a detour to process the B filter flat
+field when the task first encounters a B filter object image.
+.PP
+In summary, the basic usage of the CCD reduction package is quite simple.
+First, the instrument is identified and some parameters for the data
+are set. Calibration images are then combined if needed. Finally,
+the processing is done with the simple command
+
+.ft L
+ cl> ccdproc *.imh&
+.ft R
+
+where the processing is performed as a \fIbackground job\fR in this example.
+This simplicity was a major goal of the package.
+.NH
+Features of the Package
+.PP
+This section describes some of the special features of the package
+which contribute to its ease of use, generality, and efficiency.
+The major criteria for ease of use are to minimize the user's record keeping
+involving input and output image names, the types of images, subset
+parameters such as filters which must be kept separate, and the state
+of processing of each image. The goal is to allow input images to
+be specified using simple wildcards, such as "*.imh" to specify all
+images, with the knowledge that the task will only operate on images
+for which it makes sense. To accomplish this the tasks must be able to
+determine the type of image, subset, and the state of processing from
+the image itself. This is done by making use of image header parameters.
+.PP
+For generality the package does not require any image header information
+except the exposure time. It is really not very much more difficult to
+reduce such data. Mainly, the user must be more explicit about specifying
+images and setting task parameters or add the information to the image
+headers. Some default header information may also be set in the image
+header translation file (discussed below).
+.PP
+One important image header parameter is the image type. This
+discriminates between object images and various types of calibration
+images such as flat field, zero level, dark count, comparison arcs,
+illumination, and fringe images. This information is used in two
+ways. For most of the tasks the user may select that only one type of
+image be considered. Thus, all the flat field images may be selected
+for combining or only the processing status of the object images be
+listed. The second usage is to allow the processing tasks to identify
+the standard calibration images and apply only those operations which
+make sense. For example, flat field images are not divided by a
+flat field. This allows the user to set the processing operations
+desired for the object images without fear of misprocessing the
+calibration images. The image type is also used to automatically
+select calibration images from a list of images to be processed instead
+of explicitly identifying them.
+.PP
+A related parameter specifies the subset. For certain operations the
+images must have a common value for this parameter. This parameter is
+often the filter but it may also apply to a grating or aperture, for example.
+The subset parameter is used to identify the appropriate flat field
+image to apply to an image or to select common flat fields to be combined
+into a higher quality flat field. This is automatic and the user need not
+keep track of which image was taken with which filter or grating.
+.PP
+The other important image header parameters are the processing flags.
+These identify when an image has been processed and also act as a history
+of the operation including calibration images used and other parameter
+information. The usage of these parameters is obvious; it allows the
+user to include processed images in a wildcard list knowing that the
+processing will not be repeated and to quickly determine the processing
+status of the image.
+.PP
+Use of image header parameters often ties the software to the a
+particular observatory. To maintain generality and usefulness for data
+other than that at NOAO, the CCD reduction package was designed to
+provide a translation between parameters requested by the package and
+those actually found in the image header. This translation is defined
+in a simple text file which maps one keyword to another and also gives
+a default value to be used if the image header does not include a
+value. In addition the translation file maps the arbitrary strings
+which may identify image types to the standard types which the package
+recognizes. This is a relatively simple scheme and does not allow for
+forming combinations or for interpreting values which are not simple
+such as embedding an exposure time as part of a string. A more complex
+translation scheme may prove desirable as experience is gained with
+other types of image header formats, but by then a general header translation
+ability and/or new image database structure may be a standard IRAF
+feature.
+.PP
+This feature has proven useful at NOAO. During the course of
+developing the package the data taking system was modernized by
+updating keywords and adding new information in the image headers,
+generally following the lines laid out by the \fBccdred\fR package.
+However, there is a period of transition and it is also desirable to
+reduce preexisting data. There are several different formats for this
+data. The header translation files make coping with these different
+formats relatively easy.
+.PP
+A fundamental aspect of the package is that the processing
+modifies the images. In other words, the reduction operations are
+performed directly on the image. This "feature" further simplifies
+record keeping, frees the user from having to form unique output image
+names, and minimizes the amount of disk space required. There
+are two safety features in this process. First, the modifications do
+not take effect until the operation is completed on the image. This
+allows the user to abort the task without leaving the image data in a
+partially processed state and protects data if the computer
+crashes. The second feature is that there is a parameter which may be
+set to make a backup of the input data with a particular prefix; for
+example "b", "orig", or "imdir$" (a logical directory prefix). This
+backup feature may be used when there is sufficient disk space, when
+learning to use the package, or just to be cautious.
+.PP
+In a similar effort to efficiently manage disk space, when combining
+images into a master object or calibration image, there is an option to
+delete the input images upon completion of the combining operation.
+Generally this is desirable when there are many calibration exposures,
+such as zero level or flat field images, which are not used after they
+are combined into a final calibration image.
+.PP
+The goal of generality for many instruments at
+different observatories inherently conflicts with the goal of ease of
+use. Generality requires many parameters and options. This is
+feasible in the CCD reduction package, as well as the other IRAF packages,
+because of the IRAF parameter handling mechanism. In \fBccdred\fR
+there still remains the problem of setting the parameters appropriately
+for a particular instrument, image header format, and observatory.
+.PP
+To make this convenient there is a task, \fBsetinstrument\fR, that,
+based on an instrument name, runs a setup script for the instrument.
+An example of this task was given in the previous section.
+The script may do any type of operation but mainly it sets default
+parameters. The setup scripts are generally created by the support staff
+for the instrument. The combination of the setup script and the
+instrument translation file make the package, in a sense, programmable
+and achieves the desired instrument/observatory generality with ease of use.
+.NH
+CCD Processing
+.PP
+This section describes in some detail how the CCD processing is performed.
+The task which does the basic CCD processing is call \fBccdproc\fR.
+From the point of view of usage the task is very simple but a great deal
+is required to achieve this simplicity. The approach we take in describing
+the task is to follow the flow of control as the task runs with digressions
+as appropriate.
+.PP
+The highest level of control is a loop over the input images; all the
+operations are performed successively on each image. It is common for
+IRAF tasks which operate on individual images to allow the operation to
+be repeated automatically over a list of input images. This is important
+in the \fBccdred\fR package because data sets are often large and the
+processing is generally the same for each image. It would be tedious
+to have to give the processing command for each image to be processed.
+If an error occurs while processing an image the error is
+printed as a warning and processing continues with the next image.
+This provides protection primarily against mistyped or nonexistent images.
+.PP
+Before the first image is processed the calibration images are
+identified. There are two ways to specify calibration images;
+explicitly via task parameters or implicitly as part of the list of
+images to be processed. Explicitly identifying calibration images
+takes precedence over calibration images in the input list. Specifying
+calibration images as part of the input image list requires that the
+image types can be determined from the image header. Using the input
+list provides a mechanism for breaking processing up into sets of
+images (possibly using files containing the image names for each set)
+each having their own calibration images. One can, of course,
+selectively specify input and calibration images, but whenever possible
+one would like to avoid having to specify explicit images to process
+since this requires record keeping by the user.
+.PP
+The first step in processing an image is to check that it is of the
+appropriate image type. The user may select to process images of only
+one type. Generally this is object images since calibration images are
+automatically processed as needed. Images which are not of the desired
+type are skipped and the next image is considered.
+.PP
+A temporary output image is created next. The output pixel datatype on
+disk may be changed at this point as selected by the user.
+For example it is common for the raw CCD images to be digitized as 16
+bit integers but after calibration it is sometimes desirable to have
+real format pixels. If no output pixel datatype is specified the
+output image takes the same pixel datatype as the input image. The
+processing is done by operating on the input image and writing the
+results to a temporary output image. When the processing is complete
+the output image replaces the input image. This gives the effect of
+processing the images in place but with certain safeguards. If the
+computer crashes or the processing is interrupted the integrity of the
+input image is maintained. The reasons for chosing to process the
+images in this way are to avoid having to generate new image names (a
+tiresome record keeping process for the user), to minimize disk
+usage, and generally the unprocessed images are not used once they have
+been processed. When dealing with large volumes of data these reasons
+become fairly important. However, the user may specify a backup prefix
+for the images in which case, once the processing is completed, the
+original input image is renamed by appending it to the prefix (or with
+an added digit if a previous backup image of the same name exits)
+before the processed output image takes the original input name.
+.PP
+The next step is to determine the image geometry. Only a subsection of
+the raw image may contain the CCD data. If this region is specified by
+a header parameter then the processing will affect only this region.
+This allows calibration and other data to be part of the image.
+Normally, the only other data in a image is overscan or prescan data.
+The location of this bias data is determined from the image header or
+from a task parameter (which overrides the image header value). To
+relate calibration images of different sizes and to allow for readout
+of only a portion of the CCD detector, a header parameter may relate
+the image data coordinates to the full CCD coordinates. Application of
+calibration image data and identifying bad pixel regions via a bad
+pixel file is done in this CCD coordinate system. The final
+geometrical information is the region of the input image to be output
+after processing; an operation called trimming. This is defined by an
+image header parameter or a task parameter. Trimming of the image is
+selected by the user. Any or all of this geometry information may be
+absent from the image and appropriate defaults are used.
+.PP
+Each selected operation which is appropriate for the image type is then
+considered. If the operation has been performed previously it will not
+be repeated. If all selected operations have been performed then the
+temporary output image is deleted and the input image is left
+unchanged. The next image is then processed.
+.PP
+For each selected operation to be performed the pertinent data is
+determined. This consists of such things as the name of the
+calibration image, scaling factors, the overscan bias function, etc.
+Note that at this point only the parameters are determined, the
+operation is not yet performed. This is because operations are not
+performed sequentially but simultaneously as described below. Consider
+flat fielding as an example. First the input image is checked to see
+if it has been flat fielded. Then the flat field calibration image is
+determined. The flat field image is checked to see if it has been
+processed. If it has not been processed then it is processed by
+calling a procedure which is essentially a copy of the main processing
+program. After the flat field image has been processed, parameters
+affecting the processing, such as the flat field scale factor
+(essentially the mean of the flat field image), are determined. A log
+of the operation is then printed if desired.
+.PP
+Once all the processing operations and parameters have been defined the
+actual processing begins. One of the key design goals was that the
+processing be efficient. There are two primary methods used to achieve
+this goal; separate processing paths for 16 bit integer data and
+floating point data and simultaneous operations. If the image, the
+calibration images, and the output image (as selected by the user) are
+16 bit integer pixel datatypes then the image data is read and written
+as integer data. This eliminates internal datatype conversions both
+during I/O and during computations. However, many operations include
+use of real factors such as the overscan bias, dark count exposure
+scaling, and flat field scaling which causes the computation to be done
+in real arithmetic before the result is stored again as an integer
+value. In any case there is never any loss of precision except when
+converting the output pixel to short integer. If any of the images are
+not integer then a real internal data path is used in which input and
+output image data are converted to real as necessary.
+.PP
+For each data path the processing proceeds line-by-line. For each line
+in the output image data region (ignoring pixels outside the data area
+and pixels which are trimmed) the appropriate input data and
+calibration data are obtained. The calibration data is determined from
+the CCD coordinates of the output image and are not necessarily from
+the same image line or columns. The input data is copied to the output
+array while applying bad pixel corrections and trimming. The line is
+then processed using a specially optimized procedure. This procedure
+applies all operations simultaneously for all combinations of
+operations. As an example, consider subtracting an overscan bias,
+subtracting a zero level, and dividing by a flat field. The basic
+kernel of the task, where the bulk of the CPU time is used, is
+
+.nf
+.ft L
+ do i = 1, n
+ out[i] = (out[i] - overscan - zero[i]) * flatscale / flat[i]
+.ft R
+.fi
+
+Here, \fIn\fR is the number of pixels in the line, \fIoverscan\fR is
+the overscan bias value for the line, \fIzero\fR is the zero level data
+from the zero level image, \fIflatscale\fR is the mean of the flat
+field image, and \fIflat\fR is the flat field data from the flat
+field image. Note the operations are not applied sequentially but
+in a single statement. This is the most efficient method and there is
+no need for intermediate images.
+.PP
+Though the processing is logically performed line-by-line in the program,
+the image I/O from the disk is not done this way. The IRAF virtual
+operating system image interface automatically provides multi-line
+buffering for maximal I/O efficiency.
+.PP
+In many image processing systems it has been standard to apply operations
+sequentially over an image. This requires producing intermediate images.
+Since this is clearly inefficient in terms of I/O it has been the practice
+to copy the images into main memory and operate upon them there until
+the final image is ready to be saved. This has led to the perception
+that in order to be efficient an image processing system \fImust\fR
+store images in memory. This is not true and the IRAF CCD reduction
+package illustrates this. The CCD processing does not use intermediate
+images and does not need to keep the entire image in main memory.
+Furthermore, though of lesser importance than I/O, the single statement method
+illustrated above is more efficient than multiple passes through the
+images even when the images are kept in main memory. Finally, as CCD
+detectors increase in size and small, fast, and cheap processors become
+common it is a distinct advantage to not require the large amounts of
+memory needed to keep entire images in memory.
+.PP
+There is one area in which use of main memory can improve performance
+and \fBccdproc\fR does take advantage of it if desired. The calibration
+images usually are the same for many input images. By specifying the
+maximum amount of memory available for storing images in memory
+the calibration images may be stored in memory up to that amount.
+By parameterizing the memory requirement there is no builtin dependence
+on large memory!
+.PP
+After processing the input image the last steps are to log the operations
+in the image header using processing keywords and replace the input
+image by the output image as described earlier. The CCD coordinates
+of the data are recorded in the header, even if not there previously, to
+allow further processing on the image after the image has been trimmed.
+.NH
+Combining Images
+.PP
+The second important tool in the CCD reduction package is a task to combine
+many images into a single, higher quality image. While this may also be
+done with more general image processing tools (the IRAF task \fBimsum\fR
+for example) the \fBccdred\fR tasks include special CCD dependent features such
+as recognizing the image types and using the image header translation
+file. Combining images is often done
+with calibration images, which are easy to obtain in number, where it
+is important to minimize the statistical noise so as to not affect the
+object images. Sometimes object images also are combined.
+The task is called \fBcombine\fR and there are special versions of
+this task called \fBzerocombine, darkcombine\fR, and \fBflatcombine\fR
+for the standard calibration images.
+.PP
+The task takes a list of input images to be combined. As output there
+is the combined image, an optional sigma image, and optional log output either
+to the terminal, to a log file, or both. A subset or subsets
+of the input images may be selected based on the image type and a
+subset parameter such as the filter. As with the processing task,
+this allows selecting images without having to explicitly list each
+image from a large data set. When combining based on a subset parameter
+there is an output image, and possibly a sigma image, for each separate subset.
+The output image pixel datatype may also be changed during combining;
+usually from 16 bit integer input to real output.
+The sigma image is the standard deviation of the input images about the
+output image.
+.PP
+Except for summing the images together,
+combining images may require correcting for variations between the images
+due to differing exposure times, sky background, extinctions, and
+positions. Currently, extinction corrections and registration are
+not included but scaling and shifting corrections are included.
+The scaling corrections may be done by exposure times or by computing
+the mode in each image. Additive shifting is also done by computing
+the mode in the images. The region of the image in which the mode
+is computed can be specified but by default the whole image is used.
+A scaling correction is used when the flux level or sensitivity is varying.
+The offset correction is used when the sky brightness is varying independently
+of the object brightness. If the images are not scaled then special
+data paths combine the images more efficiently.
+.PP
+Except for medianing and summing, the images are combined by averaging.
+The average may be weighted by
+
+.nf
+.ft L
+ weight = (N * scale / mode) ** 2
+.ft R
+.fi
+
+where \fIN\fR is the number of images previously combined (the task
+records the number of images combined in the image header), \fIscale\fR
+is the relative scale (applied by dividing) from the exposure time or
+mode, and \fImode\fR is the background mode estimate used when adding a
+variable offset.
+.PP
+The combining operation is the heart of the task. There are a number
+algorithms which may be used as well as applying statistical weights.
+The algorithms are used to detect and reject deviant pixels, such as
+cosmic rays.
+The choice of algorithm depends on the data, the number of images,
+and the importance of rejecting cosmic rays. The more complex the
+algorithm the more time consuming the operation.
+The list below summarizes the algorithms.
+Further algorithms may be added in time.
+
+.IP "Sum - sum the input images"
+.br
+The input images are combined by summing. Care must be taken
+not to exceed the range of the 16 bit integer datatype when summing if the
+output datatype is of this type. Summing is the only algorithm in which
+scaling and weighting are not used. Also no sigma image is produced.
+.IP "Average - average the input images"
+.br
+The input images are combined by averaging. The images may be scaled
+and weighted. There is no pixel rejection. A sigma image is produced
+if more than one image is combined.
+.IP "Median - median the input images"
+.br
+The input images are combined by medianing each pixel. Unless the images
+are at the same exposure level they should be scaled. The sigma image
+is based on all the input images and is only an approximation to the
+uncertainty in the median estimates.
+.IP "Minreject, maxreject, minmaxreject - reject extreme pixels"
+.br
+At each pixel the minimum, maximum, or both are excluded from the
+average. The images should be scaled and the average may be
+weighted. The sigma image requires at least two pixels after rejection
+of the extreme values. These are relatively fast algorithms and are
+a good choice if there are many images (>15).
+.IP "Threshold - reject pixels above and below specified thresholds"
+.br
+The input images are combined with pixels above and below specified
+threshold values (before scaling) excluded. The images may be scaled
+and the average weighted. The sigma image also has the rejected
+pixels excluded.
+.IP "Sigclip - apply a sigma clipping algorithm to each pixel"
+.br
+The input images are combined by applying a sigma clipping algorithm
+at each pixel. The images should be scaled. This only rejects highly
+deviant points and so
+includes more of the data than the median or minimum and maximum
+algorithms. It requires many images (>10-15) to work effectively.
+Otherwise the bad pixels bias the sigma significantly. The mean
+used to determine the sigmas is based on the "minmaxrej" algorithm
+to eliminate the effects of bad pixels on the mean. Only one
+iteration is performed and at most one pixel is rejected at each
+point in the output image. After the deviant pixels are rejected the final
+mean is computed from all the data. The sigma image excludes the
+rejected pixels.
+.IP "Avsigclip - apply a sigma clipping algorithm to each pixel"
+.br
+The input images are combined with a variant of the sigma clipping
+algorithm which works well with only a few images. The images should
+be scaled. For each line the mean is first estimated using the
+"minmaxrej" algorithm. The sigmas at each point in the line are scaled
+by the square root of the mean, that is a Poisson scaling of the noise
+is assumed. These sigmas are averaged to get a line estimate of the
+sigma. Then the sigma at each point in the line is estimated by
+multiplying the line sigma by the square root of the mean at that point. As
+with the sigma clipping algorithm only one iteration is performed and
+at most one pixel is rejected at each point. After the deviant pixels
+are rejected the file mean is computed from all the data. The sigma
+image excludes the rejected pixels.
+.RE
+.PP
+The "avsigclip" algorithm is the best algorithm for rejecting cosmic
+rays, especially with a small number of images, but it is also the most
+time consuming. With many images (>10-15) it might be advisable to use
+one of the other algorithms ("maxreject", "median", "minmaxrej") because
+of their greater speed.
+.PP
+This task also has several design features to make it efficient and
+versatile. There are separate data paths for integer data and real
+data; as with processing, if all input images and the output image are
+of the same datatype then the I/O is done with no internal conversions.
+With mixed datatypes the operations are done as real. Even in the
+integer path the operations requiring real arithmetic to preserve the
+accuracy of the calculation are performed in that mode. There is
+effectively no limit to the number of images which may be combined.
+Also, the task determines the amount of memory available and buffers
+the I/O as much as possible. This is a case where operating on images
+from disk rather than in memory is essential.
+.NH
+Status and Conclusion
+.PP
+The initial implementation of the IRAF \fBccdred\fR package was
+completed in June 1987. It has been in use at the National Optical
+Astronomy Observatories since April 1987. The package was not
+distributed with Version 2.5 of IRAF (released in August 1987) but is
+available as a separate installation upon request. It will be part of
+future releases of IRAF.
+.PP
+At NOAO the CCD reduction package is available at the telescopes as the
+data is obtained. This is accomplished by transferring the images from
+the data taking computer to a Sun workstation (Sun Microsystems, Inc.)
+initially via tape and later by a direct link. There are several
+reasons for adopting this architecture. First, the data acquisition
+system is well established and is dedicated to its real-time function.
+The second computer was phased in without disrupting the essential
+operation of the telescopes and if it fails data taking may continue
+with data being stored on tape. The role of the second computer is to
+provide faster and more powerful reduction and analysis capability not
+required in a data acquisition system. In the future it can be more
+easily updated to follow the state of the art in small computers. As
+CCD detectors get larger the higher processing speeds will be essential
+to keep up with the data flow.
+.PP
+By writing the reduction software in the high level, portable, IRAF
+system the users have the capability to process their data from the
+basic CCD reductions to a full analysis at the telescope. Furthermore,
+the same software is widely available on a variety of computers if
+later processing or reprocessing is desired; staff and visitors at NOAO
+may also reduce their data at the headquarters facilities. The use of
+a high level system was also essential in achieving the design goals;
+it would be difficult to duplicate this complex package without
+the rich programming environment provided by the IRAF system.
+.NH
+References
+.PP
+The following documentation is distributed by the National Optical
+Astronomy Observatories, Central Computer Services, P.O. Box 26732,
+Tucson, Arizona, 85726. A comprehensive description of the IRAF system
+is given in \fIThe IRAF Data Reduction and Analysis System\fR by Doug
+Tody (also appearing in \fIProceedings of the SPIE - Instrumentation in
+Astronomy VI\fR, Vol. 627, 1986). A general guide to using IRAF is \fIA
+User's Introduction to the IRAF Command Language\fR by Peter Shames
+and Doug Tody. Both these documents are also part of the IRAF
+documentation distributed with the system.
+.PP
+A somewhat more tutorial description of the \fBccdred\fR package is
+\fIA User's Guide to the IRAF CCDRED Package\fR by the author.
+Detailed task descriptions and supplementary documentation are
+given in the on-line help library and are part of the user's guide.
+.NH
+Appendix
+.PP
+The current set of tasks making up the IRAF CCD Reduction Package,
+\fBccdred\fR, are summarized below.
+
+.nf
+.ft L
+ badpiximage - Create a bad pixel mask image from a bad pixel file
+ ccdgroups - Group CCD images into image lists
+ ccdhedit - CCD image header editor
+ ccdlist - List CCD processing information
+ ccdproc - Process CCD images
+ combine - Combine CCD images
+ darkcombine - Combine and process dark count images
+ flatcombine - Combine and process flat field images
+ mkfringecor - Make fringe correction images from sky images
+ mkillumcor - Make flat field illumination correction images
+ mkillumflat - Make illumination corrected flat fields
+ mkskycor - Make sky illumination correction images
+ mkskyflat - Make sky corrected flat field images
+setinstrument - Set instrument parameters
+ zerocombine - Combine and process zero level images
+.fi
+.ft R
diff --git a/noao/imred/quadred/src/quad/doc/ccdtypes.hlp b/noao/imred/quadred/src/quad/doc/ccdtypes.hlp
new file mode 100644
index 00000000..2cec33ea
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/ccdtypes.hlp
@@ -0,0 +1,124 @@
+.help ccdtypes Jun87 noao.imred.ccdred
+.ih
+NAME
+ccdtypes -- Description of the CCD image types
+.ih
+CCDTYPES
+The following CCD image types may be specified as the value of the parameter
+\fIccdtype\fR:
+
+.nf
+ "" - (the null string) all image types
+ object - object images
+ zero - zero level images such as a bias or preflash
+ dark - dark count images
+ flat - flat field images
+ illum - iillumination images
+ fringe - fringe correction images
+ other - other image types defined in the translation file
+ none - images without an image type parameter
+ unknown - image types not defined in the translation file
+.fi
+.ih
+DESCRIPTION
+The \fBccdred\fR package recognizes certain standard CCD image types
+identified in the image header. The tasks may select images of a
+particular CCD image type from image lists with the parameter
+\fIccdtype\fR and also recognize and take special actions for
+calibration images.
+
+In order to make use of CCD image type information the header keyword
+identifying the image type must be specified in the instrument
+translation file. This entry has the form
+
+ imagetyp keyword
+
+where keyword is the image header keyword. This allows the package to
+access the image type string. There must also be a translation between
+the image type strings and the CCD types as recognized by the package.
+This information consists of lines in the instrument translation file
+of the form
+
+ header package
+
+where header is the exact string given in the image header and package
+is one of the types recognized by the package. The image header string
+can be virtually anything and if it contains blanks it must be
+quoted. The package image types are those given above except for
+the null string, "none", and "unknown". That is, these types may
+be specified as a CCD image type in selecting images but not as a translations
+of image type strings.
+
+There may be more than one image type that maps to the same package
+type. In particular other standard CCD image types, such as comparison
+spectra, multiple exposure, standard star, etc., should be mapped to
+object or other. There may also be more than one type of flat field, i.e. dome
+flat, sky flat, and lamp flat. For more on the instrument translation
+file see the help for \fBinstruments\fR.
+.ih
+EXAMPLES
+1. The example entries in the instrument translation file are from the 1986
+NOAO CCD image header format produced by the CAMERA format tape writer.
+
+.nf
+ imagetyp data-typ
+
+ 'OBJECT (0)' object
+ 'DARK (1)' dark
+ 'PROJECTOR FLAT (2)' flat
+ 'SKY FLAT (3)' other
+ 'COMPARISON LAMP (4)' other
+ 'BIAS (5)' zero
+ 'DOME FLAT (6)' flat
+.fi
+
+The image header keyword describing the image type is "data-typ".
+The values of the image type strings in the header contain blanks so they
+are quoted. Also the case of the strings is important. Note that there
+are two types of flat field images and two types of other images.
+
+2. One way to check the image types is with the task \fBccdlist\fR.
+
+.nf
+ cl> ccdlist *.imh
+ Zero.imh[504,1][real][zero][1][OT]:FOCUS L98-193
+ Flat1.imh[504,1][real][flat][1][OTZ]:dflat 6v+blue 5s
+ ccd002.imh[504,504][real][unknown][1][OTZF]:FOCUS L98-193
+ ccd003.imh[544,512][short][object][1]:L98-193
+ ccd004.imh[544,512][short][object][1]:L98-193
+ ccd005.imh[544,512][short][object][1]:L98-193
+ oldformat.imh[544,512][short][none][1]:M31 V
+.fi
+
+The unknown type has a header image type of "MUL (8)". The old format
+image does not have any header type.
+
+3. To select only images of a particular type:
+
+.nf
+ cl> ccdlist *.imh ccdtype=object
+ ccd003.imh[544,512][short][object][1]:L98-193
+ ccd004.imh[544,512][short][object][1]:L98-193
+ ccd005.imh[544,512][short][object][1]:L98-193
+ cl> ccdlist *.imh ccdtype=unknown
+ ccd002.imh[504,504][real][unknown][1][OTZF]:FOCUS L98-193
+ cl> ccdlist *.imh ccdtype=none
+ oldformat.imh[544,512][short][none][1]:M31 V
+.fi
+
+4. To process images with \fBccdproc\fR:
+
+.nf
+ cl> ccdproc *.imh
+ cl> ccdproc *.imh ccdtype=object
+.fi
+
+In the first case all the images will be processed (the default value of
+\fIccdtype\fR is ""). However, the task recognizes the calibration
+images, such as zero level and flat fields, and processes them appropriately.
+In the second case only object images are processed and all other images
+are ignored (except if needed as a calibration image).
+.ih
+SEE ALSO
+instruments
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/combine.hlp b/noao/imred/quadred/src/quad/doc/combine.hlp
new file mode 100644
index 00000000..b3c0848e
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/combine.hlp
@@ -0,0 +1,1030 @@
+.help combine Sep92 noao.imred.ccdred
+.ih
+NAME
+combine -- Combine CCD images using various algorithms
+.ih
+USAGE
+combine input output
+.ih
+PARAMETERS
+.ls input
+List of CCD images to combine. Images of a particular CCD image type may be
+selected with the parameter \fIccdtype\fR with the remaining images ignored.
+.le
+.ls output
+Output combined image or list of images. If the \fIproject\fR parameter is
+no (the typical case for CCD acquisition) then there will be one output image
+or, if the \fIsubsets\fR parameter is selected, one output image per subset.
+If the images consist of stacks then the \fIproject\fR option allows combining
+each input stack into separate output images as given by the image list.
+.le
+.ls plfile = "" (optional)
+Output pixel list file or list of files. If no name is given or the
+list ends prematurely then no file is produced. The pixel list file
+is a map of the number of pixels rejected or, equivalently,
+the total number of input images minus the number of pixels actually used.
+The file name is also added to the output image header under the
+keyword BPM.
+.le
+.ls sigma = "" (optional)
+Output sigma image or list of images. If no name is given or the list ends
+prematurely then no image is produced. The sigma is standard deviation,
+corrected for a finite population, of the input pixel values (excluding
+rejected pixels) about the output combined pixel values.
+.le
+
+.ls ccdtype = ""
+CCD image type to combine. If specified only input images of the specified
+type are combined. See \fBccdtypes\fR for the possible image types.
+.le
+.ls subsets = no
+Combine images by subset parameter? If yes then the input images are
+grouped by subset parameter and each group combined into a separate output
+image. The subset identifier is appended to the output image
+name(s). See \fBsubsets\fR for more on the subset parameter.
+.le
+.ls delete = no
+Delete input images after combining? Only those images combined are deleted.
+.le
+.ls clobber = no
+Clobber existing output images?
+.le
+
+.ls combine = "average" (average|median)
+Type of combining operation performed on the final set of pixels (after
+offsetting, masking, thresholding, and rejection). The choices are
+"average" or "median". The median uses the average of the two central
+values when the number of pixels is even.
+.le
+.ls reject = "none" (none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip)
+Type of rejection operation performed on the pixels remaining after offsetting,
+masking and thresholding. The algorithms are discussed in the
+DESCRIPTION section. The rejection choices are:
+
+.nf
+ none - No rejection
+ minmax - Reject the nlow and nhigh pixels
+ ccdclip - Reject pixels using CCD noise parameters
+ crreject - Reject only positive pixels using CCD noise parameters
+ sigclip - Reject pixels using a sigma clipping algorithm
+ avsigclip - Reject pixels using an averaged sigma clipping algorithm
+ pclip - Reject pixels using sigma based on percentiles
+.fi
+
+.le
+.ls project = no
+Project (combine) across the highest dimension of the input images? If
+no then all the input images are combined to a single output image. If
+yes then the highest dimension elements of each input image are combined to
+an output image and optional pixel list and sigma images. Each element of
+the highest dimension may have a separate offset but there can only be one
+mask image.
+.le
+.ls outtype = "real" (short|integer|long|real|double)
+Output image pixel datatype. The pixel datatypes are "double",
+"real", "long", "integer", and "short" with highest precedence first.
+If none is specified then the highest precedence datatype of the input
+images is used. The datatypes may be abbreviated to a single character.
+.le
+.ls offsets = "none" (none|grid|<filename>)
+Input image offsets. The offsets may be specified in a file consisting
+of one line per image with the offsets in each dimension forming the
+columns. The special case of a grid may be specified by the string:
+
+.nf
+ grid [n1] [s1] [n2] [s2] ...
+.fi
+
+where ni is the number of images in dimension i and si is the step
+in dimension i. For example "grid 5 100 5 100" specifies a 5x5
+grid with origins offset by 100 pixels.
+.le
+.ls masktype = "none" (none|goodvalue|badvalue|goodbits|badbits)
+Type of pixel masking to use. If "none" then no pixel masking is done
+even if an image has an associated pixel mask. The other choices
+are to select the value in the pixel mask to be treated as good
+(goodvalue) or bad (badvalue) or the bits (specified as a value)
+to be treated as good (goodbits) or bad (badbits). The pixel mask
+file name comes from the image header keyword BPM.
+.le
+.ls maskvalue = 0
+Mask value used with the \fImasktype\fR parameter. If the mask type
+selects good or bad bits the value may be specified using IRAF notation
+for decimal, octal, or hexadecimal; i.e 12, 14b, 0cx to select bits 3
+and 4.
+.le
+.ls blank = 0.
+Output value to be used when there are no pixels.
+.le
+
+.ls scale = "none" (none|mode|median|mean|exposure|@<file>|!<keyword>)
+Multiplicative image scaling to be applied. The choices are none, scale
+by the mode, median, or mean of the specified statistics section, scale
+by the exposure time in the image header, scale by the values in a specified
+file, or scale by a specified image header keyword. When specified in
+a file the scales must be one per line in the order of the input
+images.
+.le
+.ls zero = "none" (none|mode|median|mean|@<file>|!<keyword>)
+Additive zero level image shifts to be applied. The choices are none or
+shift by the mode, median, or mean of the specified statistics section,
+shift by values given in a file, or shift by values given by an image
+header keyword. When specified in a file the zero values must be one
+per line in the order of the input images.
+.le
+.ls weight = "none" (none|mode|median|mean|exposure|@<file>|!<keyword>)
+Weights to be applied during the final averaging. The choices are none,
+the mode, median, or mean of the specified statistics section, the exposure
+time, values given in a file, or values given by an image header keyword.
+When specified in a file the weights must be one per line in the order of
+the input images.
+.le
+.ls statsec = ""
+Section of images to use in computing image statistics for scaling and
+weighting. If no section is given then the entire region of the input is
+sampled (for efficiency the images are sampled if they are big enough).
+When the images are offset relative to each other one can precede the image
+section with one of the modifiers "input", "output", "overlap". The first
+interprets the section relative to the input image (which is equivalent to
+not specifying a modifier), the second interprets the section relative to
+the output image, and the last selects the common overlap and any following
+section is ignored.
+.le
+
+.ce
+Algorithm Parameters
+.ls lthreshold = INDEF, hthreshold = INDEF
+Low and high thresholds to be applied to the input pixels. This is done
+before any scaling, rejection, and combining. If INDEF the thresholds
+are not used.
+.le
+.ls nlow = 1, nhigh = 1 (minmax)
+The number of low and high pixels to be rejected by the "minmax" algorithm.
+These numbers are converted to fractions of the total number of input images
+so that if no rejections have taken place the specified number of pixels
+are rejected while if pixels have been rejected by masking, thresholding,
+or nonoverlap, then the fraction of the remaining pixels, truncated
+to an integer, is used.
+.le
+.ls nkeep = 1
+The minimum number of pixels to retain or the maximum number to reject
+when using the clipping algorithms (ccdclip, crreject, sigclip,
+avsigclip, or pclip). When given as a positive value this is the minimum
+number to keep. When given as a negative value the absolute value is
+the maximum number to reject. This is actually converted to a number
+to keep by adding it to the number of images.
+.le
+.ls mclip = yes (ccdclip, crreject, sigclip, avsigcliip)
+Use the median as the estimate for the true intensity rather than the
+average with high and low values excluded in the "ccdclip", "crreject",
+"sigclip", and "avsigclip" algorithms? The median is a better estimator
+in the presence of data which one wants to reject than the average.
+However, computing the median is slower than the average.
+.le
+.ls lsigma = 3., hsigma = 3. (ccdclip, crreject, sigclip, avsigclip, pclip)
+Low and high sigma clipping factors for the "ccdclip", "crreject", "sigclip",
+"avsigclip", and "pclip" algorithms. They multiply a "sigma" factor
+produced by the algorithm to select a point below and above the average or
+median value for rejecting pixels. The lower sigma is ignored for the
+"crreject" algorithm.
+.le
+.ls rdnoise = "0.", gain = "1.", snoise = "0." (ccdclip, crreject)
+CCD readout noise in electrons, gain in electrons/DN, and sensitivity noise
+as a fraction. These parameters are used with the "ccdclip" and "crreject"
+algorithms. The values may be either numeric or an image header keyword
+which contains the value.
+.le
+.ls sigscale = 0.1 (ccdclip, crreject, sigclip, avsigclip)
+This parameter determines when poisson corrections are made to the
+computation of a sigma for images with different scale factors. If all
+relative scales are within this value of unity and all relative zero level
+offsets are within this fraction of the mean then no correction is made.
+The idea is that if the images are all similarly though not identically
+scaled, the extra computations involved in making poisson corrections for
+variations in the sigmas can be skipped. A value of zero will apply the
+corrections except in the case of equal images and a large value can be
+used if the sigmas of pixels in the images are independent of scale and
+zero level.
+.le
+.ls pclip = -0.5 (pclip)
+Percentile clipping algorithm parameter. If greater than
+one in absolute value then it specifies a number of pixels above or
+below the median to use for computing the clipping sigma. If less
+than one in absolute value then it specifies the fraction of the pixels
+above or below the median to use. A positive value selects a point
+above the median and a negative value selects a point below the median.
+The default of -0.5 selects approximately the quartile point.
+See the DESCRIPTION section for further details.
+.le
+.ls grow = 0
+Number of pixels to either side of a rejected pixel along image lines
+to also be rejected. This applies only to pixels rejected by one of
+the rejection algorithms and not the masked or threshold rejected pixels.
+.le
+
+PACKAGE PARAMETERS
+
+The package parameters are used to specify verbose and log output and the
+instrument and header definitions.
+.ih
+DESCRIPTION
+A set of CCD images are combined by weighted averaging or medianing. Pixels
+may be rejected from the combining by using pixel masks, threshold levels,
+and rejection algorithms. The images may be scaled multiplicatively or
+additively based on image statistics, image header keywords, or text files
+before rejection. The images may be combined with integer pixel coordinate
+offsets to produce an image bigger than any of the input images.
+This task is a variant of the \fBimages.imcombine\fR task specialized
+for CCD images.
+
+The input images to be combined are specified by a list. A subset or
+subsets of the input list may be selected using the parameters
+\fIccdtype\fR and \fIsubsets\fR. The \fIccdtype\fR parameter selects only
+images of a specified standard CCD image type. The \fIsubsets\fR parameter
+breaks up the input list into sublists of common subset parameter (filter,
+grating, etc.). For more information see \fBccdtypes\fR and
+\fBsubsets\fR. This selection process is useful with wildcard templates to
+combine, for example, the flat field images for each filter in one step
+(see \fBflatcombine\fR). When subsets of the input list are used the
+output image and optional pixel file and sigma image are given by root names
+with a subset identifier appended by the task.
+
+If the \fBproject\fR parameter is yes then the highest dimension elements
+of each input image are combined to make an output image of one lower
+dimension. There is no limit to the number of elements combined in this
+case. This case is If the \fBproject\fR is no then the entire input list
+is combined to form a single output image per subset. In this case the
+images must all have the same dimensionality but they may have different
+sizes. There is a software limit of approximately 100 images in this
+case.
+
+The output image header is a copy of the first image in the combined set.
+In addition, the number of images combined is recorded under the keyword
+NCOMBINE, the exposure time is updated as the weighted average of the input
+exposure times, and any pixel list file created is recorded under the
+keyword BPM. The output pixel type is set by the parameter \fIouttype\fR.
+If left blank then the input datatype of highest precision is used.
+
+In addition to one or more output combined images there may also be a pixel
+list image containing the number of pixels rejected at each point in the
+output image, an image containing the sigmas of the pixels combined about
+the final output combined pixels, and a log file. The pixel list image is
+in the compact pixel list format which can be used as an image in other
+programs. The sigma computation is the standard deviation corrected for a
+finite population (the n/(n-1) factor) including weights if a weighted
+average is used.
+
+Other input/output parameters are \fIdelete\fR and \fIclobber\fR. The
+\fIdelete\fR parameter may be set to "yes" to delete the input images
+used in producing an output image after it has been created. This is
+useful for minimizing disk space, particularly with large
+sets of calibration images needed to achieve high statistical accuracy
+in the final calibration image. The \fBclobber\fR parameter allows
+the output image names to be existing images which are overwritten (at
+the end of the operation).
+
+An outline of the steps taken by the program is given below and the
+following sections elaborate on the steps.
+
+.nf
+o Set the input image offsets and the final output image size.
+o Set the input image scales and weights
+o Write the log file output
+.fi
+
+For each output image line:
+
+.nf
+o Get input image lines that overlap the output image line
+o Reject masked pixels
+o Reject pixels outside the threshold limits
+o Reject pixels using the specified algorithm
+o Reject neighboring pixels along each line
+o Combine remaining pixels using the weighted average or median
+o Compute sigmas of remaining pixels about the combined values
+o Write the output image line, rejected pixel list, and sigmas
+.fi
+
+
+OFFSETS
+
+The images to be combined need not be of the same size or overlap. They
+do have to have the same dimensionality which will also be the dimensionality
+of the output image. Any dimensional images supported by IRAF may be
+used. Note that if the \fIproject\fR flag is yes then the input images
+are the elements of the highest dimension; for example the planes of a
+three dimensional image.
+
+The overlap of the images is determined by a set of integer pixel offsets
+with an offset for each dimension of each input image. For example
+offsets of 0, 10, and 20 in the first dimension of three images will
+result in combining the three images with only the first image in the
+first 10 colums, the first two images in the next 10 columns and
+all three images starting in the 31st column. At the 31st output column
+the 31st column of the first image will be combined with the 21st column
+of the second image and the 1st column of the third image.
+
+The output image size is set by the maximum extent in each dimension
+of any input image after applying the offsets. In the above example if
+all the images have 100 columns then the output image will have 130
+columns corresponding to the 30 column offset in the third image.
+
+The input image offsets are set using the \fIoffset\fR parameter. There
+are three ways to specify the offsets. If the word "none" or the empty
+string "" are used then all offsets will be zero and all pixels with the
+same coordinates will be combined. The output image size will be equal to
+the biggest dimensions of the input images.
+
+If the input images have offsets in a regular grid or one wants to make
+an output image in which the input images are "mosaiced" together in
+a grid then the special offset string beginning with the word "grid"
+is used. The format is
+
+.nf
+ grid [n1] [s1] [n2] [s2] ...
+.fi
+
+where ni is the number of images in dimension i and si is the step in
+dimension i. For example "grid 5 100 5 100" specifies a 5x5 grid with
+origins offset by 100 pixels. Note that one must insure that the input
+images are specified in the correct order. This may best be accomplished
+using a "@" list. One useful application of the grid is to make a
+nonoverlapping mosaic of a number of images for display purposes. Suppose
+there are 16 images which are 100x100. The offset string "grid 4 101 4
+101" will produce a mosaic with a one pixel border having the value set
+by \fIblank\fR parameter between the images.
+
+The offsets may be defined in a file by specifying the file name
+in the \fIoffset\fR parameter. (Note that the special file name STDIN
+may be used to type in the values terminated by the end-of-file
+character). The file consists of a line for each input image. The lines
+must be in the same order as the input images and so an "@" list may
+be useful. The lines consist of whitespace separated offsets one for
+each dimension of the images. In the first example cited above the
+offset file might contain:
+
+.nf
+ 0 0
+ 10 0
+ 20 0
+.fi
+
+where we assume the second dimension has zero offsets.
+
+The offsets need not have zero for one of the images. The offsets may
+include negative values or refer to some arbitrary common point.
+When the offsets are read by the program it will find the minimum
+value in each dimension and subtract it from all the other offsets
+in that dimension. The above example could also be specified as:
+
+.nf
+ 225 15
+ 235 15
+ 245 15
+.fi
+
+There may be cases where one doesn't want the minimum offsets reset
+to zero. If all the offsets are positive and the comment "# Absolute"
+appears in the offset file then the images will be combined with
+blank values between the first output pixel and the first overlapping
+input pixel. Continuing with the above example, the file
+
+.nf
+ # Absolute
+ 10 10
+ 20 10
+ 30 10
+.fi
+
+will have the first pixel of the first image in the 11th pixel of the
+output image. Note that there is no way to "pad" the other side of
+the output image.
+
+
+SCALES AND WEIGHTS
+
+In order to combine images with rejection of pixels based on deviations
+from some average or median they must be scaled to a common level. There
+are two types of scaling available, a multiplicative intensity scale and an
+additive zero point shift. The intensity scaling is defined by the
+\fIscale\fR parameter and the zero point shift by the \fIzero\fR
+parameter. These parameters may take the values "none" for no scaling,
+"mode", "median", or "mean" to scale by statistics of the image pixels,
+"exposure" (for intensity scaling only) to scale by the exposure time
+keyword in the image header, any other image header keyword specified by
+the keyword name prefixed by the character '!', and the name of a file
+containing the scale factors for the input image prefixed by the
+character '@'.
+
+Examples of the possible parameter values are shown below where
+"myval" is the name of an image header keyword and "scales.dat" is
+a text file containing a list of scale factors.
+
+.nf
+ scale = none No scaling
+ zero = mean Intensity offset by the mean
+ scale = exposure Scale by the exposure time
+ zero = !myval Intensity offset by an image keyword
+ scale = @scales.dat Scales specified in a file
+.fi
+
+The image statistics factors are computed by sampling a uniform grid
+of points with the smallest grid step that yields less than 10000
+pixels; sampling is used to reduce the time need to compute the statistics.
+If one wants to restrict the sampling to a region of the image the
+\fIstatsec\fR parameter is used. This parameter has the following
+syntax:
+
+.nf
+ [input|output|overlap] [image section]
+.fi
+
+The initial modifier defaults to "input" if absent. The modifiers are useful
+if the input images have offsets. In that case "input" specifies
+that the image section refers to each input image, "output" specifies
+that the image section refers to the output image coordinates, and
+"overlap" specifies the mutually overlapping region of the input images.
+In the latter case an image section is ignored.
+
+The statistics are as indicated by their names. In particular, the
+mode is a true mode using a bin size which is a fraction of the
+range of the pixels and is not based on a relationship between the
+mode, median, and mean. Also masked pixels are excluded from the
+computations as well as during the rejection and combining operations.
+
+The "exposure" option in the intensity scaling uses the exposure time
+from the image header. If one wants to use a nonexposure time image
+header keyword the !<keyword> syntax is available.
+
+If both an intensity scaling and zero point shift are selected the
+multiplicative scaling is done first. Use of both makes sense
+if the intensity scaling is the exposure time to correct for
+different exposure times and then the zero point shift allows for
+sky brightness changes.
+
+The image statistics and scale factors are recorded in the log file
+unless they are all equal, which is equivalent to no scaling. The
+intensity scale factors are normalized to a unit mean and the zero
+point shifts are adjust to a zero mean.
+
+Scaling affects not only the mean values between images but also the
+relative pixel uncertainties. For example scaling an image by a
+factor of 0.5 will reduce the effective noise sigma of the image
+at each pixel by the square root of 0.5. Changes in the zero
+point also changes the noise sigma if the image noise characteristics
+are Poissonian. In the various rejection algorithms based on
+identifying a noise sigma and clipping large deviations relative to
+the scaled median or mean, one may need to account for the scaling induced
+changes in the image noise characteristics.
+
+In those algorithms it is possible to eliminate the "sigma correction"
+while still using scaling. The reasons this might be desirable are 1) if
+the scalings are similar the corrections in computing the mean or median
+are important but the sigma corrections may not be important and 2) the
+image statistics may not be Poissonian, either inherently or because the
+images have been processed in some way that changes the statistics. In the
+first case because computing square roots and making corrections to every
+pixel during the iterative rejection operation may be a significant
+computational speed limit the parameter \fIsigscale\fR selects how
+dissimilar the scalings must be to require the sigma corrections. This
+parameter is a fractional deviation which, since the scale factors are
+normalized to unity, is the actual minimum deviation in the scale factors.
+For the zero point shifts the shifts are normalized by the mean shift
+before adjusting the shifts to a zero mean. To always use sigma scaling
+corrections the parameter is set to zero and to eliminate the correction in
+all cases it is set to a very large number.
+
+If the final combining operation is "average" then the images may be
+weighted during the averaging. The weights are specified in the
+same way as the scale factors. In addition
+the NCOMBINE keyword, if present, will be used in the weights.
+The weights, scaled to a unit sum, are printed in the log output.
+
+The weights are only used for the final weighted average and sigma image
+output. They are not used to form averages in the various rejection
+algorithms.
+
+
+PIXEL MASKS
+
+A pixel mask is a type of IRAF file having the extension ".pl" which
+identifies an integer value with each pixel of the images to which it is
+applied. The integer values may denote regions, a weight, a good or bad
+flag, or some other type of integer or integer bit flag. In the common
+case where many values are the same this file is compacted to be small and
+efficient to use. It is also most compact and efficient if the majority of
+the pixels have a zero mask value so frequently zero is the value for good
+pixels. Note that these files, while not stored as a strict pixel array,
+may be treated as images in programs. This means they may be created by
+programs such as \fBmkpattern\fR, edited by \fBimedit\fR, examined by
+\fBimexamine\fR, operated upon by \fBimarith\fR, graphed by \fBimplot\fR,
+and displayed by \fBdisplay\fR.
+
+At the time of introducing this task, generic tools for creating
+pixel masks have yet to be written. There are two ways to create a
+mask in V2.10. First if a regular integer image can be created
+then it can be converted to pixel list format with \fBimcopy\fR:
+
+.nf
+ cl> imcopy template plfile.pl
+.fi
+
+by specifically using the .pl extension on output. Other programs that
+can create integer images (such \fBmkpattern\fR or \fBccdred.badpiximage\fR)
+can create the pixel list file directly by simply using the ".pl"
+extension in the output image name.
+
+To use pixel masks with \fBcombine\fR one must associate a pixel
+mask file with an image by entering the pixel list file name in the
+image header under the keyword BPM (bad pixel mask). This can be
+done with \fBhedit\fR. Note that the same pixel mask may be associated
+with more than one image as might be the case if the mask represents
+defects in the detector used to obtain the images.
+
+If a pixel mask is associated with an image the mask is used when the
+\fImasktype\fR parameter is set to a value other than "none". Note that
+when it is set to "none" mask information is not used even if it exists for
+the image. The values of \fImasktype\fR which apply masks are "goodvalue",
+"badvalue", "goodbits", and "badbits". They are used in conjunction with
+the \fImaskvalue\fR parameter. When the mask type is "goodvalue" the
+pixels with mask values matching the specified value are included in
+combining and all others are rejected. Similarly, for a mask type of
+"badvalue" the pixels with mask values matching the specified value are
+rejected and all others are accepted. The bit types are useful for
+selecting a combination of attributes in a mask consisting of bit flags.
+The mask value is still an integer but is interpreted by bitwise comparison
+with the values in the mask file.
+
+If a mask operation is specified and an image has no mask image associated
+with it then the mask values are taken as all zeros. In those cases be
+careful that zero is an accepted value otherwise the entire image will be
+rejected.
+
+
+THRESHOLD REJECTION
+
+In addition to rejecting masked pixels, pixels in the unscaled input
+images which are below or above the thresholds given by the parameters
+\fIlthreshold\fR and \fIhthreshold\fR are rejected. Values of INDEF
+mean that no threshold value is applied. Threshold rejection may be used
+to exclude very bad pixel values or as an alternative way of masking
+images. In the latter case one can use a task like \fBimedit\fR
+or \fBimreplace\fR to set parts of the images to be excluded to some
+very low or high magic value.
+
+
+REJECTION ALGORITHMS
+
+The \fIreject\fR parameter selects a type of rejection operation to
+be applied to pixels not masked or thresholded. If no rejection
+operation is desired the value "none" is specified.
+
+MINMAX
+.in 4
+A specified fraction of the highest and lowest pixels are rejected.
+The fraction is specified as the number of high and low pixels, the
+\fInhigh\fR and \fInlow\fR parameters, when data from all the input images
+are used. If pixels have been rejected by offseting, masking, or
+thresholding then a matching fraction of the remaining pixels, truncated
+to an integer, are used. Thus,
+
+.nf
+ nl = n * nlow/nimages + 0.001
+ nh = n * nhigh/nimages + 0.001
+.fi
+
+where n is the number of pixels surviving offseting, masking, and
+thresholding, nimages is the number of input images, nlow and nhigh
+are task parameters and nl and nh are the final number of low and
+high pixels rejected by the algorithm. The factor of 0.001 is to
+adjust for rounding of the ratio.
+
+As an example with 10 input images and specifying one low and two high
+pixels to be rejected the fractions to be rejected are 0.1 and 0.2
+and the number rejected as a function of n is:
+
+.nf
+ n 0 1 2 3 4 5 6 7 8 9 10
+ nl 0 0 0 0 0 1 1 1 1 1 2
+ nh 0 0 0 0 0 0 0 0 0 0 1
+.fi
+
+.in -4
+CCDCLIP
+.in 4
+If the images are obtained using a CCD with known read out noise, gain, and
+sensitivity noise parameters and they have been processed to preserve the
+relation between data values and photons or electrons then the noise
+characteristics of the images are well defined. In this model the sigma in
+data values at a pixel with true value <I>, as approximated by the median
+or average with the lowest and highest value excluded, is given by:
+
+.nf
+ sigma = ((rn / g) ** 2 + <I> / g + (s * <I>) ** 2) ** 1/2
+.fi
+
+where rn is the read out noise in electrons, g is the gain in
+electrons per data value, s is a sensitivity noise given as a fraction,
+and ** is the exponentiation operator. Often the sensitivity noise,
+due to uncertainties in the pixel sensitivities (for example from the
+flat field), is not known in which case a value of zero can be used.
+See the task \fBstsdas.wfpc.noisemodel\fR for a way to determine
+these vaues (though that task expresses the read out noise in data
+numbers and the sensitivity noise parameter as a percentage).
+
+The read out noise is specified by the \fIrdnoise\fR parameter. The value
+may be a numeric value to be applied to all the input images or a image
+header keyword containing the value for each image. Similarly, the
+parameter \fIgain\fR specifies the gain as either a value or image header
+keyword and the parameter \fIsnoise\fR specifies the sensitivity
+noise parameter as either a value or image header keyword.
+
+The algorithm operates on each output pixel independently. It starts by
+taking the median or unweighted average (excluding the minimum and maximum)
+of the unrejected pixels provided there are at least two input pixels. The
+expected sigma is computed from the CCD noise parameters and pixels more
+that \fIlsigma\fR times this sigma below or \fIhsigma\fR times this sigma
+above the median or average are rejected. The process is then iterated
+until no further pixels are rejected. If the average is used as the
+estimator of the true value then after the first round of rejections the
+highest and lowest values are no longer excluded. Note that it is possible
+to reject all pixels if the average is used and is sufficiently skewed by
+bad pixels such as cosmic rays.
+
+If there are different CCD noise parameters for the input images
+(as might occur using the image header keyword specification) then
+the sigmas are computed for each pixel from each image using the
+same estimated true value.
+
+If the images are scaled and shifted and the \fIsigscale\fR threshold
+is exceedd then a sigma is computed for each pixel based on the
+image scale parameters; i.e. the median or average is scaled to that of the
+original image before computing the sigma and residuals.
+
+After rejection the number of retained pixels is checked against the
+\fInkeep\fR parameter. If there are fewer pixels retained than specified
+by this parameter the pixels with the smallest residuals in absolute
+value are added back. If there is more than one pixel with the same
+absolute residual (for example the two pixels about an average
+or median of two will have the same residuals) they are all added
+back even if this means more than \fInkeep\fR pixels are retained.
+Note that the \fInkeep\fR parameter only applies to the pixels used
+by the clipping rejection algorithm and does not apply to threshold
+or bad pixel mask rejection.
+
+This is the best clipping algorithm to use if the CCD noise parameters are
+adequately known. The parameters affecting this algorithm are \fIreject\fR
+to select this algorithm, \fImclip\fR to select the median or average for
+the center of the clipping, \fInkeep\fR to limit the number of pixels
+rejected, the CCD noise parameters \fIrdnoise, gain\fR and \fIsnoise\fR,
+\fIlsigma\fR and \fIhsigma\fR to select the clipping thresholds,
+and \fIsigscale\fR to set the threshold for making corrections to the sigma
+calculation for different image scale factors.
+
+.in -4
+CRREJECT
+.in 4
+This algorithm is identical to "ccdclip" except that only pixels above
+the average are rejected based on the \fIhsigma\fR parameter. This
+is appropriate for rejecting cosmic ray events and works even with
+two images.
+
+.in -4
+SIGCLIP
+.in 4
+The sigma clipping algorithm computes at each output pixel the median or
+average excluding the high and low values and the sigma about this
+estimate. There must be at least three input pixels, though for this method
+to work well there should be at least 10 pixels. Values deviating by more
+than the specified sigma threshold factors are rejected. These steps are
+repeated, except that after the first time the average includes all values,
+until no further pixels are rejected or there are fewer than three pixels.
+
+After rejection the number of retained pixels is checked against the
+\fInkeep\fR parameter. If there are fewer pixels retained than specified
+by this parameter the pixels with the smallest residuals in absolute
+value are added back. If there is more than one pixel with the same
+absolute residual (for example the two pixels about an average
+or median of two will have the same residuals) they are all added
+back even if this means more than \fInkeep\fR pixels are retained.
+Note that the \fInkeep\fR parameter only applies to the pixels used
+by the clipping rejection algorithm and does not apply to threshold
+or bad pixel mask rejection.
+
+The parameters affecting this algorithm are \fIreject\fR to select
+this algorithm, \fImclip\fR to select the median or average for the
+center of the clipping, \fInkeep\fR to limit the number of pixels
+rejected, \fIlsigma\fR and \fIhsigma\fR to select the
+clipping thresholds, and \fIsigscale\fR to set the threshold for
+making corrections to the sigma calculation for different image scale
+factors.
+
+.in -4
+AVSIGCLIP
+.in 4
+The averaged sigma clipping algorithm assumes that the sigma about the
+median or mean (average excluding the low and high values) is proportional
+to the square root of the median or mean at each point. This is
+described by the equation:
+
+.nf
+ sigma(column,line) = sqrt (gain(line) * signal(column,line))
+.fi
+
+where the \fIestimated\fR signal is the mean or median (hopefully excluding
+any bad pixels) and the gain is the \fIestimated\fR proportionality
+constant having units of photons/data number.
+
+This noise model is valid for images whose values are proportional to the
+number of photons recorded. In effect this algorithm estimates a
+detector gain for each line with no read out noise component when
+information about the detector noise parameters are not known or
+available. The gain proportionality factor is computed
+independently for each output line by averaging the square of the residuals
+(at points having three or more input values) scaled by the median or
+mean. In theory the proportionality should be the same for all rows but
+because of the estimating process will vary somewhat.
+
+Once the proportionality factor is determined, deviant pixels exceeding the
+specified thresholds are rejected at each point by estimating the sigma
+from the median or mean. If any values are rejected the median or mean
+(this time not excluding the extreme values) is recomputed and further
+values rejected. This is repeated until there are no further pixels
+rejected or the number of remaining input values falls below three. Note
+that the proportionality factor is not recomputed after rejections.
+
+If the images are scaled differently and the sigma scaling correction
+threshold is exceedd then a correction is made in the sigma
+calculations for these differences, again under the assumption that
+the noise in an image scales as the square root of the mean intensity.
+
+After rejection the number of retained pixels is checked against the
+\fInkeep\fR parameter. If there are fewer pixels retained than specified
+by this parameter the pixels with the smallest residuals in absolute
+value are added back. If there is more than one pixel with the same
+absolute residual (for example the two pixels about an average
+or median of two will have the same residuals) they are all added
+back even if this means more than \fInkeep\fR pixels are retained.
+Note that the \fInkeep\fR parameter only applies to the pixels used
+by the clipping rejection algorithm and does not apply to threshold
+or bad pixel mask rejection.
+
+This algorithm works well for even a few input images. It works better if
+the median is used though this is slower than using the average. Note that
+if the images have a known read out noise and gain (the proportionality
+factor above) then the "ccdclip" algorithm is superior. The two algorithms
+are related in that the average sigma proportionality factor is an estimate
+of the gain.
+
+The parameters affecting this algorithm are \fIreject\fR to select
+this algorithm, \fImclip\fR to select the median or average for the
+center of the clipping, \fInkeep\fR to limit the number of pixels
+rejected, \fIlsigma\fR and \fIhsigma\fR to select the
+clipping thresholds, and \fIsigscale\fR to set the threshold for
+making corrections to the sigma calculation for different image scale
+factors.
+
+.in -4
+PCLIP
+.in 4
+The percentile clipping algorithm is similar to sigma clipping using the
+median as the center of the distribution except that, instead of computing
+the sigma of the pixels from the CCD noise parameters or from the data
+values, the width of the distribution is characterized by the difference
+between the median value and a specified "percentile" pixel value. This
+width is then multipled by the scale factors \fIlsigma\fR and \fIhsigma\fR
+to define the clipping thresholds above and below the median. The clipping
+is not iterated.
+
+The pixel values at each output point are ordered in magnitude and the
+median is determined. In the case of an even number of pixels the average
+of the two middle values is used as the median value and the lower or upper
+of the two is the median pixel when counting from the median pixel to
+selecting the percentile pixel. The parameter \fIpclip\fR selects the
+percentile pixel as the number (if the absolute value is greater
+than unity) or fraction of the pixels from the median in the ordered set.
+The direction of the percentile pixel from the median is set by the sign of
+the \fIpclip\fR parameter with a negative value signifying pixels with
+values less than the median. Fractional values are internally converted to
+the appropriate number of pixels for the number of input images. A minimum
+of one pixel and a maximum corresponding to the extreme pixels from the
+median are enforced. The value used is reported in the log output. Note
+that the same percentile pixel is used even if pixels have been rejected by
+offseting, masking, or thresholding; for example, if the 3nd pixel below
+the median is specified then the 3rd pixel will be used whether there are
+10 pixels or 5 pixels remaining after the preliminary steps.
+
+Some examples help clarify the definition of the percentile pixel. In the
+examples assume 10 pixels. The median is then the average of the
+5th and 6th pixels. A \fIpclip\fR value of 2 selects the 2nd pixel
+above the median (6th) pixel which is the 8th pixel. A \fIpclip\fR
+value of -0.5 selects the point halfway between the median and the
+lowest pixel. In this case there are 4 pixels below the median,
+half of that is 2 pixels which makes the percentile pixel the 3rd pixel.
+
+The percentile clipping algorithm is most useful for clipping small
+excursions, such as the wings of bright objects when combining
+disregistered observations for a sky flat field, that are missed when using
+the pixel values to compute a sigma. It is not as powerful, however, as
+using the CCD noise parameters (provided they are accurately known) to clip
+about the median.
+
+The parameters affecting this algorithm are \fIreject\fR to select this
+algorithm, \fIpclip\fR to select the percentile pixel, \fInkeep\fR to limit
+the number of pixels rejected, and \fIlsigma\fR and \fIhsigma\fR to select
+the clipping thresholds.
+
+.in -4
+GROW REJECTION
+
+Neighbors of pixels rejected by the rejection algorithms along image lines
+may also be rejected. The number of neighbors to be rejected on either
+side is specified by the \fIgrow\fR parameter. The rejection only
+applies to neighbors along each image line. This is because the
+task operates independently on each image line and does not have the
+ability to go back to previous lines or maintain a list of rejected
+pixels to later lines.
+
+This rejection step is also checked against the \fInkeep\fR parameter
+and only as many pixels as would not violate this parameter are
+rejected. Unlike it's application in the rejection algorithms at
+this stage there is no checking on the magnitude of the residuals
+and the pixels retained which would otherwise be rejected are randomly
+selected.
+
+
+COMBINING
+
+After all the steps of offsetting the input images, masking pixels,
+threshold rejection, scaling, and applying a rejection algorithms the
+remaining pixels are combined and output. The pixels may be combined
+by computing the median or by computing a weighted average.
+
+
+SIGMA OUTPUT
+
+In addition to the combined image and optional sigma image may be
+produced. The sigma computed is the standard deviation, corrected for a
+finite population by a factor of n/(n-1), of the unrejected input pixel
+values about the output combined pixel values.
+.ih
+EXAMPLES
+1. To average and median images without any other features:
+
+.nf
+ cl> combine obj* avg combine=average reject=none
+ cl> combine obj* med combine=median reject=none
+.fi
+
+2. To reject cosmic rays:
+
+.nf
+ cl> combine obs1,obs2 Obs reject=crreject rdnoise=5.1, gain=4.3
+.fi
+
+3. To make a grid for display purposes with 21 64x64 images:
+
+.nf
+ cl> combine @list grid offset="grid 5 65 5 65"
+.fi
+
+4. To apply a mask image with good pixels marked with a zero value and
+ bad pixels marked with a value of one:
+
+.nf
+ cl> hedit ims* bpm badpix.pl add+ ver-
+ cl> combine ims* final combine=median masktype=goodval
+.fi
+
+5. To scale image by the exposure time and then adjust for varying
+ sky brightness and make a weighted average:
+
+.nf
+ cl> combine obj* avsig combine=average reject=avsig \
+ >>> scale=exp zero=mode weight=exp expname=exptime
+.fi
+.ih
+TIME REQUIREMENTS
+The following times were obtain with a Sun 4/470. The tests combine
+1000x200 images consisting of Poisson noise and cosmic rays generated
+with the \fBartdata\fR package. The times, especially the total time,
+are approximate and depend on user loads.
+
+.nf
+IMAGES: Number of images (1000x200) and datatype (R=real, S=short)
+COMBINE: Combine option
+REJECT: Rejection option with grow = 0
+ minmax: nlow = 1, nhigh = 1
+ ccdclip: lsigma = 3., hsigma = 3, sigscale = 0.
+ sigclip: lsigma = 3., hsigma = 3, sigscale = 0.
+ avsigclip: lsigma = 3., hsigma = 3, sigscale = 0.
+ pclip: lsigma = 3., hsigma = 3, pclip = -0.5
+ /a: mclip = no (clip about the average)
+ /m: mclip = yes (clip about the median)
+O M T S: Features used (Y=yes, N=no)
+O: offset = "grid 5 10 2 10"
+M: masktype = goodval, maskval = 0
+ Pixel mask has 2 bad lines and 20 bad columns
+T: lthreshold = INDEF, hthreshold = 1100.
+S: scale = mode, zero = none, weight = mode
+TIME: cpu time in seconds, total time in minutes and seconds
+
+
+IMAGES COMBINE REJECT O M T S TIME
+
+ 10R average none N N N N 1.3 0:08
+ 10R average minmax N N N N 4.3 0:10
+ 10R average pclip N N N N 17.9 0:32
+ 10R average ccdclip/a N N N N 11.6 0:21
+ 10R average crreject/a N N N N 11.4 0:21
+ 10R average sigclip/a N N N N 13.6 0:29
+ 10R average avsigclip/a N N N N 15.9 0:35
+ 10R average ccdclip/m N N N N 16.9 0:32
+ 10R average crreject/m N N N N 17.0 0:28
+ 10R average sigclip/m N N N N 19.6 0:42
+ 10R average avsigclip/m N N N N 20.6 0:43
+
+ 10R median none N N N N 6.8 0:17
+ 10R median minmax N N N N 7.8 0:15
+ 10R median pclip N N N N 16.9 1:00
+ 10R median ccdclip/a N N N N 18.0 0:34
+ 10R median crreject/a N N N N 17.7 0:30
+ 10R median sigclip/a N N N N 21.1 1:13
+ 10R median avsigclip/a N N N N 23.1 0:41
+ 10R median ccdclip/m N N N N 16.1 0:27
+ 10R median crreject/m N N N N 16.0 0:27
+ 10R median sigclip/m N N N N 18.1 0:29
+ 10R median avsigclip/m N N N N 19.6 0:32
+
+ 10R average none N N N Y 6.1 0:36
+ 10R median none N N N Y 10.4 0:49
+ 10R median pclip N N N Y 20.4 1:10
+ 10R median ccdclip/m N N N Y 19.5 0:36
+ 10R median avsigclip/m N N N Y 23.0 1:06
+
+ 10R average none N Y N N 3.5 0:12
+ 10R median none N Y N N 8.9 0:21
+ 10R median pclip N Y N N 19.9 0:45
+ 10R median ccdclip/m N Y N N 18.0 0:44
+ 10R median avsigclip/m N Y N N 20.9 0:28
+
+ 10R average none Y N N N 4.3 0:13
+ 10R median none Y N N N 9.6 0:21
+ 10R median pclip Y N N N 21.8 0:54
+ 10R median ccdclip/m Y N N N 19.3 0:44
+ 10R median avsigclip/m Y N N N 22.8 0:51
+
+ 10R average none Y Y Y Y 10.8 0:22
+ 10R median none Y Y Y Y 16.1 0:28
+ 10R median pclip Y Y Y Y 27.4 0:42
+ 10R median ccdclip/m Y Y Y Y 25.5 0:39
+ 10R median avsigclip/m Y Y Y Y 28.9 0:44
+
+ 10S average none N N N N 2.2 0:06
+ 10S average minmax N N N N 4.6 0:12
+ 10S average pclip N N N N 18.1 0:33
+.fi
+.ih
+REVISIONS
+.ls COMBINE V2.10.2
+The weighting was changed from using the square root of the exposure time
+or image statistics to using the values directly. This corresponds
+to variance weighting. Other options for specifying the scaling and
+weighting factors were added; namely from a file or from a different
+image header keyword. The \fInkeep\fR parameter was added to allow
+controlling the maximum number of pixels to be rejected by the clipping
+algorithms. The \fIsnoise\fR parameter was added to include a sensitivity
+or scale noise component to the noise model. Errors will now delete
+the output images.
+.le
+.ls COMBINE V2.10
+This task was greatly revised to provide many new features. These features
+are:
+
+.nf
+ o Bad pixel masks
+ o Combining offset and different size images
+ o Blank value for missing data
+ o Combining across the highest dimension (the project option)
+ o Separating threshold rejection, the rejection algorithms,
+ and the final combining statistic
+ o New CCDCLIP, CRREJECT, and PCLIP algorithms
+ o Rejection now may reject more than one pixel per output pixel
+ o Choice of a central median or average for clipping
+ o Choice of final combining operation
+ o Simultaneous multiplicative and zero point scaling
+.fi
+.le
+.ih
+LIMITATIONS
+Though this task is essentially not limited by the physical
+limits of the host (number of open files, amount of memory) there is a
+software limit in the IRAF virtual operating system of about 120 separate
+images which may be combined. To combine more images one may combine smaller
+groups and then combine those or one may stack the images into a higher
+dimensional image using \fBimstack\fR and use the \fIproject\fR option.
+.ih
+SEE ALSO
+image.imcombine, instruments, ccdtypes, icfit, ccdred, guide, darkcombine,
+flatcombine, zerocombine, onedspec.scombine wfpc.noisemodel
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/contents.ms b/noao/imred/quadred/src/quad/doc/contents.ms
new file mode 100644
index 00000000..8ba2624a
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/contents.ms
@@ -0,0 +1,34 @@
+.sp 1i
+.ps +2
+.ft B
+.ce
+Contents
+.sp 3
+.ps -2
+.ft R
+.sp
+1.\h'|0.4i'\fBIntroduction\fP\l'|5.6i.'\0\01
+.sp
+2.\h'|0.4i'\fBGetting Started\fP\l'|5.6i.'\0\02
+.sp
+3.\h'|0.4i'\fBProcessing Your Data\fP\l'|5.6i.'\0\05
+.br
+\h'|0.4i'3.1.\h'|0.9i'Combining Calibration Images\l'|5.6i.'\0\06
+.br
+\h'|0.4i'3.2.\h'|0.9i'Calibrations and Corrections\l'|5.6i.'\0\07
+.sp
+4.\h'|0.4i'\fBSpecial Processing Operations\fP\l'|5.6i.'\0\08
+.br
+\h'|0.4i'4.1.\h'|0.9i'Spectroscopic Flat Fields\l'|5.6i.'\0\08
+.br
+\h'|0.4i'4.2.\h'|0.9i'Illumination Corrections\l'|5.6i.'\0\09
+.br
+\h'|0.4i'4.3.\h'|0.9i'Sky Flat Fields\l'|5.6i.'\010
+.br
+\h'|0.4i'4.4.\h'|0.9i'Illumination Corrected Flat Fields\l'|5.6i.'\010
+.br
+\h'|0.4i'4.5.\h'|0.9i'Fringe Corrections\l'|5.6i.'\010
+.sp
+5.\h'|0.4i'\fBSummary\fP\l'|5.6i.'\011
+.sp
+\h'|0.4i'\fBReferences\fP\l'|5.6i.'\011
diff --git a/noao/imred/quadred/src/quad/doc/cosmicrays.hlp b/noao/imred/quadred/src/quad/doc/cosmicrays.hlp
new file mode 100644
index 00000000..c50a129f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/cosmicrays.hlp
@@ -0,0 +1,220 @@
+.help cosmicrays Dec87 noao.imred.ccdred
+.ih
+NAME
+cosmicrays -- Detect and replace cosmic rays
+.ih
+USAGE
+cosmicrays input output
+.ih
+PARAMETERS
+.ls input
+List of input images in which to detect cosmic rays.
+.le
+.ls output
+List of output images in which the detected cosmic rays will be replaced
+by an average of neighboring pixels. If the output image name differs
+from the input image name then a copy of the input image is made with
+the detected cosmic rays replaced. If no output images are specified
+then the input images are modified in place. In place modification of
+an input image also occurs when the output image name is the same as
+the input image name.
+.le
+.ls badpix = ""
+List of bad pixel files to be created, one for each input image. If no
+file names are given then no bad pixel file is created. The bad pixel
+file is a simple list of pixel coordinates for each replaced cosmic ray.
+This file may be used in conjunction with \fBbadpixelimage\fR to create
+a mask image.
+.le
+.ls ccdtype = ""
+If specified only the input images of the desired CCD image type will be
+selected.
+.le
+.ls threshold = 25.
+Detection threshold above the mean of the surrounding pixels for cosmic
+rays. The threshold will depend on the noise characteristics of the
+image and how weak the cosmic rays may be for detection. A typical value
+is 5 or more times the sigma of the background.
+.le
+.ls fluxratio = 2.
+The ratio (as a percent) of the mean neighboring pixel flux to the candidate
+cosmic ray pixel for rejection. The value depends on the seeing and the
+characteristics of the cosmic rays. Typical values are in the range
+2 to 10 percent.
+.le
+.ls npasses = 5
+Number of cosmic ray detection passes. Since only the locally strongest
+pixel is considered a cosmic ray, multiple detection passes are needed to
+detect and replace multiple pixel cosmic ray events.
+.le
+.ls window = 5
+Size of cosmic ray detection window. A square window of either 5 by 5 or
+7 by 7 is used to detect cosmic rays. The smaller window allows detection
+in the presence of greater background gradients but is less sensitive at
+discriminating multiple event cosmic rays from stars. It is also marginally
+faster.
+.le
+.ls interactive = yes
+Examine parameters interactively? A plot of the mean flux within the
+detection window (x100) vs the flux ratio (x100) is plotted and the user may
+set the flux ratio threshold, delete and undelete specific events, and
+examine specific events. This is useful for new data in which one is
+uncertain of an appropriate flux ratio threshold. Once determined the
+task need not be used interactively.
+.le
+.ls answer
+This parameter is used for interactive queries when processing a list of
+images. The responses may be "no", "yes", "NO", or "YES". The upper case
+responses permanently enable or disable the interactive review while
+the lower case reponses allow selective examination of certain input
+images.
+.le
+.ih
+OTHER PARAMETERS
+There are other parameters which may be defined by the package, as is the
+case with \fBccdred\fR, or as part of the task, as is the case with
+standalone version in the \fBgeneric\fR package.
+
+.ls verbose
+If yes then a time stamped log of the operation is printed on the standard
+output.
+.le
+.ls logfile
+If a log file is specified then a time stamped log of the operation is
+recorded.
+.le
+.ls plotfile
+If a plot file is specified then the graph of the flux ratio (x100) vs
+the mean flux (x100) is recorded as metacode. This may be spooled or examined
+later.
+.le
+.ls graphics = "stdgraph"
+Interactive graphic output device for interactive examination of the
+detection parameters.
+.le
+.ls cursor = ""
+Interactive graphics cursor input. If null the graphics display cursor
+is used, otherwise a file containing cursor input may be specified.
+.le
+.ls instrument
+The \fBccdred\fR instrument file is used for mapping header keywords and
+CCD image types.
+.le
+.ih
+CURSOR COMMANDS
+
+.nf
+d Mark candidate for replacement (applys to '+' points)
+q Quit and replace the selected pixels
+r Redraw the graph
+s Make a surface plot for the candidate nearest the cursor
+t Set the flux ratio threshold at the y cursor position
+u Mark candidate to not be replaced (applys to 'x' points)
+w Adjust the graph window (see \fBgtools\fR)
+.fi
+
+There are no colon commands except those for the windowing options (type
+:\help or see \fBgtools\fR).
+.ih
+DESCRIPTION
+Cosmic ray events in each input image are detected and replaced by the
+average of the four neighbors. The replacement may be performed
+directly on the input image if no output image is specified or if the
+output image name is the same as the input image name. If a new image
+is created it is a copy of the input image except for the replaced
+pixels. The processing keyword CRCOR is added to the output image
+header. Optional output includes a log file to which a processing log
+is appended, a verbose log output to the standard output (the same as
+that in the log file), a plot file showing the parameters of the
+detected cosmic ray candidates and the flux ratio threshold used, and a
+bad pixel file containing the coordinates of the replaced pixels. The
+bad pixel file may be used for plotting purposes or to create a mask
+image for display and analysis using the task \fBbadpiximage\fR. This
+bad pixel file will be replaced by the IRAF bad pixel facility when it
+becomes available. If one wants more than a simple mask image then by
+creating a different output image a difference image between the
+original and the modified image may be made using \fBimarith\fR.
+
+This task may be applied to an image previously processed to detect
+additional cosmic rays. A warning will be given (because of the
+CRCOR header parameter) and the previous processing header keyword will
+be overwritten.
+
+The cosmic ray detection algorithm consists of the following steps.
+First a pixel must be the brightest pixel within the specified
+detection window (either 5x5 or 7x7). The mean flux in the surrounding
+pixels with the second brightest pixel excluded (which may also be a
+cosmic ray event) is computed and the candidate pixel must exceed this
+mean by the amount specified by the parameter \fIthreshold\fR. A plane
+is fit to the border pixels of the window and the fitted background is
+subtracted. The mean flux (now background subtracted) and the ratio of
+this mean to the cosmic ray candidate (the brightest pixel) are
+computed. The mean flux (x100) and the ratio (x100) are recorded for
+interactive examination if desired.
+
+Once the list of cosmic ray candidates has been created and a threshold
+for the flux ratio established (either by the parameter \fIfluxratio\fR
+or modified interactively) the pixels with ratios below the threshold
+are replaced in the output by the average of the four neighboring pixels
+(with the second strongest pixel in the detection window excluded if it is
+one of these pixels). Additonal pixels may then be detected and replaced
+in further passes as specified by the parameter \fInpasses\fR. Note that
+only pixels in the vicinity of replaced pixels need be considered in
+further passes.
+
+The division between the peaks of real objects and cosmic rays is made
+based on the flux ratio between the mean flux (excluding the center
+pixel and the second strongest pixel) and the candidate pixel. This
+threshold depends on the point spread function and the distribution of
+multiple cosmic ray events and any additional neighboring light caused
+by the events. This threshold is not strongly coupled to small changes
+in the data so that once it is set for a new type of image data it may
+be used for similar images. To set it initially one may examine the
+scatter plot of the flux ratio as a function of the mean flux. This
+may be done interactively or from the optional plot file produced.
+
+When the interactive flag is set the user is queried for each image.
+Responses may be made for specific images or for all images by using
+lower or upper case answers respectively. When the parameters are
+examined interactively the user may change the flux ratio threshold
+('t' key). Changes made are stored in the parameter file and, thus,
+learned for further images. Pixels to be deleted are marked by crosses
+and pixels which are peaks of objects are marked by pluses. The user
+may explicitly delete or undelete any point if desired but this is only
+for special cases near the threshold. In the future keys for
+interactive display of the specific detections will be added.
+Currently a surface plot of any candidate may be displayed graphically
+in four 90 degree rotated views using the 's' key. Note that the
+initial graph does not show all the points some of which are clearly
+cosmic rays because they have negative mean flux or flux ratio. To
+view all data one must rewindow the graph with the 'w' key or ":/"
+commands (see \fBgtools\fR).
+.ih
+EXAMPLES
+1. To replace cosmic rays in a set of images ccd*:
+
+.nf
+ cl> cosmicrays ccd* new//ccd*
+ ccd001: Examine parameters interactively? (yes):
+ [A scatter plot graph is made. One can adjust the threshold.]
+ [Looking at a few points using the 's' key can be instructive.]
+ [When done type 'q'.]
+ ccd002: Examine parameters interactively? (yes): NO
+ [No further interactive examination is done.]
+.fi
+
+After cleaning one typically displays the images and possibly blinks them.
+A difference image or mask image may also be created.
+
+2. To create a mask image a bad pixel file must be specified. In the
+following we replace the cosmic rays in place and create a bad pixel
+file and mask image:
+
+.nf
+ cl> cosmicrays ccd001 ccd001 badpix=ccd001.bp
+ cl> badpiximage ccd001.bp ccd001 ccd001bp
+.fi
+.ih
+SEE ALSO
+badpixelimage gtools
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/darkcombine.hlp b/noao/imred/quadred/src/quad/doc/darkcombine.hlp
new file mode 100644
index 00000000..ef9eb81c
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/darkcombine.hlp
@@ -0,0 +1,125 @@
+.help darkcombine Sept93 arcon.quad
+.ih
+NAME
+darkcombine -- Combine and process dark count images
+.ih
+USAGE
+darkcombine input
+.ih
+PARAMETERS
+.ls input
+List of dark count images to combine. The \fIccdtype\fR parameter
+may be used to select the zero level images from a list containing all
+types of data.
+.le
+.ls output = "Dark"
+Output dark count root image name.
+.le
+.ls combine = "average" (average|median)
+Type of combining operation performed on the final set of pixels (after
+rejection). The choices are
+"average" or "median". The median uses the average of the two central
+values when the number of pixels is even.
+.le
+.ls reject = "avsigclip" (none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip)
+Type of rejection operation. See \fBcombine\fR for details.
+.le
+.ls ccdtype = "zero"
+CCD image type to combine. If no image type is given then all input images
+are combined.
+.le
+.ls process = no
+Process the input images before combining?
+.le
+.ls delete = no
+Delete input images after combining? Only those images combined are deleted.
+.le
+.ls clobber = no
+Clobber existing output images?
+.le
+.ls scale = "none" (none|mode|median|mean|exposure)
+Multiplicative image scaling to be applied. The choices are none, scale
+by the mode, median, or mean of the specified statistics section, or scale
+by the exposure time given in the image header.
+.le
+.ls statsec = ""
+Section of images to use in computing image statistics for scaling.
+If no section is given then the entire region of the image is
+sampled (for efficiency the images are sampled if they are big enough).
+.le
+
+.ce
+Algorithm Parameters
+.ls nlow = 1, nhigh = 1 (minmax)
+The number of low and high pixels to be rejected by the "minmax" algorithm.
+.le
+.ls nkeep = 1
+The minimum number of pixels to retain or the maximum number to reject
+when using the clipping algorithms (ccdclip, crreject, sigclip,
+avsigclip, or pclip). When given as a positive value this is the minimum
+number to keep. When given as a negative value the absolute value is
+the maximum number to reject. This is actually converted to a number
+to keep by adding it to the number of images.
+.le
+.ls mclip = yes (ccdclip, crreject, sigclip, avsigcliip)
+Use the median as the estimate for the true intensity rather than the
+average with high and low values excluded in the "ccdclip", "crreject",
+"sigclip", and "avsigclip" algorithms? The median is a better estimator
+in the presence of data which one wants to reject than the average.
+However, computing the median is slower than the average.
+.le
+.ls lsigma = 3., hsigma = 3. (ccdclip, crreject, sigclip, avsigclip, pclip)
+Low and high sigma clipping factors for the "ccdclip", "crreject", "sigclip",
+"avsigclip", and "pclip" algorithms. They multiply a "sigma" factor
+produced by the algorithm to select a point below and above the average or
+median value for rejecting pixels. The lower sigma is ignored for the
+"crreject" algorithm.
+.le
+.ls rdnoise = "0.", gain = "1.", snoise = "0." (ccdclip, crreject)
+CCD readout noise in electrons, gain in electrons/DN, and sensitivity noise
+as a fraction. These parameters are used with the "ccdclip" and "crreject"
+algorithms. The values may be either numeric or an image header keyword
+which contains the value.
+.le
+.ls pclip = -0.5 (pclip)
+Percentile clipping algorithm parameter. If greater than
+one in absolute value then it specifies a number of pixels above or
+below the median to use for computing the clipping sigma. If less
+than one in absolute value then it specifies the fraction of the pixels
+above or below the median to use. A positive value selects a point
+above the median and a negative value selects a point below the median.
+The default of -0.5 selects approximately the quartile point.
+See \fBcombine\fR for further details.
+.le
+.ls blank = 0.
+Output value to be used when there are no pixels.
+.le
+.ih
+DESCRIPTION
+The dark count images in the input image list are combined.
+The input images may be processed first if desired.
+The original images may be deleted automatically if desired.
+
+This task is a script which applies \fBquadproc\fR and \fBcombine\fR. The
+parameters and combining algorithms are described in detail in the help for
+\fBcombine\fR. This script has default parameters specifically set for
+dark count images and simplifies the combining parameters. There are other
+combining options not included in this task. For these additional
+features, such as thresholding, offseting, masking, and projecting, use
+\fBcombine\fR.
+
+The version of \fBdarkcombine\fR in the \fBquad\fR package differs from that
+in \fBccdred\fR in that \fBquadproc\fR rather than \fBccdproc\fR is used to
+process the images if this is requested. The \fBquad\fR version MUST be
+used if process=yes and the input list contains any multi-readout images which
+have not been overscan corrected and trimmed.
+.ih
+EXAMPLES
+1. The image data contains four dark count images. To automatically select
+them and combine them as a background job using the default combining algorithm:
+
+ cl> darkcombine ccd*.imh&
+.ih
+SEE ALSO
+quadproc, combine
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/flatcombine.hlp b/noao/imred/quadred/src/quad/doc/flatcombine.hlp
new file mode 100644
index 00000000..c463655d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/flatcombine.hlp
@@ -0,0 +1,139 @@
+.help flatcombine Sept93 arcon.quad
+.ih
+NAME
+flatcombine -- Combine and process flat field images
+.ih
+USAGE
+flatcombine input
+.ih
+PARAMETERS
+.ls input
+List of flat field images to combine. The \fIccdtype\fR parameter
+may be used to select the flat field images from a list containing all
+types of data.
+.le
+.ls output = "Flat"
+Output flat field root image name. The subset ID is appended.
+.le
+.ls combine = "average" (average|median)
+Type of combining operation performed on the final set of pixels (after
+rejection). The choices are
+"average" or "median". The median uses the average of the two central
+values when the number of pixels is even.
+.le
+.ls reject = "avsigclip" (none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip)
+Type of rejection operation. See \fBcombine\fR for details.
+.le
+.ls ccdtype = "flat"
+CCD image type to combine. If no image type is given then all input images
+are combined.
+.le
+.ls process = no
+Process the input images before combining?
+.le
+.ls subsets = yes
+Combine images by subset parameter? If yes then the input images are
+grouped by subset parameter and each group combined into a separate output
+image. The subset identifier is appended to the output and sigma image
+names. See \fBsubsets\fR for more on the subset parameter. This is generally
+used with flat field images.
+.le
+.ls delete = no
+Delete input images after combining? Only those images combined are deleted.
+.le
+.ls clobber = no
+Clobber existing output images?
+.le
+.ls scale = "none" (none|mode|median|mean|exposure)
+Multiplicative image scaling to be applied. The choices are none, scale
+by the mode, median, or mean of the specified statistics section, or scale
+by the exposure time given in the image header.
+.le
+.ls statsec = ""
+Section of images to use in computing image statistics for scaling.
+If no section is given then the entire region of the image is
+sampled (for efficiency the images are sampled if they are big enough).
+.le
+
+.ce
+Algorithm Parameters
+.ls nlow = 1, nhigh = 1 (minmax)
+The number of low and high pixels to be rejected by the "minmax" algorithm.
+.le
+.ls nkeep = 1
+The minimum number of pixels to retain or the maximum number to reject
+when using the clipping algorithms (ccdclip, crreject, sigclip,
+avsigclip, or pclip). When given as a positive value this is the minimum
+number to keep. When given as a negative value the absolute value is
+the maximum number to reject. This is actually converted to a number
+to keep by adding it to the number of images.
+.le
+.ls mclip = yes (ccdclip, crreject, sigclip, avsigcliip)
+Use the median as the estimate for the true intensity rather than the
+average with high and low values excluded in the "ccdclip", "crreject",
+"sigclip", and "avsigclip" algorithms? The median is a better estimator
+in the presence of data which one wants to reject than the average.
+However, computing the median is slower than the average.
+.le
+.ls lsigma = 3., hsigma = 3. (ccdclip, crreject, sigclip, avsigclip, pclip)
+Low and high sigma clipping factors for the "ccdclip", "crreject", "sigclip",
+"avsigclip", and "pclip" algorithms. They multiply a "sigma" factor
+produced by the algorithm to select a point below and above the average or
+median value for rejecting pixels. The lower sigma is ignored for the
+"crreject" algorithm.
+.le
+.ls rdnoise = "0.", gain = "1.", snoise = "0." (ccdclip, crreject)
+CCD readout noise in electrons, gain in electrons/DN, and sensitivity noise
+as a fraction. These parameters are used with the "ccdclip" and "crreject"
+algorithms. The values may be either numeric or an image header keyword
+which contains the value.
+.le
+.ls pclip = -0.5 (pclip)
+Percentile clipping algorithm parameter. If greater than
+one in absolute value then it specifies a number of pixels above or
+below the median to use for computing the clipping sigma. If less
+than one in absolute value then it specifies the fraction of the pixels
+above or below the median to use. A positive value selects a point
+above the median and a negative value selects a point below the median.
+The default of -0.5 selects approximately the quartile point.
+See \fBcombine\fR for further details.
+.le
+.ls blank = 1.
+Output value to be used when there are no pixels.
+.le
+.ih
+DESCRIPTION
+The flat field images in the input image list are combined. If there
+is more than one subset (such as a filter or grating) then the input
+flat field images are grouped by subset and an combined separately.
+The input images may be processed first if desired. However if all
+zero level bias effects are linear then this is not necessary and some
+processing time may be saved. The original images may be deleted
+automatically if desired.
+
+This task is a script which applies \fBquadproc\fR and \fBcombine\fR. The
+parameters and combining algorithms are described in detail in the help for
+\fBcombine\fR. This script has default parameters specifically set for
+flat field images and simplifies the combining parameters. There are other
+combining options not included in this task. For these additional
+features, such as thresholding, offseting, masking, and projecting, use
+\fBcombine\fR.
+
+The version of \fBzerocombine\fR in the \fBquad\fR package differs from that
+in \fBccdred\fR in that \fBquadproc\fR rather than \fBccdproc\fR is used to
+process the images if this is requested. The \fBquad\fR version MUST be
+used if process=yes and the input list contains any multi-readout images which
+have not been overscan corrected and trimmed.
+.ih
+EXAMPLES
+1. The image data contains four flat field images for three filters.
+To automatically select them and combine them as a background job
+using the default combining algorithm:
+
+ cl> flatcombine ccd*.imh&
+
+The final images are "FlatV", "FlatB", and "FlatR".
+.ih
+SEE ALSO
+quadproc, combine, subsets
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/flatfields.hlp b/noao/imred/quadred/src/quad/doc/flatfields.hlp
new file mode 100644
index 00000000..94766960
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/flatfields.hlp
@@ -0,0 +1,177 @@
+.help flatfields Jun87 noao.imred.ccdred
+
+.ih
+NAME
+flatfields -- Discussion of CCD flat field calibrations
+.ih
+DESCRIPTION
+This topic describes the different types of CCD flat fields and
+the tasks available in the \fBccdred\fR and spectroscopy packages for
+creating them. Flat field calibration is the most important operation
+performed on CCD data. This operation calibrates the relative response
+of the detector at each pixel. In some cases this is as simple as
+taking a special type of observation called a flat field. However, in
+many cases this calibration observation must be corrected for
+iillumination, scanning, wavelength, and aperture effects.
+
+The discussion is in three sections; direct imaging, scan mode,
+and spectroscopy. Though there are many similarities between these
+modes of operation there are important differences in how corrections
+are applied to the basic flat field observations. The application of
+the flat field calibrations to the observations using \fBccdproc\fR is
+the same in all cases, however.
+.sh
+1. Direct Imaging
+The starting point for determining the flat field calibration is an
+observation of something which should have uniform response at all
+points on the detector. In addition the color of the light falling at
+each pixel should be the same as that in an observation so the same
+filter must be used when determining the flat field (the issue of the
+matching the color of the objects observed at the appropriate pixels is
+ignored here). The best calibration observation is of a blank sky. If
+an accurate blank sky observation can be obtained then this is all that
+is needed for a flat field calibration. This type of flat field might
+be called a \fIsky flat\fR, though this term is more often used for a
+type of flat field described below. There are two difficulties with
+this type of calibration; finding a really blank sky and getting a
+sufficiently accurate measurement without using all the observing
+time.
+
+It is usually not possible to get a blank sky observation accurate
+enough to calibrate the individual pixels without introducing
+undesirable noise. What is generally done is to use a lamp to either
+uniformly illuminate a part of the dome or directly illuminate the
+field of view. The first type of observation is called a \fIdome
+flat\fR and the second is called a \fIprojection flat\fR. We shall call
+both of these types of observations \fBlamp flat fields\fR. If the
+iillumination is truely uniform then these types of observations are
+sufficient for flat field calibration. To get a very accurate flat
+field many observations are made and then combined (see
+\fBflatcombine\fR).
+
+Unfortunately, it is sometimes the case that the lamp flat fields
+do not illuminate the telescope/detector in the same way as the actual
+observations. Calibrating with these flat fields will introduce a
+residual large scale iillumination pattern, though it will correctly
+calibrate the relative pixel responses locally. There are two ways to
+correct for this effect. The first is to correct the flat field
+observation. The second is to apply the uncorrected flat field to the
+observations and then apply an \fIiillumination\fR correction as a
+separate operation. The first is more efficient since it consists of a
+single correction applied to each observation but in some cases the
+approximate correction is desired immediately, the observation needed
+to make the correction has not been taken yet, or the residual
+iillumination error is not discovered until later.
+
+For the two methods there are two types of correction. One is to
+use a blank sky observation to correct for the residual iillumination
+pattern. This is different than using the sky observation directly as
+a flat field calibration in that only the large scale pattern is
+needed. Determining the large scale iillumination does not require high
+signal-to-noise at each pixel and faint objects in the image can be
+either eliminated or ignored. The second method is to remove the large
+scale shape from the lamp flat field. This is not as good as using a
+blank sky observation but, if there is no such observation and the
+iillumination pattern is essentially only in the lamp flat field, this
+may be sufficient.
+
+From the above two paragraphs one sees there are four options.
+There is a task in the \fBccdred\fR package for each of these options.
+To correct a lamp flat field observation by a blank sky observation,
+called a \fIsky flat\fR, the task is \fBmkskyflat\fR. To correct the
+flat field for its own large scale gradients, called an \fIiillumination
+flat\fR, the task is \fBmkillumflat\fR. To create a secondary
+correction to be applied to data processed with the lamp flat field
+image the tasks are \fBmkskycor\fR and \fBmkillumcor\fR which are,
+respectively, based on a blank sky observation and the lamp flat field
+iillumination pattern.
+
+With this introduction turn to the individual documentation for these
+four tasks for further details.
+.sh
+2. Scan Mode
+There are two types of scan modes supported by the \fBccdred\fR
+package; \fIshortscan\fR and \fIlongscan\fR (see \fBccdproc\fR for
+further details). They both affect the manner in which flat field
+calibrations are handled. The shortscan mode produces images which are
+the same as direct images except that the light recorded at each pixel
+was collected by a number of different pixels. This improves the flat
+field calibration. If the flat field images, of the same types
+described in the direct imaging section, are observed in the same way
+as all other observations, i.e. in scan mode, then there is no
+difference from direct imaging (except in the quality of the flat
+fields). There is a statistical advantage to observing the lamp or sky
+flat field without scanning and then numerically averaging to simulate
+the result of the scanning. This improves the accuracy of
+the flat fields and might possibly allow direct blank sky observations
+to be used for flat fields. The numerical scanning is done in
+\fBccdproc\fR by setting the appropriate scanning parameters.
+
+In longscan mode the CCD detector is read out in such a way that
+each output image pixel is the sum of the light falling on all pixels
+along the direction of the scan. This reduces the flat field calibration
+to one dimension, one response value for each point across the scan.
+The one dimensional calibration is obtained from a longscan observation
+by averaging all the readout lines.
+This is done automatically in \fBccdproc\fR by setting the appropriate
+parameters. In this case very good flat fields can be obtained from
+one or more blank sky observations or an unscanned lamp observation. Other
+corrections are not generally used.
+.sh
+3. Spectroscopy
+Spectroscopic flat fields differ from direct imaging in that the
+spectrum of the sky or lamp and transmission variations with wavelength
+are part of the observation. Application of such images will introduce
+the inverse of the spectrum and transmission into the observation. It
+also distorts the observed counts making signal-to-noise estimates
+invalid. This, and the low signal in the dispersed light, makes it
+difficult to use blank sky observations directly as flat fields. As
+with direct imaging, sky observation may be used to correct for
+iillumination errors if necessary. At sufficiently high dispersion the
+continuous lamp spectrum may be flat enough that the spectral signature
+of the lamp is not a problem. Alternatively, flux calibrating the
+spectra will also remove the flat field spectral signature. The
+spectroscopic flat fields also have to be corrected for regions outside
+of the slit or apertures to avoid bad response effects when applying
+the flat field calibration to the observations.
+
+The basic scheme for removing the spectral signature is to average
+all the lines or columns across the dispersion and within the aperture
+to form an estimate of the spectrum. In addition to the averaging, a
+smooth curve is fit to the lamp spectrum to remove noise. This smooth
+shape is then divided back into each line or column to eliminate the
+shape of the spectrum without changing the shape of the spectrum
+in the spatial direction or the small scale response variations.
+Regions outside of the apertures are replaced by unity.
+This method requires that the dispersion be aligned fairly close to
+either the CCD lines or columns.
+
+This scheme is used in both longslit and multiaperture spectra.
+The latter includes echelle, slitlets, aperture masks, and fiber feeds.
+For narrow apertures which do not have wider slits for the lamp
+exposures there may be problems with flexure and defining a good
+composite spectrum. The algorithm for longslit spectra is simpler and
+is available in the task \fBresponse\fR in the \fBlongslit\fR package.
+For multiaperture data there are problems of defining where the spectra
+lie and avoiding regions off of the aperture where there is no signal.
+The task which does this is \fBapnormalize\fR in the \fBapextract\fR
+package. Note that the lamp observations must first be processed
+explicitly for bias and dark count corrections.
+
+Longslit spectra may also suffer the same types of iillumination
+problems found in direct imaging. However, in this case the iillumination
+pattern is determined from sky observations (or the flat field itself)
+by finding the large scale pattern across the dispersion and at a number
+of wavelengths while avoiding the effects of night sky spectrum. The
+task which makes this type of correction in the \fBlongslit\fR package
+is \fBiillumination\fR. This produces an iillumination correction.
+To make sky flats or the other types of corrections image arithmetic
+is used. Note also that the sky observations must be explicitly
+processed through the flat field stage before computing the iillumination.
+.ih
+SEE ALSO
+.nf
+ccdproc, guide, mkillumcor, mkillumflat, mkskycor, mkskyflat
+apextract.apnormalize, longslit.response, longslit.iillumination
+.fi
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/guide.hlp b/noao/imred/quadred/src/quad/doc/guide.hlp
new file mode 100644
index 00000000..d7639a6f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/guide.hlp
@@ -0,0 +1,715 @@
+.help guide Sept93 arcon.quad
+.ce
+User's Guide to the QUAD Package
+.sh
+1. Introduction
+
+ This guide provides a brief description of the \fBquad\fR package including
+examples of its use for reducing simple CCD data. The \fBquad\fR package
+contains all the basic tasks necessary for the reduction of CCD data obtained
+using the CTIO array controller Arcon. It is based on the IRAF CCD reduction
+package \fBccdred\fR written by Frank Valdes. It incorporates a few special
+tasks needed to deal with the peculiarities of Arcon data but most of the
+routines are taken directly from the standard package. The way in which one
+uses the routines and the basic reduction recipe is unchanged.
+
+This guide is generic in that it is not tied to any particular type of data.
+There may be more specific guides (or "cookbooks") for your data. Detailed
+descriptions of the tasks and features of the package are provided in the help
+documentation for the package.
+
+With Arcon the CCD is often readout using four ("quad") or two ("dual")
+amplifiers in order to reduce readout time. A feature of such images is that
+each readout typically has a slightly different, DC bias level, gain, and
+readout noise. As a result both zero frames and uniformly illuminated
+exposures show a characteristic chequer board pattern, the sections of the
+image read through each amplifier having different levels. In addition, there
+will be a separate overscan strip, used to monitor the zero level, for each
+readout. The location of these overscan strips in the raw frame depends on
+which amplifiers are used (for more on this see \fBquadreadout\fR). Because
+of these peculiarities the \fBquad\fR package must be used for the first
+reduction steps, overscan correction and trimming, of multi-readout images;
+subsequent steps can be performed using \fBquad\fR or \fBccdred\fR. Either
+package can be used for the complete reduction of conventional single readout
+CCD images.
+
+ The purpose of \fBquad\fR package is to provide tools for the removal of
+all the "instrumental signatures" from CCD data taken with Arcon. The standard
+reduction operations are: replacement of bad columns and lines by interpolation
+from neighboring columns and lines; subtraction of a bias level
+determined from overscan or prescan columns or lines; subtraction of a
+zero level using a zero exposure time calibration image; subtraction
+of a dark count calibration image appropriately scaled to the dark time
+exposure; division by a scaled flat field calibration image; division
+by an iillumination image (derived from a blank sky image); subtraction
+of a scaled fringe image (also derived from a blank sky image); and
+trimming the image of unwanted lines or columns such as the overscan
+strip. Any set of these operations may be done simultaneously over a list of
+images in a highly efficient manner. The reduction operations are
+recorded in the image header and may also be logged on the terminal and
+in a log file.
+
+ The package also provides tools for combining multiple exposures
+of object and calibration images to improve the statistical accuracy of
+the observations and to remove transient bad pixels. The combining
+operation scales images of different exposure times, adjusts for
+variable sky background, statistically weights the images by their
+signal-to-noise, and provides a number of useful algorithms for
+detecting and rejecting transient bad pixels.
+
+ Other tasks are provided for listing reduction information about
+the images, deriving secondary calibration images (such as sky
+corrected flat fields or iillumination correction images), and easily
+setting the package parameters for different instruments.
+
+The \fBquad\fR package also includes some tasks which can be used for the
+examination of multi-readout images, prior to reducing them, by for instance
+calculating simple image statistics, generating histograms, etc.
+
+ There are several important features provided by the \fBccdred\fR package
+underpining \fBquad\fR, which makes the reduction of CCD images convenient;
+particularly to minimize record keeping. One of these is the ability to
+recognize the different types of CCD images. This ability allows the user to
+select a certain class of images to be processed or listed and allows the
+processing tasks to identify calibration images and process them differently
+from object images. The standard CCD image types are \fIobject\fR,
+\fIzero\fR level, \fIdark\fR count, and \fIflat\fR field. For more on
+the image types see \fBccdtypes\fR.
+
+ The tasks can also identify the different filters (or other subset
+parameter) which require different flat field images. This means you don't
+have to separate the images by filter and process each set separately.
+This feature is discussed further in \fBsubsets\fR.
+
+ The tasks keep track of the reduction steps completed on each
+image and ignore images which have been processed. This feature,
+along with recognizing the image types and subsets, makes it possible to
+specify all the images to a task with a wildcard template, such as
+"*.imh", rather than indicating each image by name. You will find this
+extremely important with large sets of observations.
+
+ A fundamental aspect of the package is that the processing
+modifies the images. In other words, the reduction operations are
+performed directly on the image. This "feature" further simplifies
+record keeping, frees the user from having to form unique output image
+names, and minimizes the amount of disk space required. There
+are two safety features in this process. First, the modifications do
+not take effect until the operation is completed on the image. This
+allows you to abort the task without messing up the image data and
+protects data if the computer crashes. The second feature is that
+there is a package parameter which may be set to make a backup of the
+input data with a particular prefix such as "orig" or "imdir$". This
+backup feature may be used when there is sufficient disk space, when learning
+to use the package, or just to be cautious.
+
+ In a similar effort to efficiently manage disk space, when combining
+images into a master object or calibration image there is an option to
+delete the input images upon completion of the combining operation.
+Generally this is desirable when there are many calibration exposures,
+such as zero level or flat field images, which are not used after they
+are combined into a final calibration image.
+
+ The following sections guide you through the basic use of the
+\fBquad\fR package. Only the important parameters which you might
+want to change are described. It is assumed that the support personnel
+have created the necessary instrument files (see \fBinstruments\fR)
+which will set the default parameters for the data you will be
+reducing. If this is not the case you may need to delve more deeply
+into the details of the tasks. Information about all the parameters
+and how the various tasks operate are given in the help documentation
+for the tasks and in additional special help topics. Some useful help
+documentation is indicated in the discussion and also in the
+\fBReferences\fR section.
+.sh
+2. Getting Started
+
+ The first step is to load \fBquad\fR. This is done by loading
+the \fBarcon\fR package, and then the \fBquad\fR package. Loading a
+package consists of typing its name.
+
+ When you load the \fBquad\fR package the menu of tasks or commands
+is listed. This appears as follows:
+
+.nf
+ cl> quad
+ badpiximage combine mkillumcor qstatistics
+ ccdgroups cosmicrays mkillumflat quadproc
+ ccdhedit darkcombine mkskycor quadscale
+ ccdinstrument flatcombine mkskyflat setinstrument
+ ccdlist mkfringecor qhistogram zerocombine
+.fi
+
+A summary of the tasks and additional help topics is obtained by typing:
+
+ cl> help
+
+This list and how to get additional help on specific topics is described
+in the \fBReferences\fR section at the end of this guide.
+
+ The first command to use is \fBsetinstrument\fR, which sets the package
+appropriately for the CCD images to be reduced. The support personnel
+should tell you the instrument identification, but if not a list
+of known instruments may be listed by using '?' for the instrument name.
+
+.nf
+ cl> setinstrument
+ Instrument ID (type ? for a list) \fI<enter instrument id or ?>\fR
+ <Set quad package parameters using eparam>
+ <Set quadproc task parameters using eparam>
+.fi
+
+This task sets the default parameters and then allows you to modify the
+package parameters and the processing parameters using the parameter
+editor \fBeparam\fR. If you are not familiar with \fBeparam\fR see the
+help or CL introduction documentation. For most terminals you move up
+and down through the parameters with the terminal arrow keys, you
+change the parameters by simply typing the desired value, and you exit
+with control Z or control D. Note that you can change parameters for
+any task at any time with \fBeparam\fR and you do not have to run
+\fBsetinstrument\fR again, even if you logout, until you need to reduce
+data from a different instrument.
+
+ The \fBquad\fR package parameters control general I/O functions of
+the tasks in the package. The parameters you might wish to change are
+the output pixel type and the verbose option. Except when the input
+images are short integers, the noise is significantly greater than one
+digital unit, and disk space is critical, it is probably better to
+allow the processing to convert the images to real pixel datatype. The
+verbose parameter simply prints the information written to the log file
+on the terminal. This can be useful when little else is being done and
+you are just beginning. However, when doing background processing and
+other IRAF reduction tasks it is enough to simply look at the end of
+the logfile with the task \fBtail\fR to see the current state of the
+processing.
+
+ The \fBquadproc\fR parameters control the CCD processing. There are
+many parameters but they all may be conveniently set at this point.
+Many of the parameters have default values set appropriately for the
+instrument you specified. The images to be processed can be specified
+later. What needs to be set are the processing operations that you
+want done and the parameters required for each operation. The
+processing operations are selected by entering yes or no for each one.
+The following items briefly describe each of the possible processing
+operations and the additional parameters required.
+
+.ls \fIfixpix\fR - Fix bad CCD lines and columns?
+The bad pixels (cosmetic defects) in the detector are given in a file
+specified by the parameter \fIfixfile\fR. This information is used
+to replace the pixels by interpolating from the neighboring pixels.
+A standard file for your instrument may be set by \fBsetinstrument\fR
+or if the word "image" is given then the file is defined in the instrument
+data file. For more on the bad pixel file see \fBinstruments\fR.
+.le
+.ls \fIoverscan\fR - Apply overscan strip correction?
+The overscan or prescan region is specified by the parameter
+\fIbiassec\fR. This is given as an IRAF image section. For guidance on
+seting this parameter see the help page for \fBquadproc\fR. The overscan
+region is averaged along the readout axis, specified by the parameter
+\fIreadaxis\fR, to create a one dimensional bias vector. This bias is
+fit by a function to remove cosmic rays and noise. There are a number
+of parameters at the end of the parameter list which control the
+fitting.
+.le
+.ls \fItrim\fR - Trim the image?
+The image is trimmed to the image section given by the parameter
+\fItrimsec\fR. For guidance on setting this parameter see the help page
+for \fBquadproc\fR.
+.le
+.ls \fIzerocor\fR - Apply zero level correction?
+The zero level image to be subtracted is specified by the parameter
+\fIzero\fR. If none is given then the calibration image will be sought
+in the list of images to be processed.
+.le
+.ls \fIdarkcor\fR - Apply dark count correction?
+The dark count image to be subtracted is specified by the parameter
+\fIdark\fR. If none is given then the calibration image will be sought
+in the list of images to be processed.
+.le
+.ls \fIflatcor\fR - Apply flat field correction?
+The flat field images to be used are specified by the parameter
+\fIflat\fR. There must be one flat field image for each filter
+or subset (see \fBsubsets\fR) to be processed. If a flat field
+image is not given then the calibration image will be sought
+in the list of images to be processed.
+.le
+.ls \fIreadcor\fR - Convert zero level image to readout correction?
+If a one dimensional zero level readout correction vector is to be subtracted
+instead of a two dimensional zero level image then, when this parameter is set,
+the zero level images will be averaged to one dimension. The readout axis
+must be specified by the parameter \fIreadaxis\fR. The default for your
+instrument is set by \fBsetinstrument\fR.
+.le
+.ls \fIscancor\fR - Convert flat field image to scan correction?
+If the instrument is operated in a scan mode then a correction to the
+flat field may be required. There are two types of scan modes, "shortscan"
+and "longscan". In longscan mode flat field images will be averaged
+to one dimension and the readout axis must be specified. Shortscan mode
+is a little more complicated. The scan correction is used if the flat
+field images are not observed in scan mode. The number of scan lines
+must be specified by the parameter \fInscan\fR. If they are observed in
+scan mode, like the object observations, then the scan correction
+operations should \fInot\fR be specified. For details of scan mode operations
+see \fBquadproc\fR. The scan parameters
+should be set by \fBsetinstrument\fR. If in doubt consult someone
+familiar with the instrument and mode of operation.
+.le
+
+ This description of the parameters is longer than the actual operation of
+setting the parameters. The only parameters likely to change during processing
+are the calibration image parameters.
+
+ When processing many images using the same calibration files a modest
+performance improvement can be achieved by keeping (caching) the
+calibration images in memory to avoid disk accesses. This option
+is available by specifying the amount of memory available for image
+caching with the parameter \fImax_cache\fR. If the value is zero then
+the images are accessed from disk as needed while if there is
+sufficient memory the calibration images may be kept in memory during
+the task execution.
+.sh
+3. Processing Your Data
+
+ The processing path depends on the type of data, the type of
+instrument, types of calibration images, and the observing
+sequence. In this section we describe two types of operations common
+in reducing most data; combining calibration images and performing the
+standard calibration and correction operations. Some additional special
+operations are described in the following section.
+
+ However, the first thing you might want to try before any
+processing is to get a listing of the CCD images showing the CCD image
+types, subsets, and processing flags. The task for this is
+\fBccdlist\fR. It has three types of output; a short one line per
+image format, a longer format which shows the state of the processing,
+and a format which prints the image names only (used to create files
+containing lists of images of a particular CCD image type). To get a
+quick listing type:
+
+.nf
+ cl> ccdlist *.imh
+ ccd001.imh[544,512][short][unknown][V]:FOCUS L98-193
+ ccd007.imh[544,512][short][object][V]:N2968 V 600s
+ ccd015.imh[544,512][short][object][B]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R]:N4036 R 600s
+ ccd045.imh[544,512][short][flat][V]:dflat 5s
+ ccd066.imh[544,512][short][flat][B]:dflat 5s
+ ccd103.imh[544,512][short][flat][R]:dflat 5s
+ ccd104.imh[544,512][short][zero][]:bias
+ ccd105.imh[544,512][short][dark][]:dark 3600s
+.fi
+
+ The example shows only a sample of the images. The short format
+listing tells you the name of the image, its size and pixel type, the
+CCD image type as seen by the package, the subset identifier (in this
+case the filter), and the title. If the data had been processed then
+there would also be processing flags. If the CCD image types do not
+seem right then there may be a problem with the instrument
+specification.
+
+ Many of the tasks in the \fBquad\fR package have the parameter
+\fIccdtype\fR which selects a particular type of image. To list
+only the object images from the previous example:
+
+.nf
+ cl> ccdlist *.imh ccdtype=object
+ ccd007.imh[544,512][short][object][V]:N2968 V 600s
+ ccd015.imh[544,512][short][object][B]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R]:N4036 R 600s
+.fi
+
+If no CCD image type is specified (by using the null string "")
+then all image types are selected. This may be
+necessary if your instrument data does not contain image type identifications.
+.sh
+3.1 Combining Calibration Images
+
+ If you do not need to combine calibration images because you only
+have one image of each type, you can skip this section. Calibration
+images, particularly zero level and flat field images, are combined in
+order to minimize the effects of noise and reject cosmic ray hits in the
+calibrations. The basic tool for combining images is the task
+\fBcombine\fR. There are simple variants of this task whose default
+parameters are set appropriately for each type of calibration image.
+These are the ones you will use for calibration images leaving
+\fBcombine\fR for combining object images. Zero level images are
+combined with \fBzerocombine\fR, dark count images with
+\fBdarkcombine\fR, and flat field images with \fBflatcombine\fR.
+
+ For example, to combine flat field images the command is:
+
+.nf
+ cl> flatcombine *.imh
+ Jun 1 14:26 combine: maxreject
+ Images N Exp Mode Scale Offset Weight
+ ccd045.imh 1 5.0 INDEF 1.000 0. 0.048
+ ccd046.imh 1 5.0 INDEF 1.000 0. 0.048
+ <... list of files ...>
+ ccd065.imh 1 5.0 INDEF 1.000 0. 0.048
+ ----------- ------ ------
+ FlatV.imh 21 5.0
+.fi
+
+This output is printed when verbose mode is set. The same information
+is recorded in the log file. In this case the flat fields are combined
+by rejecting the maximum value at each point in the image (the
+"maxreject" algorithm). The images are scaled by the exposure times,
+which are all the same in this example. The mode is not evaluated for
+exposure scaling and the relative weights are the same because the
+exposure times are the same. The example only shows part of the
+output; \fBflatcombine\fR automatically groups the flat field images by
+filter to produce the calibration images "FlatV", "FlatB", and
+"FlatR".
+.sh
+3.2 Calibrations and Corrections
+
+ Processing the CCD data is easy and largely automated.
+First, set the task parameters with the following command:
+
+ cl> eparam quadproc
+
+You may have already set the parameters when you ran
+\fBsetinstrument\fR, though the calibration image parameters
+\fIzero\fR, \fIdark\fR, and \fIflat\fR may still need to be set or
+changed. Once this is done simply give the command
+
+.nf
+ cl> quadproc *.imh
+ ccd003: Jun 1 15:13 Overscan section is [520:540,*] with mean=485.0
+ ccd003: Jun 1 15:14 Trim data section is [3:510,3:510]
+ ccd003: Jun 1 15:14 Overscan section is [520:540,*] with mean=485.0
+ FlatV: Jun 1 15:14 Trim data section is [3:510,3:510]
+ FlatV: Jun 1 15:15 Overscan section is [520:540,*] with mean=486.4
+ ccd003: Jun 1 15:15 Flat field image is FlatV.imh with scale=138.2
+ ccd004: Jun 1 15:16 Trim data section is [3:510,3:510]
+ ccd004: Jun 1 15:16 Overscan section is [520:540,*] with mean=485.2
+ ccd004: Jun 1 15:16 Flat field image is FlatV.imh with scale=138.2
+ <... more ...>
+ ccd013: Jun 1 15:22 Trim data section is [3:510,3:510]
+ ccd013: Jun 1 15:23 Overscan section is [520:540,*] with mean=482.4
+ FlatB: Jun 1 15:23 Trim data section is [3:510,3:510]
+ FlatB: Jun 1 15:23 Overscan section is [520:540,*] with mean=486.4
+ ccd013: Jun 1 15:24 Flat field image is FlatB.imh with scale=132.3
+ <... more ...>
+.fi
+
+ The output shown is with verbose mode set. It is the same as
+recorded in the log file. It illustrates the principle of automatic
+calibration image processing. The first object image, "ccd003", was
+being processed when the flat field image was required. Since the
+image was taken with the V filter the appropriate flat field was
+determined to be "FlatV". Since it had not been processed, the
+processing of "ccd003" was interrupted to process "FlatV". The
+processed calibration image may have been cached if there was enough
+memory. Once "FlatV" was processed (note that the flat field was not
+flattened because the task knows this image is a flat field) the
+processing of "ccd003" was completed. The next image, "ccd004", is
+also a V filter image so the already processed, and possibly cached,
+flat field "FlatV" is used again. The first B band image is "ccd013"
+and, as before, the B filter flat field calibration image is processed
+automatically. The same automatic calibration processing and image
+caching occurs when using zero level and dark count calibration
+images.
+
+ Commonly the processing is done with the verbose mode turned off
+and the task run as a background job. This is done with the commands
+
+.nf
+ cl> quad.verbose=no
+ cl> quadproc *.imh &
+.fi
+
+The already processed images in the input list are recognized as having been
+processed and are not affected. To check the status of the processing we
+can look at the end of the log file with:
+
+ cl> tail logfile
+
+After processing we can repeat the \fBccdlist\fR command to find:
+
+.nf
+ cl> ccdlist *.imh ccdtype=object
+ ccd007.imh[508,508][real][object][V][OTF]:N2968 V 600s
+ ccd015.imh[508,508][real][object][B][OTF]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R][OTF]:N4036 R 600s
+.fi
+
+The processing flags indicate the images have been overscan corrected,
+trimmed, and flat fielded.
+
+ As you can see, processing images is very easy. There is one source
+of minor confusion for beginning users and that is dealing with calibration
+images. First, there is no reason that calibration images
+may not be processed explicitly with \fBquadproc\fR, just remember to set
+the \fIccdtype\fR to the calibration image type or to "". When processing
+object images the calibration images to be used may be specified either
+with the task parameter for the particular calibration image or by
+including the calibration image in the list of input images. Calibration
+images specified by parameter value take precedence and the task
+does not check its CCD image type. Calibration images given in the
+input list must have a valid CCD image type. In case too many
+calibration images are specified, say because the calibration images
+combined to make the master calibration images were not deleted and
+so are part of the image list "*.imh", only the first one will be used.
+Another point to know is that flat field, iillumination, and fringe images
+are subset (filter) dependent and so a calibration image for each filter
+must be specified.
+.sh
+4. Special Processing Operations
+
+ The special processing operations are mostly concerned with the
+flat field response correction. There are also special processing
+operations available in \fBquadproc\fR for one dimensional readout
+corrections in the zero level and flat field calibrations. These
+were described briefly above and in more detail in \fBquadproc\fR
+and are not discussed further in this guide. The processing
+operations described in this section are for preparing flat fields
+for two dimensional spectroscopic data, for correcting flat fields
+for iilluminations effects, for making a separate iillumination correction,
+and for applying corrections for fringe effects. For additional
+discussion about flat fields and iillumination corrections see the
+help topic \fBflatfields\fR.
+.sh
+4.1 Spectroscopic Flat Fields
+
+ For spectroscopic data the flat fields may have to be processed to
+remove the general shape of the lamp spectrum and to replace regions outside
+of the aperture where there is no flat field information with values that
+will not cause bad response effects when the flat field is applied to the
+data. If the shape of the lamp spectrum is not important and if the
+longslit spectra have the regions outside of the slit either off the
+detector or trimmed then you may use the flat field without special
+processing.
+
+ First you must process the flat field images explicitly with
+
+ cl> quadproc *.imh ccdtype=flat
+
+where "*.imh" may be replaced with any list containing the flat fields.
+If zero level and dark count corrections are required these calibration
+images must be available at this time.
+
+ Load the \fBtwodspec\fR package and then either the \fBlongslit\fR
+package, for longslit data, or the \fBapextract\fR package, for
+multiaperture data such as echelles, multifiber, or aperture mask
+spectra. The task for removing the longslit quartz spectrum is
+\fBresponse\fR. There is also a task for removing iillumination
+effects, including the slit profile, from longslit spectra called
+\fBiillumination\fR. For more about processing longslit spectra see the
+help for these tasks and the paper \fIReduction of Longslit Spectra
+with IRAF\fR. The cookbook \fIReduction of Longslit Spectroscopic
+Data Using IRAF (KPNO ICCD and Cryogenic Camera Data)\fR also provides
+a very good discussion even if your data is from a different instrument.
+
+ For multiaperture data the task for removing the relative shapes of
+the spectra is called \fBapnormalize\fR. Again, consult the help documentation
+for this task for further details. Since you will probably also be
+using the package for extracting the spectra you may be interested
+in the document \fIThe IRAF APEXTRACT Package\fR.
+.sh
+4.2 Iillumination Corrections
+
+ The flat field calibration images may not have the same iillumination
+pattern as the observations of the sky due to the way the lamp illuminates the
+optical system. In this case when the flat field correction is applied
+to the data there will be gradients in the sky background. To remove
+these gradients a blank sky calibration image is heavily smoothed
+to produce an iillumination image. The iillumination image
+is then divided into the images during processing to correct for the
+iillumination difference between the flat field and the objects.
+Like the flat fields, the iillumination corrections images may be subset
+dependent so there should be an iillumination image for each subset.
+
+The task which makes iillumination correction images is \fBmkskycor\fR.
+Some examples are
+
+.nf
+ cl> mkskycor sky004 Illum004
+ cl> mkskycor sky*.imh ""
+.fi
+
+In the first example the sky image "sky004" is used to make the iillumination
+correction image "Illum004". In the second example the sky images are
+converted to iillumination correction images by specifying no output image
+names. Like \fBquadproc\fR if the input images have not been processed they
+are first processed automatically.
+
+To apply the iillumination correction
+
+.nf
+ cl> quadproc *.imh ccdtype=object illumcor+ illum=Illum004
+ cl> quadproc *.imh ccdtype=object illumcor+ illum=sky*.imh
+.fi
+
+The iillumination images could also be set using \fBeparam\fR or given
+on the command line.
+.sh
+4.3 Sky Flat Fields
+
+ You will notice that when you process images with an iillumination
+correction you are dividing each image by a flat field calibration and
+an iillumination correction. If the iillumination corrections are not
+done as a later step but at the same time as the rest of the processing
+one will get the same calibration by multiplying the flat field by
+the iillumination correction and using this product alone as the
+flat field. Such an image is called a \fIsky flat\fR since it is
+a flat field which has been corrected to yield a flat sky when applied
+to the observations. This approach has the advantage of one less
+calibration image and two less computations (scaling and dividing the
+iillumination correction). As an added short cut, rather than compute
+the iillumination image with \fBmkskycor\fR and then multiplying, the
+task \fBmkskyflat\fR does all this in one step. Thus, \fBmkskyflat\fR
+takes an input blank sky image, processes it if needed, determines the
+appropriate flat field (sky flats are also subset dependent) from the
+\fBquadproc\fR parameters or the input image list, and produces an
+output sky flat. Further if no output image is specified the task
+converts the input blank sky calibration image into a sky flat.
+
+ Two examples in which a new image is created and in which the
+input images are converted to sky flats are
+
+.nf
+ cl> mkskyflat sky004 Skyflat
+ cl> mkskyflat sky*.imh ""
+.fi
+.sh
+4.4 Iillumination Corrected Flat Fields
+
+ A third method to account for iillumination problems in the flat fields
+is to remove the large scale pattern from the flat field itself. This is
+useful if there are no reasonable blank sky calibration images and the
+astronomical exposures are evenly illuminated but the flat fields are not.
+This is done by smoothing the flat field images instead of blank sky
+images. As with using the sky images there are two methods, creating
+an iillumination correction to be applied as a separate step or fixing
+the original flat field. The smoothing algorithm is
+the same as that used in the other tasks. The tasks to make these types
+of corrections are \fBmkillumcor\fR and \fBmkillumflat\fR. The usage
+is pretty much the same as the other iillumination correction tasks
+except that it is more reasonable to replace the original flat fields
+by the corrected flat fields when fixing the flat field. Examples
+of an iillumination correction and removing the iillumination pattern
+from the flat field are
+
+.nf
+ cl> mkillumcor flat025 Illum025
+ cl> mkillumflat flat*.imh ""
+.fi
+
+As with the other tasks, the input images are processed if necessary.
+.sh
+4.5 Fringe Corrections
+
+ Some CCD detectors suffer from fringing effects due to the night
+sky emission lines which are not removed by the other calibration
+and correction operations. To correct for the fringing you need a
+really blank sky image. There is not yet a task to remove objects from
+sky images because this is often done with an interactive image display
+tool (which will soon be added). The blank sky image is heavily smoothed
+to determine the mean sky background and then this is subtracted from the
+original image. The image should then be essentially zero except for the
+fringe pattern. This fringe correction image is scaled to the same
+exposure time as the image to be corrected and then subtracted to remove
+the fringing. Note that since the night sky lines are variable there
+may need to be an additional scaling applied. Determining this scaling
+requires either an interactive display tool or a very clever task.
+Such tasks will also be added in the future.
+
+ The task to make a fringe correction image is \fBmkfringecor\fR.
+the sky background is determined in exactly the same way as the iillumination
+pattern, in fact the same sky image may be used for both the sky
+iillumination and for the fringe correction. The task works consistently
+with the "mk" tasks in that the input images are processed first if needed
+and then the output correction image is produced with the specified name
+or replaces the input image if no output image is specified.
+As examples,
+
+.nf
+ cl> mkfringecor sky004 Fringe
+ cl> mkfringecor sky*.imh ""
+.fi
+.sh
+6. Summary
+
+ The \fBquad\fR package is very easy to use. First load the package;
+it is in the \fBarcon\fR package. If this is your first time reducing data
+from a particular instrument or if you have changed instruments then run
+\fBsetinstrument\fR. Set the processing parameters for the operations you want
+performed. If you need to combine calibration images to form a master
+calibration image use one of the combine tasks. Spectroscopic flat fields may
+need to be processed first in order to remove the lamp spectrum.
+Finally, just type
+
+ cl> quadproc *.imh&
+.sh
+7. References
+
+ A general guide to using IRAF is \fIA User's Introduction to the IRAF
+Command Language\fR. This document may be found in the IRAF documentation
+sets and is available from the National Optical Astronomy Observatories,
+Central Computer Services (NOAO-CCS).
+
+ A more detailed description of the \fBccdred\fR package, on which
+\fBquad\fR is based, including a discussion of the design and some of the
+algorithms see \fIThe IRAF CCD Reduction Package -- CCDRED\fR by F. Valdes.
+This paper is available from NOAO-CCS and appears in the proceedings of the
+Santa Cruz Summer Workshop in Astronomy and Astrophysics, \fIInstrumentation
+for Ground-Based Optical Astronomy: Present and Future\fR, edited by
+Lloyd B. Robinson and published by Springer-Verlag.
+
+ The task descriptions and supplementary documentation are available
+on-line through the help task by typing
+
+ cl> help \fItopic\fR
+
+where \fItopic\fR is one of the following.
+
+.nf
+ SPECIAL TASKS FOR MULTI-READOUT CCD IMAGES
+
+ quadproc - Process multi-readout CCD images
+ quadscale - Apply correction for amplifier dependent gain differences
+ qstatistics - Calculate image statistics for multi-readout CCD images
+ qhistogram - Make histogram of multi-readout CCD image
+ darkcombine - Combine and process dark count images
+ flatcombine - Combine and process flat field images
+ zerocombine - Combine and process zero level images
+
+
+ STANDARD CCDRED TASKS
+
+ badpiximage - Create a bad pixel mask image from a bad pixel file
+ ccdgroups - Group CCD images into image lists
+ ccdhedit - CCD image header editor
+ ccdinstrument - Review and edit instrument translation files
+ ccdlist - List CCD processing information
+ combine - Combine CCD images
+ cosmicrays - Detect and replace cosmic rays
+ mkfringecor - Make fringe correction images from sky images
+ mkillumcor - Make flat field iillumination correction images
+ mkillumflat - Make iillumination corrected flat fields
+ mkskycor - Make sky iillumination correction images
+ mkskyflat - Make sky corrected flat field images
+ setinstrument - Set instrument parameters
+
+ ADDITIONAL HELP TOPICS
+
+ ccdgeometry - Discussion of CCD coordinate/geometry keywords
+ ccdtypes - Description of the CCD image types
+ flatfields - Discussion of CCD flat field calibrations
+ guide - Introductory guide to using the CCDRED package
+ instruments - Instrument specific data files
+ package - CCD image reduction package
+ quadreadout - Description of multi-readout CCD data
+ subsets - Description of CCD subsets
+.fi
+
+Printed copies of the on-line help documentation may be made with the
+command
+
+ cl> help topic | lprint
+
+ In addition to the package documentation for \fBquad\fR,
+\fBlongslit\fR, and \fBapextract\fR there may be specific guides for
+certain instruments. These specific guides, called "cookbooks", give
+specific examples and parameter values for the CCD data.
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/guide.ms b/noao/imred/quadred/src/quad/doc/guide.ms
new file mode 100644
index 00000000..62d87bb9
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/guide.ms
@@ -0,0 +1,794 @@
+.RP
+.TL
+User's Guide to the CCDRED Package
+.AU
+Francisco Valdes
+.AI
+IRAF Group - Central Computer Services
+.K2
+P.O. Box 26732, Tucson, Arizona 85726
+June 1987
+Revised February 1988
+.AB
+The IRAF CCD reduction package, \fBccdred\fR, provides tools
+for the easy and efficient reduction of CCD images. The standard
+reduction operations are replacement of bad pixels, subtraction of an
+overscan or prescan bias, subtraction of a zero level image,
+subtraction of a dark count image, division by a flat field calibration
+image, division by an illumination correction, subtraction of a fringe
+image, and trimming unwanted lines or columns. Another common
+operation provided by the package is scaling and combining images with
+a number of algorithms for rejecting cosmic rays. Data in the image
+header is used to make the reductions largely automated and
+self-documenting though the package may still be used in the absence of
+this data. Also a translation mechanism is used to relate image header
+parameters to those used by the package to allow data from a variety of
+observatories and instruments to be processed. This guide provides a brief
+description of the IRAF CCD reduction package and examples of reducing
+simple CCD data.
+.AE
+.NH
+Introduction
+.LP
+ This guide provides a brief description of the IRAF CCD reduction
+package \fBccdred\fR and examples of reducing simple CCD data. It is a
+generic guide in that it is not tied to any particular type of data.
+There may be more specific guides (or "cookbooks") for your data.
+Detailed descriptions of the tasks and features of the package are
+provided in the help documentation for the package.
+
+ The purpose of the CCDRED package is to provide tools for the easy
+and efficient reduction of CCD images. The standard reduction
+operations are replacement of bad columns and lines by interpolation
+from neighboring columns and lines, subtraction of a bias level
+determined from overscan or prescan columns or lines, subtraction of a
+zero level using a zero length exposure calibration image, subtraction
+of a dark count calibration image appropriately scaled to the dark time
+exposure, division by a scaled flat field calibration image, division
+by an illumination image (derived from a blank sky image), subtraction
+of a scaled fringe image (also derived from a blank sky image), and
+trimming the image of unwanted lines or columns such as the overscan
+strip. Any set of operations may be done simultaneously over a list of
+images in a highly efficient manner. The reduction operations are
+recorded in the image header and may also be logged on the terminal and
+in a log file.
+
+ The package also provides tools for combining multiple exposures
+of object and calibration images to improve the statistical accuracy of
+the observations and to remove transient bad pixels. The combining
+operation scales images of different exposure times, adjusts for
+variable sky background, statistically weights the images by their
+signal-to-noise, and provides a number of useful algorithms for
+detecting and rejecting transient bad pixels.
+
+ Other tasks are provided for listing reduction information about
+the images, deriving secondary calibration images (such as sky
+corrected flat fields or illumination correction images), and easily
+setting the package parameters for different instruments.
+
+ There are several important features provided by the package to
+make the reduction of CCD images convenient; particularly to minimize
+record keeping. One of these is the ability to recognize the different
+types of CCD images. This ability allows the user to select a certain
+class of images to be processed or listed and allows the processing
+tasks to identify calibration images and process them differently from
+object images. The standard CCD image types are \fIobject\fR,
+\fIzero\fR level, \fIdark\fR count, and \fIflat\fR field. For more on
+the image types see \fBccdtypes\fR.
+
+ The tasks can also identify the different filters (or other subset
+parameter) which require different flat field images. This means you don't
+have to separate the images by filter and process each set separately.
+This feature is discussed further in \fBsubsets\fR.
+
+ The tasks keep track of the reduction steps completed on each
+image and ignore images which have been processed. This feature,
+along with recognizing the image types and subsets, makes it possible to
+specify all the images to a task with a wildcard template, such as
+"*.imh", rather than indicating each image by name. You will find this
+extremely important with large sets of observations.
+
+ A fundamental aspect of the package is that the processing
+modifies the images. In other words, the reduction operations are
+performed directly on the image. This "feature" further simplifies
+record keeping, frees the user from having to form unique output image
+names, and minimizes the amount of disk space required. There
+are two safety features in this process. First, the modifications do
+not take effect until the operation is completed on the image. This
+allows you to abort the task without messing up the image data and
+protects data if the computer crashes. The second feature is that
+there is a package parameter which may be set to make a backup of the
+input data with a particular prefix such as "orig" or "imdir$". This
+backup feature may be used when there is sufficient disk space, when learning
+to use the package, or just to be cautious.
+
+ In a similar effort to efficiently manage disk space, when combining
+images into a master object or calibration image there is an option to
+delete the input images upon completion of the combining operation.
+Generally this is desirable when there are many calibration exposures,
+such as zero level or flat field images, which are not used after they
+are combined into a final calibration image.
+
+ The following sections guide you through the basic use of the
+\fBccdred\fR package. Only the important parameters which you might
+want to change are described. It is assumed that the support personnel
+have created the necessary instrument files (see \fBinstruments\fR)
+which will set the default parameters for the data you will be
+reducing. If this is not the case you may need to delve more deeply
+into the details of the tasks. Information about all the parameters
+and how the various tasks operate are given in the help documentation
+for the tasks and in additional special help topics. Some useful help
+documentation is indicated in the discussion and also in the
+\fBReferences\fR section.
+.NH
+Getting Started
+.LP
+ The first step is to load \fBccdred\fR. This is done by loading
+the \fBnoao\fR package, followed by the image reduction package
+\fBimred\fR, and finally the \fBccdred\fR package. Loading a
+package consists of typing its name. Note that some of these packages may be
+loaded automatically when you logon to IRAF.
+
+ When you load the \fBccdred\fR package the menu of tasks or commands
+is listed. This appears as follows:
+
+.nf
+.KS
+.ft L
+ cl> ccdred
+ badpiximage ccdtest mkfringecor setinstrument
+ ccdgroups combine mkillumcor zerocombine
+ ccdhedit cosmicrays mkillumflat
+ ccdlist darkcombine mkskycor
+ ccdproc flatcombine mkskyflat
+.ft R
+.KE
+.fi
+
+A summary of the tasks and additional help topics is obtained by typing:
+
+.ft L
+ cl> help
+.ft R
+
+This list and how to get additional help on specific topics is described
+in the \fBReferences\fR section at the end of this guide.
+
+ The first command to use is \fBsetinstrument\fR, which sets the package
+appropriately for the CCD images to be reduced. The support personnel
+should tell you the instrument identification, but if not a list
+of known instruments may be listed by using '?' for the instrument name.
+
+.nf
+.ft L
+ cl> setinstrument
+ Instrument ID (type ? for a list) \fI<enter instrument id or ?>
+ <Set ccdred package parameters using eparam>
+ <Set ccdproc task parameters using eparam>
+.ft R
+.fi
+
+This task sets the default parameters and then allows you to modify the
+package parameters and the processing parameters using the parameter
+editor \fBeparam\fR. If you are not familiar with \fBeparam\fR see the
+help or CL introduction documentation. For most terminals you move up
+and down through the parameters with the terminal arrow keys, you
+change the parameters by simply typing the desired value, and you exit
+with control Z or control D. Note that you can change parameters for
+any task at any time with \fBeparam\fR and you do not have to run
+\fBsetinstrument\fR again, even if you logout, until you need to reduce
+data from a different instrument.
+
+ The \fBccdred\fR package parameters control general I/O functions of
+the tasks in the package. The parameters you might wish to change are
+the output pixel type and the verbose option. Except when the input
+images are short integers, the noise is significantly greater than one
+digital unit, and disk space is critical, it is probably better to
+allow the processing to convert the images to real pixel datatype. The
+verbose parameter simply prints the information written to the log file
+on the terminal. This can be useful when little else is being done and
+you are just beginning. However, when doing background processing and
+other IRAF reduction tasks it is enough to simply look at the end of
+the logfile with the task \fBtail\fR to see the current state of the
+processing.
+
+ The \fBccdproc\fR parameters control the CCD processing. There are
+many parameters but they all may be conveniently set at this point.
+Many of the parameters have default values set appropriately for the
+instrument you specified. The images to be processed can be specified
+later. What needs to be set are the processing operations that you
+want done and the parameters required for each operation. The
+processing operations are selected by entering yes or no for each one.
+The following items briefly describe each of the possible processing
+operations and the additional parameters required.
+
+.LP
+\fIfixpix\fR - Fix bad CCD lines and columns?
+.IP
+The bad pixels (cosmetic defects) in the detector are given in a file
+specified by the parameter \fIfixfile\fR. This information is used
+to replace the pixels by interpolating from the neighboring pixels.
+A standard file for your instrument may be set by \fBsetinstrument\fR
+or if the word "image" is given then the file is defined in the instrument
+data file. For more on the bad pixel file see \fBinstruments\fR.
+.LP
+\fIoverscan\fR - Apply overscan strip correction?
+.IP
+The overscan or prescan region is specified by the parameter
+\fIbiassec\fR. This is given as an IRAF image section. The overscan
+region is averaged along the readout axis, specified by the parameter
+\fIreadaxis\fR, to create a one dimensional bias vector. This bias is
+fit by a function to remove cosmic rays and noise. There are a number
+of parameters at the end of the parameter list which control the
+fitting. The default overscan bias section and fitting parameters for
+your instrument should be set by \fBsetinstrument\fR. If the word
+"image" is given the overscan bias section is defined in the image
+header or the instrument translation file. If an overscan section is
+not set you can use \fBimplot\fR to determine the columns or rows for
+the bias region and define an overscan image section. If you are
+unsure about image sections consult with someone or read the
+introductory IRAF documentation.
+.LP
+\fItrim\fR - Trim the image?
+.IP
+The image is trimmed to the image section given by the parameter
+\fItrimsec\fR. A default trim section for your instrument should be
+set by \fBsetinstrument\fR, however, you may override this default if
+desired. If the word "image" is given the data
+image section is given in the image header or the instrument
+translation file. As with the overscan image section it is
+straightforward to specify, but if you are unsure consult someone.
+.LP
+\fIzerocor\fR - Apply zero level correction?
+.IP
+The zero level image to be subtracted is specified by the parameter
+\fIzero\fR. If none is given then the calibration image will be sought
+in the list of images to be processed.
+.LP
+\fIdarkcor\fR - Apply dark count correction?
+.IP
+The dark count image to be subtracted is specified by the parameter
+\fIdark\fR. If none is given then the calibration image will be sought
+in the list of images to be processed.
+.LP
+\fIflatcor\fR - Apply flat field correction?
+.IP
+The flat field images to be used are specified by the parameter
+\fIflat\fR. There must be one flat field image for each filter
+or subset (see \fBsubsets\fR) to be processed. If a flat field
+image is not given then the calibration image will be sought
+in the list of images to be processed.
+.LP
+\fIreadcor\fR - Convert zero level image to readout correction?
+.IP
+If a one dimensional zero level readout correction vector is to be subtracted
+instead of a two dimensional zero level image then, when this parameter is set,
+the zero level images will be averaged to one dimension. The readout axis
+must be specified by the parameter \fIreadaxis\fR. The default for your
+instrument is set by \fBsetinstrument\fR.
+.LP
+\fIscancor\fR - Convert flat field image to scan correction?
+.IP
+If the instrument is operated in a scan mode then a correction to the
+flat field may be required. There are two types of scan modes, "shortscan"
+and "longscan". In longscan mode flat field images will be averaged
+to one dimension and the readout axis must be specified. Shortscan mode
+is a little more complicated. The scan correction is used if the flat
+field images are not observed in scan mode. The number of scan lines
+must be specified by the parameter \fInscan\fR. If they are observed in
+scan mode, like the object observations, then the scan correction
+operations should \fInot\fR be specified. For details of scan mode operations
+see \fBccdproc\fR. The scan parameters
+should be set by \fBsetinstrument\fR. If in doubt consult someone
+familiar with the instrument and mode of operation.
+.LP
+
+ This description of the parameters is longer than the actual operation of
+setting the parameters. The only parameters likely to change during processing
+are the calibration image parameters.
+
+ When processing many images using the same calibration files a modest
+performance improvement can be achieved by keeping (caching) the
+calibration images in memory to avoid disk accesses. This option
+is available by specifying the amount of memory available for image
+caching with the parameter \fImax_cache\fR. If the value is zero then
+the images are accessed from disk as needed while if there is
+sufficient memory the calibration images may be kept in memory during
+the task execution.
+.NH
+Processing Your Data
+.LP
+ The processing path depends on the type of data, the type of
+instrument, types of calibration images, and the observing
+sequence. In this section we describe two types of operations common
+in reducing most data; combining calibration images and performing the
+standard calibration and correction operations. Some additional special
+operations are described in the following section.
+
+ However, the first thing you might want to try before any
+processing is to get a listing of the CCD images showing the CCD image
+types, subsets, and processing flags. The task for this is
+\fBccdlist\fR. It has three types of of output; a short one line per
+image format, a longer format which shows the state of the processing,
+and a format which prints the image names only (used to create files
+containing lists of images of a particular CCD image type). To get a
+quick listing type:
+
+.nf
+.ft L
+ cl> ccdlist *.imh
+ ccd001.imh[544,512][short][unknown][V]:FOCUS L98-193
+ ccd007.imh[544,512][short][object][V]:N2968 V 600s
+ ccd015.imh[544,512][short][object][B]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R]:N4036 R 600s
+ ccd045.imh[544,512][short][flat][V]:dflat 5s
+ ccd066.imh[544,512][short][flat][B]:dflat 5s
+ ccd103.imh[544,512][short][flat][R]:dflat 5s
+ ccd104.imh[544,512][short][zero][]:bias
+ ccd105.imh[544,512][short][dark][]:dark 3600s
+.ft R
+.fi
+
+ The example shows only a sample of the images. The short format
+listing tells you the name of the image, its size and pixel type, the
+CCD image type as seen by the package, the subset identifier (in this
+case the filter), and the title. If the data had been processed then
+there would also be processing flags. If the CCD image types do not
+seem right then there may be a problem with the instrument
+specification.
+
+ Many of the tasks in the \fBccdred\fR package have the parameter
+\fIccdtype\fR which selects a particular type of image. To list
+only the object images from the previous example:
+
+.nf
+.ft L
+ cl> ccdlist *.imh ccdtype=object
+ ccd007.imh[544,512][short][object][V]:N2968 V 600s
+ ccd015.imh[544,512][short][object][B]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R]:N4036 R 600s
+.ft R
+.fi
+
+If no CCD image type is specified (by using the null string "")
+then all image types are selected. This may be
+necessary if your instrument data does not contain image type identifications.
+.NH 2
+Combining Calibration Images
+.LP
+ If you do not need to combine calibration images because you only
+have one image of each type, you can skip this section. Calibration
+images, particularly zero level and flat field images, are combined in
+order to minimize the effects of noise and reject bad pixels in the
+calibrations. The basic tool for combining images is the task
+\fBcombine\fR. There are simple variants of this task whose default
+parameters are set appropriately for each type of calibration image.
+These are the ones you will use for calibration images leaving
+\fBcombine\fR for combining object images. Zero level images are
+combined with \fBzerocombine\fR, dark count images with
+\fBdarkcombine\fR, and flat field images with \fBflatcombine\fR.
+
+ For example, to combine flat field images the command is:
+
+.nf
+.ft L
+ cl> flatcombine *.imh
+ Jun 1 14:26 combine: maxreject
+ Images N Exp Mode Scale Offset Weight
+ ccd045.imh 1 5.0 INDEF 1.000 0. 0.048
+ ccd046.imh 1 5.0 INDEF 1.000 0. 0.048
+ \fI<... list of files ...>\fL
+ ccd065.imh 1 5.0 INDEF 1.000 0. 0.048
+ ----------- ------ ------
+ FlatV.imh 21 5.0
+.ft R
+.fi
+
+This output is printed when verbose mode is set. The same information
+is recorded in the log file. In this case the flat fields are combined
+by rejecting the maximum value at each point in the image (the
+"maxreject" algorithm). The images are scaled by the exposure times,
+which are all the same in this example. The mode is not evaluated for
+exposure scaling and the relative weights are the same because the
+exposure times are the same. The example only shows part of the
+output; \fBflatcombine\fR automatically groups the flat field images by
+filter to produce the calibration images "FlatV", "FlatB", and
+"FlatR".
+.NH 2
+Calibrations and Corrections
+.LP
+ Processing the CCD data is easy and largely automated.
+First, set the task parameters with the following command:
+
+.ft L
+ cl> eparam ccdproc
+.ft R
+
+You may have already set the parameters when you ran
+\fBsetinstrument\fR, though the calibration image parameters
+\fIzero\fR, \fIdark\fR, and \fIflat\fR may still need to be set or
+changed. Once this is done simply give the command
+
+.nf
+.ft L
+ cl> ccdproc *.imh
+ ccd003: Jun 1 15:13 Overscan section is [520:540,*] with mean=485.0
+ ccd003: Jun 1 15:14 Trim data section is [3:510,3:510]
+ ccd003: Jun 1 15:14 Overscan section is [520:540,*] with mean=485.0
+ FlatV: Jun 1 15:14 Trim data section is [3:510,3:510]
+ FlatV: Jun 1 15:15 Overscan section is [520:540,*] with mean=486.4
+ ccd003: Jun 1 15:15 Flat field image is FlatV.imh with scale=138.2
+ ccd004: Jun 1 15:16 Trim data section is [3:510,3:510]
+ ccd004: Jun 1 15:16 Overscan section is [520:540,*] with mean=485.2
+ ccd004: Jun 1 15:16 Flat field image is FlatV.imh with scale=138.2
+ \fI<... more ...>\fL
+ ccd013: Jun 1 15:22 Trim data section is [3:510,3:510]
+ ccd013: Jun 1 15:23 Overscan section is [520:540,*] with mean=482.4
+ FlatB: Jun 1 15:23 Trim data section is [3:510,3:510]
+ FlatB: Jun 1 15:23 Overscan section is [520:540,*] with mean=486.4
+ ccd013: Jun 1 15:24 Flat field image is FlatB.imh with scale=132.3
+ \fI<... more ...>\fL
+.ft R
+.fi
+
+ The output shown is with verbose mode set. It is the same as
+recorded in the log file. It illustrates the principle of automatic
+calibration image processing. The first object image, "ccd003", was
+being processed when the flat field image was required. Since the
+image was taken with the V filter the appropriate flat field was
+determined to be "FlatV". Since it had not been processed, the
+processing of "ccd003" was interrupted to process "FlatV". The
+processed calibration image may have been cached if there was enough
+memory. Once "FlatV" was processed (note that the flat field was not
+flattened because the task knows this image is a flat field) the
+processing of "ccd003" was completed. The next image, "ccd004", is
+also a V filter image so the already processed, and possibly cached,
+flat field "FlatV" is used again. The first B band image is "ccd013"
+and, as before, the B filter flat field calibration image is processed
+automatically. The same automatic calibration processing and image
+caching occurs when using zero level and dark count calibration
+images.
+
+ Commonly the processing is done with the verbose mode turned off
+and the task run as a background job. This is done with the commands
+
+.nf
+.ft L
+ cl> ccdred.verbose=no
+ cl> ccdproc *.imh &
+.ft R
+.fi
+
+The already processed images in the input list are recognized as having been
+processed and are not affected. To check the status of the processing we
+can look at the end of the log file with:
+
+.ft L
+ cl> tail logfile
+.ft R
+
+After processing we can repeat the \fBccdlist\fR command to find:
+
+.nf
+.ft L
+ cl> ccdlist *.imh ccdtype=object
+ ccd007.imh[508,508][real][object][V][OTF]:N2968 V 600s
+ ccd015.imh[508,508][real][object][B][OTF]:N3098 B 500s
+ ccd024.imh[544,512][short][object][R][OTF]:N4036 R 600s
+.ft R
+.fi
+
+The processing flags indicate the images have been overscan corrected,
+trimmed, and flat fielded.
+
+ As you can see, processing images is very easy. There is one source
+of minor confusion for beginning users and that is dealing with calibration
+images. First, there is no reason that calibration images
+may not be processed explicitly with \fBccdproc\fR, just remember to set
+the \fIccdtype\fR to the calibration image type or to "". When processing
+object images the calibration images to be used may be specified either
+with the task parameter for the particular calibration image or by
+including the calibration image in the list of input images. Calibration
+images specified by parameter value take precedence and the task
+does not check its CCD image type. Calibration images given in the
+input list must have a valid CCD image type. In case too many
+calibration images are specified, say because the calibration images
+combined to make the master calibration images were not deleted and
+so are part of the image list "*.imh", only the first one will be used.
+Another point to know is that flat field, illumination, and fringe images
+are subset (filter) dependent and so a calibration image for each filter
+must be specified.
+.NH
+Special Processing Operations
+.LP
+ The special processing operations are mostly concerned with the
+flat field response correction. There are also special processing
+operations available in \fBccdproc\fR for one dimensional readout
+corrections in the zero level and flat field calibrations. These
+were described briefly above and in more detail in \fBccdproc\fR
+and are not discussed further in this guide. The processing
+operations described in this section are for preparing flat fields
+for two dimensional spectroscopic data, for correcting flat fields
+for illuminations effects, for making a separate illumination correction,
+and for applying corrections for fringe effects. For additional
+discussion about flat fields and illumination corrections see the
+help topic \fBflatfields\fR.
+.NH 2
+Spectroscopic Flat Fields
+.LP
+ For spectroscopic data the flat fields may have to be processed to
+remove the general shape of the lamp spectrum and to replace regions outside
+of the aperture where there is no flat field information with values that
+will not cause bad response effects when the flat field is applied to the
+data. If the shape of the lamp spectrum is not important and if the
+longslit spectra have the regions outside of the slit either off the
+detector or trimmed then you may use the flat field without special
+processing.
+
+ First you must process the flat field images explicitly with
+
+.ft L
+ cl> ccdproc *.imh ccdtype=flat
+.ft R
+
+where "*.imh" may be replaced with any list containing the flat fields.
+If zero level and dark count corrections are required these calibration
+images must be available at this time.
+
+ Load the \fBtwodspec\fR package and then either the \fBlongslit\fR
+package, for longslit data, or the \fBapextract\fR package, for
+multiaperture data such as echelles, multifiber, or aperture mask
+spectra. The task for removing the longslit quartz spectrum is
+\fBresponse\fR. There is also a task for removing illumination
+effects, including the slit profile, from longslit spectra called
+\fBillumination\fR. For more about processing longslit spectra see the
+help for these tasks and the paper \fIReduction of Longslit Spectra
+with IRAF\fR. The cookbook \fIReduction of Longslit Spectroscopic
+Data Using IRAF (KPNO ICCD and Cryogenic Camera Data)\fR also provides
+a very good discussion even if your data is from a different instrument.
+
+ For multiaperture data the task for removing the relative shapes of
+the spectra is called \fBapnormalize\fR. Again, consult the help documentation
+for this task for further details. Since you will probably also be
+using the package for extracting the spectra you may be interested
+in the document \fIThe IRAF APEXTRACT Package\fR.
+.NH 2
+Illumination Corrections
+.LP
+ The flat field calibration images may not have the same illumination
+pattern as the observations of the sky due to the way the lamp illuminates the
+optical system. In this case when the flat field correction is applied
+to the data there will be gradients in the sky background. To remove
+these gradients a blank sky calibration image is heavily smoothed
+to produce an illumination image. The illumination image
+is then divided into the images during processing to correct for the
+illumination difference between the flat field and the objects.
+Like the flat fields, the illumination corrections images may be subset
+dependent so there should be an illumination image for each subset.
+
+The task which makes illumination correction images is \fBmkskycor\fR.
+Some examples are
+
+.nf
+.ft L
+ cl> mkskycor sky004 Illum004
+ cl> mkskycor sky*.imh ""
+.ft R
+.fi
+
+In the first example the sky image "sky004" is used to make the illumination
+correction image "Illum004". In the second example the sky images are
+converted to illumination correction images by specifying no output image
+names. Like \fBccdproc\fR if the input images have not been processed they
+are first processed automatically.
+
+To apply the illumination correction
+
+.nf
+.ft L
+ cl> ccdproc *.imh ccdtype=object illumcor+ illum=Illum004
+ cl> ccdproc *.imh ccdtype=object illumcor+ illum=sky*.imh
+.ft R
+.fi
+
+The illumination images could also be set using \fBeparam\fR or given
+on the command line.
+.NH 2
+Sky Flat Fields
+.LP
+ You will notice that when you process images with an illumination
+correction you are dividing each image by a flat field calibration and
+an illumination correction. If the illumination corrections are not
+done as a later step but at the same time as the rest of the processing
+one will get the same calibration by multiplying the flat field by
+the illumination correction and using this product alone as the
+flat field. Such an image is called a \fIsky flat\fR since it is
+a flat field which has been corrected to yield a flat sky when applied
+to the observations. This approach has the advantage of one less
+calibration image and two less computations (scaling and dividing the
+illumination correction). As an added short cut, rather than compute
+the illumination image with \fBmkskycor\fR and then multiplying, the
+task \fBmkskyflat\fR does all this in one step. Thus, \fBmkskyflat\fR
+takes an input blank sky image, processes it if needed, determines the
+appropriate flat field (sky flats are also subset dependent) from the
+\fBccdproc\fR parameters or the input image list, and produces an
+output sky flat. Further if no output image is specified the task
+converts the input blank sky calibration image into a sky flat.
+
+ Two examples in which a new image is created and in which the
+input images are converted to sky flats are
+
+.nf
+.ft L
+ cl> mkskyflat sky004 Skyflat
+ cl> mkskyflat sky*.imh ""
+.ft R
+.fi
+.NH 2
+Illumination Corrected Flat Fields
+.LP
+ A third method to account for illumination problems in the flat fields
+is to remove the large scale pattern from the flat field itself. This is
+useful if there are no reasonable blank sky calibration images and the
+astronomical exposures are evenly illuminated but the flat fields are not.
+This is done by smoothing the flat field images instead of blank sky
+images. As with using the sky images there are two methods, creating
+an illumination correction to be applied as a separate step or fixing
+the original flat field. The smoothing algorithm is
+the same as that used in the other tasks. The tasks to make these types
+of corrections are \fBmkillumcor\fR and \fBmkillumflat\fR. The usage
+is pretty much the same as the other illumination correction tasks
+except that it is more reasonable to replace the original flat fields
+by the corrected flat fields when fixing the flat field. Examples
+of an illumination correction and removing the illumination pattern
+from the flat field are
+
+.nf
+.ft L
+ cl> mkillumcor flat025 Illum025
+ cl> mkillumflat flat*.imh ""
+.ft R
+.fi
+
+As with the other tasks, the input images are processed if necessary.
+.NH 2
+Fringe Corrections
+.LP
+ Some CCD detectors suffer from fringing effects due to the night
+sky emission lines which are not removed by the other calibration
+and correction operations. To correct for the fringing you need a
+really blank sky image. There is not yet a task to remove objects from
+sky images because this is often done with an interactive image display
+tool (which will soon be added). The blank sky image is heavily smoothed
+to determine the mean sky background and then this is subtracted from the
+original image. The image should then be essentially zero except for the
+fringe pattern. This fringe correction image is scaled to the same
+exposure time as the image to be corrected and then subtracted to remove
+the fringing. Note that since the night sky lines are variable there
+may need to be an additional scaling applied. Determining this scaling
+requires either an interactive display tool or a very clever task.
+Such tasks will also be added in the future.
+
+ The task to make a fringe correction image is \fBmkfringecor\fR.
+the sky background is determined in exactly the same way as the illumination
+pattern, in fact the same sky image may be used for both the sky
+illumination and for the fringe correction. The task works consistently
+with the "mk" tasks in that the input images are processed first if needed
+and then the output correction image is produced with the specified name
+or replaces the input image if no output image is specified.
+As examples,
+
+.nf
+.ft L
+ cl> mkfringecor sky004 Fringe
+ cl> mkfringecor sky*.imh ""
+.ft R
+.fi
+.NH
+Demonstration
+.LP
+ A simple demonstration task is available. To run this demonstration
+load the \fBccdtest\fR package; this is a subpackage of the main
+\fBccdred\fR package. Then simply type
+
+.ft L
+ cl> demo
+.ft R
+
+The demonstration will then create some artificial CCD data and reduce
+them giving descriptive comments as it goes along. This demonstration uses
+the "playback" facility of the command language and is actually substituting
+it's own commands for terminal input. Initially you must type carriage return
+or space after each comment ending with "...". If you wish to have the
+demonstration run completely automatically at it's own speed then type 'g'
+a the "..." prompt. Thereafter, it will simple pause long enough to give
+you a chance to read the comments. When the demo is finished you will
+need to remove the files created. However, feel free to examine the reduced
+images, the log file, etc. \fINote that the demonstration changes the
+setup parameters so be sure to run \fBsetinstrument\fI again and check
+the setup parameters.\fR
+.NH
+Summary
+.LP
+ The \fBccdred\fR package is very easy to use. First load the package;
+it is in the \fBimred\fR package which is in the \fBnoao\fR package.
+If this is your first time reducing data from a particular instrument
+or if you have changed instruments then run \fBsetinstrument\fR.
+Set the processing parameters for the operations you want performed.
+If you need to combine calibration images to form a master calibration
+image use one of the combine tasks. Spectroscopic flat fields may
+need to be processed first in order to remove the lamp spectrum.
+Finally, just type
+
+.ft L
+ cl> ccdproc *.imh&
+.ft R
+.SH
+References
+.LP
+ A general guide to using IRAF is \fIA User's Introduction to the IRAF
+Command Language\fR. This document may be found in the IRAF documentation
+sets and is available from the National Optical Astronomy Observatories,
+Central Computer Services (NOAO-CCS).
+
+ A more detailed description of the \fBccdred\fR package including
+a discussion of the design and some of the algorithms see \fIThe IRAF
+CCD Reduction Package -- CCDRED\fR" by F. Valdes. This paper is available
+from NOAO-CCS and appears in the proceedings of the Santa Cruz Summer
+Workshop in Astronomy and Astrophysics, \fIInstrumentation for Ground-Based
+Optical Astronomy: Present and Future\fR, edited by Lloyd B. Robinson and
+published by Springer-Verlag.
+
+ The task descriptions and supplementary documentation are available
+in printed form in the IRAF documentation sets, a special set
+containing documentation for just the \fBccdred\fR package, and on-line
+through the help task by typing
+
+.ft L
+ cl> help \fItopic\fR
+.ft R
+
+where \fItopic\fR is one of the following.
+
+.nf
+.ft L
+ badpiximage - Create a bad pixel mask image from a bad pixel file
+ ccdgroups - Group CCD images into image lists
+ ccdhedit - CCD image header editor
+ ccdlist - List CCD processing information
+ ccdproc - Process CCD images
+ ccdtest - CCD test and demonstration package
+ combine - Combine CCD images
+ cosmicrays - Detect and replace cosmic rays
+ darkcombine - Combine and process dark count images
+ flatcombine - Combine and process flat field images
+ mkfringecor - Make fringe correction images from sky images
+ mkillumcor - Make flat field illumination correction images
+ mkillumflat - Make illumination corrected flat fields
+ mkskycor - Make sky illumination correction images
+ mkskyflat - Make sky corrected flat field images
+setinstrument - Set instrument parameters
+ zerocombine - Combine and process zero level images
+
+ ADDITIONAL HELP TOPICS
+
+ ccdred - CCD image reduction package
+ ccdtypes - Description of the CCD image types
+ flatfields - Discussion of CCD flat field calibrations
+ guide - Introductory guide to using the CCDRED package
+ instruments - Instrument specific data files
+ subsets - Description of CCD subsets
+.ft R
+.fi
+
+Printed copies of the on-line help documentation may be made with the
+command
+
+.ft L
+ cl> help \fItopic\fL | lprint
+.ft R
+
+ In addition to the package documentation for \fBccdred\fR,
+\fBlongslit\fR, and \fBapextract\fR there may be specific guides for
+certain instruments. These specific guides, called "cookbooks", give
+specific examples and parameter values for the CCD data.
diff --git a/noao/imred/quadred/src/quad/doc/instruments.hlp b/noao/imred/quadred/src/quad/doc/instruments.hlp
new file mode 100644
index 00000000..2b2c92f7
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/instruments.hlp
@@ -0,0 +1,248 @@
+.help instruments Jun87 noao.imred.ccdred
+
+.ih
+NAME
+instruments -- Instrument specific data files
+.ih
+DESCRIPTION
+The \fBccdred\fR package has been designed to accommodate many different
+instruments, detectors, and observatories. This is done by having
+instrument specific data files. Note that by instrument we mean a
+combination of detector, instrument, application, and observatory, so
+there might be several "instruments" associated with a particular CCD
+detector. Creating and maintaining the instrument files is generally
+the responsibility of the support staff, though the user may create or
+copy and modify his/her own instrument/application specific files. The
+task \fBsetinstrument\fR makes this information available to the user
+and package easily.
+
+There are three instrument data files, all of which are optional. The
+package may be used without the instrument files but much of the
+convenience of the package, particularly with respect to using the CCD
+image types, will be lost. The three files are an instrument image
+header translation file, an initialization task which mainly sets
+default task parameters, and a bad pixel file identifying the cosmic
+bad pixels in the detector. These files are generally stored in a
+system data directory which is a subdirectory of the logical
+directory "ccddb$". Each file has a root name which identifies the
+instrument.
+.sh
+1. Instrument Translation File
+The instrument translation file translates the parameter names used by
+the \fBccdred\fR pacakge into instrument specific parameters and also
+supplies instrument specific default values. The package parameter
+\fIccdred.instrument\fR specifies this file to the package. The task
+\fBsetinstrument\fR sets this parameter, though it can be set
+explicitly like any other parameter. For the standard instrument
+translation file the root name is the instrument identification and the
+extension is "dat" ("*.dat" files are protected from being removed in a
+"stripped" system, i.e. when all nonessential files are removed).
+Private instrument files may be given any name desired.
+
+The instrument translation proceeds as follows. When a package task needs
+a parameter for an image, for example "imagetyp", it looks in the instrument
+translation file. If the file is not found or none is specified then the
+image header keyword that is requested has the same name. If an
+instrument translation file is defined then the requested
+parameter is translated to an image header keyword, provided a translation
+entry is given. If no translation is given the package name is used. For
+example the package parameter "imagetyp" might be translated to "data-typ"
+(the old NOAO CCD keyword). If the parameter is not found then the default
+value specified in the translation file, if present, is returned. For recording
+parameter information in the header, such as processing flags, the
+translation is also used. The default value has no meaning in this case.
+For example, if the flag specifying that the image has been corrected
+by a flat field is to be set then the package parameter name "flatcor"
+might be translated to "ff-flag". If no translation is given then the
+new image header parameter is entered as "flatcor".
+
+The format of the translation file are lines consisting of the package
+parameter name, followed by the image header keyword, followed by the
+default value. The first two fields are parameter names. The fields
+are separated by whitespace (blanks and tabs). String default values
+containing blanks must be quoted. An example is given below.
+
+.nf
+ exptime itime
+ darktime itime
+ imagetyp data-typ
+ subset f1pos
+ biassec biassec [411:431,2:573]
+ datasec datasec [14:385,2:573]
+
+ fixpix bp-flag 0
+ overscan bt-flag 0
+ zerocor bi-flag 0
+ darkcor dk-flag 0
+ flatcor ff-flag 0
+ fringcor fr-flag 0
+.fi
+
+The first two lines translate the CCD image type, and the subset parameter
+without default values (see \fBccdtypes\fR and \fBsubsets\fR for more
+information). The next two lines give the overscan bias strip
+section and the data section with default values for the instrument.
+Note that these parameters may be overridden in the task \fBccdproc\fR.
+The blank line is ignored.
+
+The next set of translations requires further discussion. For processing
+flags the package assumes that the absence of a keyword means that the
+processing has not been done. If processing is always to be done with
+the \fBCCDRED\fR package and no processing keywords are recorded in the raw data
+then these parameters should be absent (unless you don't like the names
+used by the package). However, for compatibility with the original NOAO
+CCD images, which may be processed outside of IRAF and which use 0 as the
+no processing value, the processing flags are translated and the false values
+are indicated by the default values.
+
+In addition to the parameter name translations the translation file
+contains translations between the value of the image type parameter
+and the image types used by the package. These lines
+consist of the image header type string as the first field (with quotes
+if there are blanks) and the image type as recognized by the package. The
+following example will make this clearer.
+
+.nf
+ 'OBJECT (0)' object
+ 'DARK (1)' dark
+ 'PROJECTOR FLAT (2)' flat
+ 'SKY FLAT (3)' other
+ 'COMPARISON LAMP (4)' other
+ 'BIAS (5)' zero
+ 'DOME FLAT (6)' flat
+.fi
+
+The values of the image type strings in the header contain blanks so they
+are quoted. Also the case of the strings is important. Note that there
+are two types of flat field images and three types of object images.
+
+The CCD image types recognized by the package are:
+
+.nf
+ zero - zero level image such as a bias or preflash
+ dark - dark count image
+ flat - flat field image
+ illum - iillumination image such as a sky image
+ fringe - fringe correction image
+ object - object image
+.fi
+
+There may be more than one image type that maps to the same package
+type. In particular other standard CCD image types, such as comparison
+spectra, multiple exposure, standard star, etc., should be mapped to
+object or other. There may also be more than one type of flat field,
+i.e. dome flat, sky flat, and lamp flat. For more on the CCD image
+types see \fBccdtypes\fR.
+
+The complete set of package parameters are given below.
+The package parameter names are generally the same as the
+standard image header keywords being adopted by NOAO.
+
+.nf
+ General Image Header and Default Parameters
+ ccdmean darktime exptime fixfile
+ imagetyp ncombine biassec subset
+ title datasec
+
+ CCDRED Processing Flags
+ ccdproc darkcor fixpix flatcor
+ fringcor illumcor overscan trim
+ zerocor
+
+ CCDRED CCD Image Types
+ dark flat fringe illum
+ none object unknown zero
+.fi
+
+The translation mechanism described here may become more
+sophisticated in the future and a general IRAF system facility may be
+implemented eventually. For the present the translation mechanism is
+quite simple.
+.sh
+2. Instrument Setup Script
+The task \fBsetinstrument\fR translates an instrument ID into a
+CL script in the instrument directory. This script is then executed.
+Generally this script simply sets the task parameters for an
+instrument/application. However, it could do anything else the support
+staff desires. Below are the first few lines of a typical instrument setup
+script.
+
+.nf
+ ccdred.instrument = "ccddb$kpno/example.dat"
+ ccdred.pixeltype = "real"
+ ccdproc.fixpix = yes
+ ccdproc.overscan = yes
+ ccdproc.trim = yes
+ ccdproc.zerocor = no
+ ccdproc.darkcor = no
+ ccdproc.flatcor = yes
+ ccdproc.biassec = "[411:431,2:573]"
+ ccdproc.datasec = "[14:385,2:573]"
+.fi
+
+The instrument parameter should always be set unless there is no
+translation file for the instrument. The \fBccdproc\fR parameters
+illustrate setting the appropriate processing flags for the
+instrument. The overscan bias and trim data sections show an alternate
+method of setting these instrument specific parameters. They may be
+set in the setup script in which case they are given explicitly in the
+user parameter list for \fBccdproc\fR. If the value is "image" then
+the parameters may be determined either through the default value in
+the instrument translation file, as illustrated in the previous
+section, or from the image header itself.
+
+The instrument setup script for setting default task parameters may be
+easily created by the support person as follows. Set the package
+parameters using \fBeparam\fR or with CL statements. Setting the
+parameters might involve testing. When satisfied with the way the
+package is set then the parameters may be dumped to a setup script
+using the task \fBdparam\fR. The final step is editing this script to
+delete unimportant and query parameters. For example,
+
+.nf
+ cl> dparam ccdred >> file.cl
+ cl> dparam ccdproc >> file.cl
+ cl> dparam combine >> file.cl
+ ...
+ cl> ed file.cl
+.fi
+.sh
+3. Instrument Bad Pixel File
+The bad pixel file describes the bad pixels, columns, and lines in the
+detector which are to be replaced by interpolation when processing the
+images. This file is clearly detector specific. The file consists of
+lines describing rectangular regions of the image.
+The regions are specified by four numbers giving the starting and ending
+columns followed by the starting and ending lines. The starting and
+ending points may be the same to specify a single column or line. The
+example below illustrates a bad pixel file.
+
+.nf
+ # RCA1 CCD untrimmed
+ 25 25 1 512
+ 108 108 1 512
+ 302 302 403 512
+ 1 512 70 70
+ 245 246 312 315
+.fi
+
+If there is a comment line in the file containing the word "untrimmed"
+then the coordinates of the bad pixel regions apply to the original image.
+If the image has been trimmed and the bad pixels are replaced at a later
+stage then this word indicates that the trim region be determined from the
+image header and the necessary coordinate conversion made. If the word
+"untrimmed" does not appear then the coordinates are assumed to apply to
+the image directly; i.e. the trimmed coordinates if the image has been
+trimmed or the original coordinates if the image has not been trimmed.
+The standard bad pixel files should always refer to the original, untrimmed
+coordinates.
+
+The first two bad pixel regions are complete bad columns (the image
+is 512 x 512), the next line is a partial bad column, the next line is
+a bad line, and the last line is a small bad region. These files are
+easy to create, provided you have a good image to work from and a way
+to measure the positions with an image or graphics display.
+.ih
+SEE ALSO
+ccdtypes, subsets, setinstrument
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/mkfringecor.hlp b/noao/imred/quadred/src/quad/doc/mkfringecor.hlp
new file mode 100644
index 00000000..797f4d11
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/mkfringecor.hlp
@@ -0,0 +1,90 @@
+.help mkfringecor Feb88 noao.imred.ccdred
+.ih
+NAME
+mkfringecor -- Make fringe correction images from sky images
+.ih
+USAGE
+mkfringecor input output
+.ih
+PARAMETERS
+.ls input
+List of input images for making fringe correction images.
+.le
+.ls output
+List of output fringe correction images. If none is
+specified or if the name is the same as the input image then the output
+image replaces the input image.
+.le
+.ls ccdtype = ""
+CCD image type to select from the input images. If none is specified
+then all types are used.
+.le
+.ls xboxmin = 5, xboxmax = 0.25, yboxmin = 5, yboxmax = 0.25
+Minimum and maximum smoothing box size along the x and y axes. The
+minimum box size is used at the edges and grows to the maximum size in
+the middle of the image. This allows the smoothed image to better
+represent gradients at the edge of the image. If a size is less then 1
+then it is interpreted as a fraction of the image size. If a size is
+greater than or equal to 1 then it is the box size in pixels. A size
+greater than the size of image selects a box equal to the size of the
+image.
+.le
+.ls clip = yes
+Clean the input images of objects? If yes then a clipping algorithm is
+used to detect and exclude objects from the smoothing.
+.le
+.ls lowsigma = 2.5, highsigma = 2.5
+Sigma clipping thresholds above and below the smoothed background.
+.le
+.ls ccdproc (parameter set)
+CCD processing parameters.
+.le
+.ih
+DESCRIPTION
+The input blank sky images are automatically processed up through the
+iillumination correction before computing the fringe correction images.
+The fringe corrections are subset dependent.
+The slowly varying background is determined and subtracted leaving only
+the fringe pattern caused by the sky emission lines. These fringe images
+are then scaled and subtracted from the observations by \fBccdproc\fR.
+The background is determined by heavily smoothing the image using a
+moving "boxcar" average. The effects of the objects and fringes in the
+image is minimized by using a sigma clipping algorithm to detect and
+exclude them from the average. Note, however, that objects left in the
+fringe image will affect the fringe corrected observations. Any objects
+in the sky image should be removed using \fBskyreplace\fR (not yet
+available).
+
+The smoothing algorithm is a moving average over a two dimensional
+box. The algorithm is unconvential in that the box size is not fixed.
+The box size is increased from the specified minimum at the edges to
+the maximum in the middle of the image. This permits a better estimate
+of the background at the edges, while retaining the very large scale
+smoothing in the center of the image. Note that the sophisticated
+tools of the \fBimages\fR package may be used for smoothing but this
+requires more of the user and, for the more sophisticated smoothing
+algorithms such as surface fitting, more processing time.
+
+To minimize the effects of the fringes and any objects in the blank sky
+calibration images a sigma clipping algorithm is used to detect and
+exclude features from the background. This is done by computing the
+rms of the image lines relative to the smoothed background and
+excluding points exceeding the specified threshold factors times the
+rms. This is done before each image line is added to the moving
+average, except for the first few lines where an iterative process is
+used.
+.ih
+EXAMPLES
+1. The two examples below make an fringe correction image from a blank
+sky image, "sky017". In the first example a separate fringe
+image is created and in the second the fringe image replaces the
+sky image.
+
+.nf
+ cl> mkskycor sky017 Fringe
+ cl> mkskycor sky017 frg017
+.fi
+.ih
+SEE ALSO
+ccdproc
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/mkillumcor.hlp b/noao/imred/quadred/src/quad/doc/mkillumcor.hlp
new file mode 100644
index 00000000..0effd7a2
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/mkillumcor.hlp
@@ -0,0 +1,92 @@
+.help mkillumcor Oct88 noao.imred.ccdred
+.ih
+NAME
+mkillumcor -- Make flat field iillumination correction images
+.ih
+USAGE
+mkillumcor input output
+.ih
+PARAMETERS
+.ls input
+List of input images for making flat field iillumination correction images.
+.le
+.ls output
+List of output flat field iillumination correction images. If none is
+specified or if the name is the same as the input image then the output
+image replaces the input image.
+.le
+.ls ccdtype = "flat"
+CCD image type to select from the input images. If none is specified
+then all types are used.
+.le
+.ls xboxmin = 5, xboxmax = 0.25, yboxmin = 5, yboxmax = 0.25
+Minimum and maximum smoothing box size along the x and y axes. The
+minimum box size is used at the edges and grows to the maximum size in
+the middle of the image. This allows the smoothed image to better
+represent gradients at the edge of the image. If a size is less then 1
+then it is interpreted as a fraction of the image size. If a size is
+greater than or equal to 1 then it is the box size in pixels. A size
+greater than the size of image selects a box equal to the size of the
+image.
+.le
+.ls clip = yes
+Clean the input images of objects? If yes then a clipping algorithm is
+used to detect and exclude deviant points from the smoothing.
+.le
+.ls lowsigma = 2.5, highsigma = 2.5
+Sigma clipping thresholds above and below the smoothed iillumination.
+.le
+.ls divbyzero = 1.
+The iillumination correction is the inverse of the smoothed flat field.
+This may produce division by zero. A warning is given if division
+by zero takes place and the result (the iillumination correction value)
+is replaced by the value of this parameter.
+.le
+.ls ccdproc (parameter set)
+CCD processing parameters.
+.le
+.ih
+DESCRIPTION
+First, the input flat field images are automatically processed if
+needed. Then, the large scale iillumination pattern of the images is
+determined by heavily smoothing them using a moving "boxcar" average.
+The iillumination correction, the inverse of the iillumination pattern,
+is applied by \fBccdproc\fR to CCD images to remove the iillumination
+pattern introduced by the flat field. The combination of the flat
+field calibration and the iillumination correction based on the flat
+field is equivalent to removing the iillumination from the flat field
+(see \fBmkillumflat\fR). This two step calibration is generally used
+when the observations have been previously flat field calibrated. This
+task is closely related to \fBmkskycor\fR which determines the
+iillumination correction from a blank sky image; this is preferable to
+using the iillumination from the flat field as it corrects for the
+residual iillumination error. For a general discussion of the options
+for flat fields and iillumination corrections see \fBflatfields\fR.
+
+The smoothing algorithm is a moving average over a two dimensional
+box. The algorithm is unconvential in that the box size is not fixed.
+The box size is increased from the specified minimum at the edges to
+the maximum in the middle of the image. This permits a better estimate
+of the background at the edges, while retaining the very large scale
+smoothing in the center of the image. Note that the sophisticated
+tools of the \fBimages\fR package may be used for smoothing but this
+requires more of the user and, for the more sophisticated smoothing
+algorithms such as surface fitting, more processing time.
+
+To minimize the effects of bad pixels a sigma clipping algorithm is
+used to detect and reject these pixels from the iillumination. This is
+done by computing the rms of the image lines relative to the smoothed
+iillumination and excluding points exceeding the specified threshold
+factors times the rms. This is done before each image line is added to
+the moving average, except for the first few lines where an iterative
+process is used.
+.ih
+EXAMPLES
+1. The example below makes an iillumination correction image from the
+flat field image, "flat017".
+
+ cl> mkillumcor flat017 Illum
+.ih
+SEE ALSO
+ccdproc, flatfields, mkillumflat, mkskycor, mkskyflat
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/mkillumflat.hlp b/noao/imred/quadred/src/quad/doc/mkillumflat.hlp
new file mode 100644
index 00000000..8288fb85
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/mkillumflat.hlp
@@ -0,0 +1,101 @@
+.help mkillumflat Oct88 noao.imred.ccdred
+.ih
+NAME
+mkillumflat -- Make illumination corrected flat fields
+.ih
+USAGE
+mkillumflat input output
+.ih
+PARAMETERS
+.ls input
+List of input flat field images to be illumination corrected.
+.le
+.ls output
+List of output illumination corrected flat field images.
+If none is specified or if the name is the same as the
+input image then the output image replaces the input image.
+.le
+.ls ccdtype = "flat"
+CCD image type to select from the input images.
+.le
+.ls xboxmin = 5, xboxmax = 0.25, yboxmin = 5, yboxmax = 0.25
+Minimum and maximum smoothing box size along the x and y axes. The
+minimum box size is used at the edges and grows to the maximum size in
+the middle of the image. This allows the smoothed image to better
+represent gradients at the edge of the image. If a size is less then 1
+then it is interpreted as a fraction of the image size. If a size is
+greater than or equal to 1 then it is the box size in pixels. A size
+greater than the size of image selects a box equal to the size of the
+image.
+.le
+.ls clip = yes
+Clean the input images of objects? If yes then a clipping algorithm is
+used to detect and exclude objects from the smoothing.
+.le
+.ls lowsigma = 2.5, highsigma = 2.5
+Sigma clipping thresholds above and below the smoothed illumination.
+.le
+.ls divbyzero = 1.
+The illumination flat field is the ratio of the flat field to a
+smoothed flat field. This may produce division by zero. A warning is
+given if division by zero takes place and the result (the illumination
+corrected flat field value) is replaced by the value of this
+parameter.
+.le
+.ls ccdproc (parameter set)
+CCD processing parameters.
+.le
+.ih
+DESCRIPTION
+First, the input flat field images are processed as needed. Then the
+large scale illumination pattern of the images is removed. The
+illumination pattern is determined by heavily smoothing the image using
+a moving "boxcar" average. The output image is the ratio of the input
+image to the illumination pattern. The illumination pattern is
+normalized by its mean to preserve the mean level of the input image.
+
+When this task is applied to flat field images only the small scale
+response effects are retained. This is appropriate if the flat field
+images have illumination effects which differ from the astronomical
+images and blank sky images are not available for creating sky
+corrected flat fields. When a high quality blank sky image is
+available the related task \fBmkskyflat\fR should be used. Note that
+the illumination correction, whether from the flat field or a sky
+image, may be applied as a separate step by using the task
+\fBmkillumcor\fR or \fBmkskycor\fR and applying the illumination
+correction as a separate operation in \fBccdproc\fR. However, creating
+an illumination corrected flat field image before processing is more
+efficient since one less operation per image processed is needed. For
+more discussion about flat fields and illumination corrections see
+\fBflatfields\fR.
+
+The smoothing algorithm is a moving average over a two dimensional
+box. The algorithm is unconvential in that the box size is not fixed.
+The box size is increased from the specified minimum at the edges to
+the maximum in the middle of the image. This permits a better estimate
+of the background at the edges, while retaining the very large scale
+smoothing in the center of the image. Note that the sophisticated
+tools of the \fBimages\fR package may be used for smoothing but this
+requires more of the user and, for the more sophisticated smoothing
+algorithms such as surface fitting, more processing time.
+
+To minimize the effects of bad pixels a sigma clipping algorithm is
+used to detect and reject these pixels from the illumination. This is
+done by computing the rms of the image lines relative to the smoothed
+illumination and excluding points exceeding the specified threshold
+factors times the rms. This is done before each image line is added to
+the moving average, except for the first few lines where an iterative
+process is used.
+.ih
+EXAMPLES
+1. Two examples in which a new image is created and in which the
+input flat fields are corrected in place are:
+
+.nf
+ cl> mkllumflat flat004 FlatV
+ cl> mkillumflat flat* ""
+.fi
+.ih
+SEE ALSO
+ccdproc, flatfields, mkfringecor, mkillumcor, mkskycor, mkskyflat
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/mkskycor.hlp b/noao/imred/quadred/src/quad/doc/mkskycor.hlp
new file mode 100644
index 00000000..15cfacf6
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/mkskycor.hlp
@@ -0,0 +1,103 @@
+.help mkskycor Feb88 noao.imred.ccdred
+.ih
+NAME
+mkskycor -- Make sky iillumination correction images
+.ih
+USAGE
+mkskycor input output
+.ih
+PARAMETERS
+.ls input
+List of input images for making sky iillumination correction images.
+.le
+.ls output
+List of output flat field iillumination correction images. If none is
+specified or if the name is the same as the input image then the output
+image replaces the input image.
+.le
+.ls ccdtype = ""
+CCD image type to select from the input images. If none is specified
+then all types are used.
+.le
+.ls xboxmin = 5, xboxmax = 0.25, yboxmin = 5, yboxmax = 0.25
+Minimum and maximum smoothing box size along the x and y axes. The
+minimum box size is used at the edges and grows to the maximum size in
+the middle of the image. This allows the smoothed image to better
+represent gradients at the edge of the image. If a size is less then 1
+then it is interpreted as a fraction of the image size. If a size is
+greater than or equal to 1 then it is the box size in pixels. A size
+greater than the size of image selects a box equal to the size of the
+image.
+.le
+.ls clip = yes
+Clean the input images of objects? If yes then a clipping algorithm is
+used to detect and exclude objects from the smoothing.
+.le
+.ls lowsigma = 2.5, highsigma = 2.5
+Sigma clipping thresholds above and below the smoothed iillumination.
+.le
+.ls ccdproc (parameter set)
+CCD processing parameters.
+.le
+.ih
+DESCRIPTION
+The large scale iillumination pattern of the input images, generally
+blank sky calibration images, is determined by heavily smoothing
+the image using a moving "boxcar" average. The effects of objects in
+the image may be minimized by using a sigma clipping algorithm to
+detect and exclude the objects from the average. This
+iillumination image is applied by \fBccdproc\fR to CCD images to remove
+the iillumination pattern.
+
+The input images are automatically processed up through flat field
+calibration before computing the iillumination. The iillumination
+correction is that needed to make the processed images flat
+over large scales. The input images are generally blank sky calibration
+images which have the same iillumination and instrumental effects
+as the object observations. Object images may be used but removal
+of the objects may not be very good; particularly large, bright objects.
+For further discussion of flat fields and iillumination corrections
+see \fBflatfields\fR.
+
+You will notice that when you process images with an iillumination
+correction you are dividing each image by a flat field calibration and
+an iillumination correction. If the iillumination corrections are not
+done as a later step but at the same time as the rest of the processing
+one will get the same calibration by multiplying the flat field by the
+iillumination correction and using this product alone as the flat
+field. This approach has the advantage of one less calibration image
+and two less computations (scaling and dividing the iillumination
+correction). Such an image, called a \fIsky flat\fR, may be created by
+\fBmkskyflat\fR as an alternative to this task.
+
+The smoothing algorithm is a moving average over a two dimensional
+box. The algorithm is unconvential in that the box size is not fixed.
+The box size is increased from the specified minimum at the edges to
+the maximum in the middle of the image. This permits a better estimate
+of the background at the edges, while retaining the very large scale
+smoothing in the center of the image. Note that the sophisticated
+tools of the \fBimages\fR package may be used for smoothing but this
+requires more of the user and, for the more sophisticated smoothing
+algorithms such as surface fitting, more processing time.
+
+Blank sky images may not be completely blank so a sigma clipping
+algorithm may be used to detect and exclude objects from the
+iillumination pattern. This is done by computing the rms of the image
+lines relative to the smoothed background and excluding points
+exceeding the specified threshold factors times the rms. This is done
+before each image line is added to the moving average, except for the
+first few lines where an iterative process is used.
+.ih
+EXAMPLES
+1. The two examples below make an iillumination image from a blank sky image,
+"sky017". In the first example a separate iillumination image is created
+and in the second the iillumination image replaces the sky image.
+
+.nf
+ cl> mkskycor sky017 Illum
+ cl> mkskycor sky017 sky017
+.fi
+.ih
+SEE ALSO
+ccdproc, flatfields, mkillumcor, mkillumflat, mkskyflat
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/mkskyflat.hlp b/noao/imred/quadred/src/quad/doc/mkskyflat.hlp
new file mode 100644
index 00000000..3d9ac1ca
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/mkskyflat.hlp
@@ -0,0 +1,111 @@
+.help mkskyflat Feb88 noao.imred.ccdred
+.ih
+NAME
+mkskyflat -- Make sky corrected flat field images
+.ih
+USAGE
+mkskyflat input output
+.ih
+PARAMETERS
+.ls input
+List of blank sky images to be used to create sky corrected flat field
+calibration images.
+.le
+.ls output
+List of output sky corrected flat field calibration images (called
+sky flats). If none is specified or if the name is the same as the
+input image then the output image replaces the input image.
+.le
+.le
+.ls ccdtype = ""
+CCD image type to select from the input images.
+.le
+.ls xboxmin = 5, xboxmax = 0.25, yboxmin = 5, yboxmax = 0.25
+Minimum and maximum smoothing box size along the x and y axes. The
+minimum box size is used at the edges and grows to the maximum size in
+the middle of the image. This allows the smoothed image to better
+represent gradients at the edge of the image. If a size is less then 1
+then it is interpreted as a fraction of the image size. If a size is
+greater than or equal to 1 then it is the box size in pixels. A size
+greater than the size of image selects a box equal to the size of the
+image.
+.le
+.ls clip = yes
+Clean the input images of objects? If yes then a clipping algorithm is
+used to detect and exclude objects from the smoothing.
+.le
+.ls lowsigma = 2.5, highsigma = 2.5
+Sigma clipping thresholds above and below the smoothed iillumination.
+.le
+.ls ccdproc (pset)
+CCD processing parameter set.
+.le
+.ih
+DESCRIPTION
+A sky corrected flat field calibration image, called a sky flat, is a
+flat field that when applied to observations of the sky have no large
+scale gradients. Flat field images are generally obtained by exposures
+to lamps either illuminating the telescope field or a surface in the dome
+at which the telescope is pointed. Because the detector is not illuminated
+in the same way as an observation of the sky there may be large
+scale iillumination patterns introduced into the observations with such
+a flat field. To correct this type of flat field a blank sky observation
+(which has been divided by the original flat field) is heavily smoothed
+to remove the noise leaving only the residual large scale iillumination
+pattern. This iillumination pattern is divided into the original flat
+field to remove this residual.
+
+The advantage of creating a sky flat field is that when processing
+the observations no additional operations are required. However,
+if the observations have already been processed with the original
+flat field then the residual iillumination pattern of blank sky
+calibration images may be created as an iillumination correction
+to be applied by \fBccdproc\fR. Such a correction is created by the
+task \fBmkskycor\fR. If a good blank sky image is not
+available then it may be desirable to remove the iillumination pattern
+of the flat field image using \fBmkillumflat\fR or \fBmkillumcor\fR
+provided the sky observations are truly uniformly illuminated.
+For more on flat fields and iillumination corrections see \fBflatfields\fR.
+
+The input, blank sky images are first processed, based on the
+\fBccdproc\fR parameters, if needed. These parameters also determine
+the flat field image to be used in making the sky flat. The residual
+iillumination pattern is determined by heavily smoothing the image using
+a moving "boxcar" average. The effects of objects in the input image
+may be minimized by using a sigma clipping algorithm to detect and
+exclude the objects from the average. The output image is ratio of the
+flat field image, for the same subset as the input image, to the
+residual iillumination pattern determined from the processed blank sky
+input image. The iillumination pattern is normalized by its mean to
+preserve the mean level of the flat field image.
+
+The smoothing algorithm is a moving average over a two dimensional
+box. The algorithm is unconvential in that the box size is not fixed.
+The box size is increased from the specified minimum at the edges to
+the maximum in the middle of the image. This permits a better estimate
+of the background at the edges, while retaining the very large scale
+smoothing in the center of the image. Note that the sophisticated
+tools of the \fBimages\fR package may be used for smoothing but this
+requires more of the user and, for the more sophisticated smoothing
+algorithms such as surface fitting, more processing time.
+
+Blank sky images may not be completely blank so a sigma clipping
+algorithm may be used to detect and exclude objects from the
+iillumination pattern. This is done by computing the rms of the image
+lines relative to the smoothed background and excluding points
+exceeding the specified threshold factors times the rms. This is done
+before each image line is added to the moving average, except for the
+first few lines where an iterative process is used.
+.ih
+EXAMPLES
+1. Two examples in which a new image is created and in which the
+input sky images are converted to sky flats are:
+
+.nf
+ cl> mkskyflat sky004 Skyflat
+ cl> mkskyflat sky* ""
+.fi
+.ih
+SEE ALSO
+ccdproc, flatfields, mkfringecor, mkillumcor, mkillumflat, mkskycor
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/quad.hlp b/noao/imred/quadred/src/quad/doc/quad.hlp
new file mode 100644
index 00000000..7f8754ee
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/quad.hlp
@@ -0,0 +1,121 @@
+.help package Sep93 arcon.quad
+.ih
+NAME
+quad -- reduction package for CCD images obtained with Arcon
+
+.ih
+USAGE
+quad
+
+This package \fBmust\fR be used in place of \fBccdred\fR for the first steps
+(overscan correction and trimming) of multi-readout (quad or dual) images.
+Either package can be used for the subsequent stages, and for the complete
+reduction of single readout images.
+
+.ih
+PARAMETERS
+.ls pixeltype = "real real"
+Output pixel datatype and calculation datatype. When images are processed
+or created the output pixel datatype is determined by this parameter.
+The allowed types are "short" for short integer, and "real" for real
+floating point. The calculation datatypes are also short and real with a
+default of real if none is specified. Note that Arcon generates images of type
+"ushort" (unsigned 16-bit integers). In general both the output and calculation
+types should, therefore, be set to "real" to avoid truncation and wrap
+around errors, although this means that the reduced images will occupy twice as
+much disk space.
+.le
+.ls verbose = no
+Print log information to the standard output?
+.le
+.ls logfile = "logfile"
+Text log file. If no filename is specified then no log file is kept.
+.le
+.ls plotfile = ""
+Log metacode plot file for the overscan bias vector fits. If
+no filename is specified then no metacode plot file is kept.
+.le
+.ls backup = ""
+Backup prefix for backup images. If no prefix is specified then no backup
+images are kept when processing. If specified then the backup image
+has the specified prefix.
+.le
+.ls instrument = ""
+CCD instrument translation file. This is usually set with \fBsetinstrument\fR.
+.le
+.ls ssfile = "subsets"
+Subset translation file used to define the subset identifier. See
+\fBsubsets\fR for more.
+.le
+.ls graphics = "stdgraph"
+Interactive graphics output device when fitting the overscan bias vector.
+.le
+.ls cursor = ""
+Graphics cursor input. The default is the standard graphics cursor.
+.le
+.ls version = "Version 2.0 - Sept 93"
+Package version.
+.le
+.ih
+DESCRIPTION
+The \fBquad\fR package contains all the basic tasks necessary for the
+reduction of CCD data obtained with Arcon. With Arcon images are often readout
+using four ("quad") or two ("dual") amplifiers in order to reduce readout time.
+The \fBquad\fR package includes the few special tasks needed to deal with such
+multi-readout data, as well as many standard tasks taken directly from the
+\fBccdred\fR package. The \fBquad\fR package must be used for the first
+reduction steps, overscan correction and trimming, of multi-readout images;
+subsequent steps can be performed using \fBquad\fR or \fBccdred\fR. Either
+package can be used for the complete reduction of conventional single readout
+CCD images.
+
+The \fBquad\fR package also contains the tasks \fBqstatistics\fR and
+\fBqhistogram\fR which can be used for examining raw multi-readout images.
+
+The \fBquad\fR package task itself has several parameters which are common to
+many of the tasks in the package. When images are processed or new image are
+created the output pixel datatype is that specified by the parameter
+\fBpixeltype\fR. Note that CCD processing replaces the original image by the
+processed image so the pixel type of the CCD images may change during
+processing. It is unlikely that real images will be processed to short images
+but the reverse is quite likely. Processing images from short to real
+pixel datatypes will generally increase the amount of disk space
+required (a factor of 2 on most computers).
+
+The tasks produce log output which may be printed on the standard
+output (the terminal unless redirected) and appended to a file. The
+parameter \fIverbose\fR determines whether processing information
+is printed. This may be desirable initially, but when using background
+jobs the verbose output should be turned off. The user may look at
+the end of the log file (for example with \fBtail\fR) to determine
+the status of the processing.
+
+The package was designed to work with data from many different observatories
+and instruments. In order to accomplish this an instrument translation
+file is used to define a mapping between the package parameters and
+the particular image header format. The instrument translation file
+is specified to the package by the parameter \fIinstrument\fR. This
+parameter is generally set by the task \fBsetinstrument\fR. The other
+file used is a subset file. This is generally created and maintained
+by the package and the user need not do anything. For more sophisticated
+users see \fBinstruments\fR and \fBsubsets\fR.
+
+The package has very little graphics
+output. The exception is the overscan bias subtraction. The bias
+vector is logged in the metacode plot file if given. The plot file
+may be examined with the tasks in the \fBplot\fR package such as
+\fBgkimosaic\fR. When interactively fitting the overscan vector
+the graphics input and output devices must be specified. The defaults
+should apply in most cases.
+
+Because processing replaces the input image by the processed image it
+may be desired to save the original image. This may be done by
+specifying a backup prefix with the parameter \fIbackup\fR. For
+example, if the prefix is "orig" and the image is "ccd001", the backup
+image will be "origccd001". The prefix may be a directory but if so it must
+end with '/' or '$' (for logical directories) and the directory must already
+exist.
+.ih
+SEE ALSO
+instruments, setinstrument, subsets
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/quadman.hlp b/noao/imred/quadred/src/quad/doc/quadman.hlp
new file mode 100644
index 00000000..55bfe10d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/quadman.hlp
@@ -0,0 +1,1330 @@
+.help quadman Sep93 Version-0.0
+.ce
+\fIV-ARCON. Reduction of CCD data obtained with Arcon\fR
+
+.nf
+ 1. Introduction
+ 2. Getting the Data
+ 3. Reducing the Data
+ 3.1 Introduction
+ 3.2 Reading the Data from Tape
+ 3.3 Setting Up the Translation File
+ 3.3.1 Setinstrument for CCD Used
+ 3.3.2 Setting the Subsets Parameter and Preparations
+ 3.4 Preparing Individual Calibration Frames
+ 3.5 Processing the calibration frames
+ 3.6 Preparing a Final Flat Field
+ 3.7 Processing the Images
+ 3.8 Creating the Bad Pixel File
+ 3.9 Writing the Data to Tape
+
+
+
+
+
+
+ A thinly disguised version of CCDMAN
+
+
+ Lisa Wells
+
+ Mario Hamuy
+
+ September 30, 1993
+.fi
+.bp
+.ls \fI1. Introduction\fR
+
+CCDRED is a package in IRAF used for CCD data reduction. It is primarily used
+for CCD imaging although various aspects are also used for spectral reduction.
+This document is intended as a guideline to reducing direct CCD images using
+IRAF. If you are reducing spectra, see Section III or IV of
+this manual. If you do not have experience using IRAF we suggest that
+you start by
+reading "An Introduction to IRAF" which will give you a general idea of IRAF
+structure as well as a few fundamental tools. If you plan to use this package
+extensively, there is a demo on the computer as well which will run through
+the reduction process interactively. Once you login and enter IRAF
+type the following:
+
+.nf
+ cl> noao
+ no> imred
+ im> ccdred
+ cc> ccdtest
+ cc>
+.fi
+
+The cc> prompt indicates the package has been loaded. 'ccdtest' contains several
+tasks one of which is 'demo'. Now type 'demo' and follow the instructions. It
+will prompt you, from time to time, to continue to the next section.
+
+The examples shown here are just that, examples. The user must decide
+upon the reduction procedure, naming, convention, etc..., appropriate for
+his/her own data and use the cookbook and examples as guidelines only. The
+examples are shown with prompts, for the package containing the tasks (do not
+type the prompts, of course). It is strongly recommended that you perform an
+'lpar' on every task immediately before using it, unless you are familiar with
+all of its parameters. This is not always shown in the examples, but is normal
+practice even among seasoned IRAF users.
+
+IRAF uses two conventions that you should always keep in mind.
+First, images consist of lines and columns (not rows and columns). Keep in mind
+that the mountain Forth systems for the CCDs are zero-indexed and use rows and
+lines. IRAF uses one-indexed coordinates for images (see figure 1). Second,
+the "order" of a function is the number of independent coefficients for a
+polynomial, or the number of intervals for a spline curve. For example, a cubic
+(third-degree) polynomial is described as "order=4" (four coefficients).
+
+If you require personal assistance in your reductions please contact
+either Mauricio Navarrete or Nelson Saavedra on Tololo (ex 422),
+or Mario Hamuy(ex 210) in La Serena.
+.le
+.bp
+.ls \fI2. Getting the Data\fR
+
+Many observers often get confused about the number and kind of calibration
+frames that must be taken to properly reduce their data. During a whole
+run you should get the following:
+
+1) Bias frames for each night are essential no matter what setup and chip
+you are using. 20-30 of these should be taken and combined.
+
+2) Dome flats should be taken for each filter you are using. Preferably
+this should be done every day, but you can get by with just one per run,
+as long as you take a sufficient number of them, say 20-30.
+
+3) Twilight sky flats are necessary if you want to do photometry to better
+than 2%-3%, if you are doing surface photometry of extended objects,
+or if sky subtraction is critical. We suggest that everyone take sky flats
+since it is a good check of your dome flat iillumination. For some CCDs it
+is better to use a sky flat to flatten your objects and this may depend
+upon the filters being used.
+It was found at the 0.9-m and 1.5-m telescopes that
+sky flats do better in flattening your
+images in the U and B filters. It is therefore
+suggested that you concentrate on getting many U and B sky flats (10 or more)
+since you will probably process your data using them.
+These will be combined in the first steps of the reduction.
+
+4) Darks are worth taking to check that things are working but dark correction
+is not necessary for any of the CCDs now used at CTIO. The dark current
+should be <10 e-/hour/pixel, if greater, then something is wrong and you
+should get it fixed.
+
+5) Photometric standard stars should be taken when needed and as many as
+necessary (>20) to properly calibrate your objects.
+
+You should refer to the instrument manual for more details. We
+suggest that you start taking your calibration frames early in the afternoon so
+that you have enough time left for supper. It is important to note on your
+calibration frames, the positions of bad pixels and then avoid observing
+your objects on these regions of the CCD, especially if you plan to do
+photometry. At the end of the reductions, you may wish to use a bad pixel map
+to correct the bad pixels. This will be discussed later (section 3.8)
+in more detail.
+.le
+.bp
+.ce
+\fI3. Reducing the Data\fR
+.ls \fI3.1 Introduction\fR
+
+A full reduction of CCD data requires the following operations (see the
+flow diagram on the next page):
+
+.nf
+ 1) Combine the bias, flats and darks.
+ 2) Fit and subtract a readout bias given by the overscan strip.
+ 3) Trim the image of overscan strip and border rows and columns.
+ 4) Subtract the dark, if appropriate.
+ 5) Prepare a final flat.
+ 6) Divide by the flat field.
+ 7) Fix the bad pixels in all the images.
+ 8) Fringing corrections may be done at the end.
+.fi
+
+The most general processing, described in this manual, consists of
+overscan subtracting, trimming, bias subtracting, dark subtracting,
+and flat fielding your data. Although dark subtraction is rarely used,
+it is included in this example for generality.
+
+Individual bias, darks, dome and sky flats must be properly combined to give
+good signal to noise calibration frames and to remove cosmic rays. The
+algorithm used to combine the images must have 10 or more frames to do a good
+job of cleaning the cosmic rays. IRAF offers several algorithms for combining
+the individual frames. You should always carefully inspect all the individual
+frames, and the final image to check
+for potential problems.
+
+Having obtained the combined calibration images you should flatten your sky flat
+using the dome flat and examine the result for any significant iillumination
+variation. If these variations are significant they may be fit in order to
+correct your dome flat.
+Fringing corrections may be
+applied. This should be done separately. This is only needed for the RCA
+chips at the 4 meter PF/CCD and the TI chips in the I band. We do not
+currently support this but direction can be given as to what might possibly
+work.
+
+At this level
+the images should be finished except for fixing any bad pixels that may not
+have been taken care of in the flat fielding. Once this is done you may
+do photometry. A photometry manual is available to do your analysis,
+see section VI of this manual, which describe the use of the
+aperture photometry routines in IRAF and the transformation from
+instrumental to standard magnitudes. There is also a manual which was
+written by the IRAF group in Tucson which is a good guide; "A User's
+Guide to Stellar CCD Photometry with IRAF".
+.bp
+.nf
+
+ ==========================
+ = Set Instrument =
+ = and Translation File =
+ ==========================
+ *****
+ ***
+ *
+ ==================================
+ = Combining Calibration Frames =
+ = and Removing Cosmic Rays =
+ ==================================
+ *****
+ ***
+ *
+ ===============================
+ = Processing =
+ = Calibration Frames =
+ ===============================
+ *****
+ ***
+ *
+ ================================
+ = Preparing a Flat Field =
+ ================================
+ *****
+ ***
+ *
+ ==========================
+ = Processing the data =
+ ==========================
+ *****
+ ***
+ *
+ ==========================
+ = Fixing bad pixels =
+ ==========================
+ *****
+ ***
+ *
+ ==========================
+ = Fringe Corrections =
+ = (optional) =
+ ==========================
+.fi
+.le
+.bp
+.ls \fI3.2 Reading the data from Tape\fR
+
+Load the 'dataio' package and allocate the appropriate tape drive:
+
+.nf
+ cl> dataio
+ da> alloc mta
+.fi
+
+If you wish to read fits files from an exabyte, use 'mtx' as the device
+designation. Now mount your tape on the tape drive and be sure you've
+removed the write ring. It is best to create a separate directory for
+each night. This is done using the command 'mkdir night1'. Now change
+to this directory by typing 'cd night1'. Read the data using the task
+'rfits'. You must specify the tape drive name, the list of files you wish
+to read and the "root" file name. If you transferred your data to the
+SUN using 'getpix' then you may wish to use the naming convention given
+to your files, in this case just set the parameter 'oldirafname' to yes.
+In choosing the root file name, it is usually a good idea to include a
+digit in the name to indicate the tape number (eg, "tape1" for the
+first tape; files would be called "tape10001, tape10002,.."); alternatively,
+an offset may be added (eg, offset=89 means the first files would be
+called "tape10090, tape10091,.." or 1+89, 2+89,..).
+
+.nf
+ da> epar rfits (check the parameter list)
+ da> rfits mta 1-999 tape1
+.fi
+
+The file list "1-999" should more than cover the number of files on tape;
+the task will end gracefully at the end of the tape. When finished,
+rewind the tape and deallocate the drive,
+
+.nf
+ da> rew mta
+ da> dealloc mta
+.fi
+
+and remove your tape from the drive. We assume that you kept the old IRAF
+name given to your files throughout the rest of this manual.
+
+.nf
+ \fIrfits\fR
+
+ fits_file = "mta" FITS data source
+ file_list = "1-999" File list
+ iraf_file = "tape1" IRAF filename
+ (make_image = yes) Create an IRAF image?
+ (long_header = no) Print FITS header cards?
+(short_header = yes) Print short header?
+ (datatype = "") IRAF data type
+ (blank = 0.) Blank value
+ (scale = yes) Scale the data?
+ (oldirafname = no) Use old IRAF name in place of iraf_file?
+ (offset = 0) Tape file offset
+ (mode = "ql")
+.fi
+.le
+.bp
+.ce
+\fI3.3 Setting Up the Translation File\fR
+.ls \fI3.3.1 Setinstrument for CCD Used\fR
+
+Start by loading the 'imred' and 'ccdred' packages.
+
+.nf
+ cl> noao
+ no> imred
+ im> ccdred
+ cc>
+.fi
+
+Because the 'ccdred' package was
+designed to work with data from many different observatories and instruments,
+an \fIinstrument translation file\fR is required to define a mapping
+between the package parameters and the particular image header format.
+An example of a translation file is shown on the next page.
+You must define a translation file using the task 'setinstrument'.
+Edit the parameters for the task 'setinstrument' according to the
+list given below and run it.
+The choices for instrument can be found in Appendix A. If the CCD you
+used is not listed, use the generic "ccd" or "cfccd" in the instrument
+parameter in the task.
+
+.nf
+ cc> epar setinstrument (check the parameter list)
+ cc> setinstrument
+.fi
+
+The task will run and prompt you for the instrument ID (a "?" will list
+the possible choices). Answer 'cfccd' and the task will send you into
+the parameter editing mode for
+the task 'ccdred'. It will automatically set the \fIinstrument\fR
+(translation) parameter
+so do not change it. It is a good idea while processing your calibration
+frames to save a copy of the unprocessed images. This will be done
+by the package 'ccdred' if you specify a prefix or subdirectory in the
+parameter 'backup'. In our example, the files will be saved with the prefix
+'B'. When you type 'ctrl-z' to exit you will then be sent to 'ccdproc'
+to edit its parameters. We will edit
+'ccdproc' later so don't worry about it for now.
+
+.nf
+ \fIsetinstrument parameters\fR
+
+ \fIinstrument\fR = "cfccd" Instrument ID (type ? for a list)
+ (\fIsite\fR = "ctio") Site ID
+ (\fIdirectory\fR = "ccddb$") Instrument directory
+ (review = yes) Review instrument parameters?
+ query = "" Instrument ID (type q to quit)
+ (mode = "ql")
+
+ \fIccdred parameters\fR
+
+ (pixeltype = "real real") Output and calculation pixel datatypes
+ (verbose = no) Print log information to the standard output?
+ (logfile = "ccdlog") Text log file
+ (plotfile = "ccdplot") Log metacode plot file
+ (\fIbackup\fR = "B") Backup directory or prefix
+ (\fIinstrument\fR = "ccddb$ctio/cfccd.dat") CCD instrument file
+ (\fIssfile\fR = "subsets") Subset translation file
+ (graphics = "stdgraph") Interactive graphics output device
+ (cursor = "") Graphics cursor input
+ (version = "2: October 1987")
+ (mode = "ql")
+ ($nargs = 0)
+
+.fi
+
+An example of the \fIinstrument translation file\fR follows.
+
+.nf
+
+ exptime exptime
+ darktime darktime
+ imagetyp imagetyp
+ subset filters
+ biassec biassec
+ datasec datasec
+ trimsec trimsec
+ fixfile fixfile
+
+ fixpix bp-flag 0
+ overscan bt-flag 0
+ zerocor bi-flag 0
+ darkcor dk-flag 0
+ flatcor ff-flag 0
+ fringcor fr-flag 0
+
+ OBJECT object
+ DARK dark
+ "PROJECTOR FLAT" flat
+ "SKY FLAT" other
+ COMPARISON other
+ BIAS zero
+ "DOME FLAT" flat
+ MASK other
+.fi
+
+
+The instrument file consists of first, the IRAF parameter and its associated
+image header keyword from the objects. These header values may vary depending
+upon the instrument being used.
+The second section is the
+header flag section which is added to the object as it is being processed to
+mark that the operation has been done. Once an image is zero corrected, the
+keyword bi-flag parameter is added to the image header and set to '0' so that
+the process is not repeated later. The last section is the image-type
+specification. This is used when the imagetyp parameter is read. The header
+value 'OBJECT' is translated to 'object', and a 'SKY FLAT' becomes 'other'.
+If you need to modify the translation file you may copy this file to your
+directory and change the appropriate parameters. If the name of the imagetype
+contains 2 words, then you must put quotes around the designation, for example,
+look at the 'SKY FLAT' line in the above file. Comparison arcs are not used
+in direct imaging and are not needed.
+
+Without the proper translation file, the task 'ccdlist' will give the following:
+
+.nf
+ cc> ccdlist *.imh
+
+ bias001.imh[400,420][short][unknown][]:median of 4 ave of 6 bias
+ flat002.imh[400,420][short][unknown][]:median of 4 ave of 6 flat
+ flat003.imh[400,420][short][unknown][]:median of 4 ave of 6 flat
+ obj004.imh[400,420][short][unknown][]:IC 481 V-filter ........
+ obj005.imh[400,420][short][unknown][]:IC 481 B-filter.........
+ : : : : : : : :
+ obj036.imh[400,420][short][unknown][]:Sky flat B-filter .......
+ obj037.imh[400,420][short][unknown][]:Sky flat V-filter .......
+ : : : : : : : :
+.fi
+
+The [unknown] in the listing means that the frame type is unknown, ie, if
+it is a dark, flat, bias,... etc. The blank brackets should contain the
+filter type and will be taken care of in the next section.
+.le
+.bp
+.ls \fI3.3.2 Setting the Subsets Parameter and Preparing for Processing\fR
+
+The 'ccdred' package groups observations into subsets. The image header
+parameter used to identify the subsets is defined in the \fIinstrument
+translation file\fR. For example, to select subsets by the header parameter
+'filters' the instrument translation file would contain the line
+
+.nf
+ subset filters
+.fi
+
+Now do a 'ccdlist' and you should see the
+correct image type specified for each frame:
+
+.nf
+ cc> ccdlist *.imh
+
+ bias001.imh[400,420][short][zero][]:median of 4 ave of 6 bias
+ flat002.imh[400,420][short][flat][]:median of 4 ave of 6 flat
+ flat003.imh[400,420][short][flat][]:median of 4 ave of 6 flat
+ obj004.imh[400,420][short][object][]:IC 481 V-filter ......
+ obj005.imh[400,420][short][object][]:IC 481 B-filter.......
+ : : : : : : :
+ : : : : : : :
+ obj036.imh[400,420][short][object][]:Sky flat B-filter .....
+ obj037.imh[400,420][short][object][]:Sky flat V-filter .....
+ : : : : : : :
+.fi
+
+Doing this will create a file in your directory called 'subsets'. This is a
+file with a listing of the filter type read from the image header consisting
+of the combination of the upper and lower filter bolt positions. The flats
+were taken with a color balance filter so they have different values from the
+objects in the list. Therefore, you need to edit this file to set the filter
+types properly. The bias and dark were probably taken with a setting that
+corresponds to one of the filters, but it will be ignored. If however, the
+filter type set in the header corresponds to something other than a standard
+filter, set this to some arbitrary value, for example below it is assumed that
+the filter positions for the bias were '0 1', so this is set to '0'.
+
+.nf
+ cc> edit subsets
+.fi
+
+An example of the necessary changes is:
+
+.nf
+ \fISubsets Before | Subsets After\fR
+ '1 0' 1 | '1 0' U
+ '2 0' 2 | '2 0' B
+ '3 0' 3 | '3 0' V
+ '4 0' 4 | '4 0' R
+ '5 0' 5 | '5 0' I
+ '0 1' 01 | '0 1' 0
+ '1 1' 11 | '1 1' U
+ '2 1' 21 | '2 1' B
+ '3 1' 31 | '3 1' V
+ '4 1' 41 | '4 1' R
+ '5 1' 51 | '5 1' I
+.fi
+
+If any of the parameters are not specified properly after doing 'ccdlist',
+then the translation file may be set up improperly. Consult
+Mauricio Navarrete, Nelson Saavedra, or Mario Hamuy.
+
+You must also specify the overscan and trim region.
+The overscan is the region to the far right of the image when plotting a line
+of the image (see figure 2a). The overscan region should be
+specified by the beginning and ending column followed by the beginning and
+ending line. This region should begin at least 5-10 pixels from the edge of
+the active region of the CCD. The correct position can be found by plotting
+several lines using ':l #1 #2' (#1 and #2 specify a range of lines to be
+averaged and plotted) in 'implot', and expanding the right side (see figure 2b).
+Notice the signal decays toward the right just the other side of the step with
+an e-folding distance of a few pixels. The overscan strip should begin in 3 to
+4 e-folding distances from the break. You want to fit this region all along
+the image so the range of lines should include everything. Be sure to write
+down these values so you don't forget them.
+
+The trim region is the section of the image to be kept after processing.
+Choose this area excluding the overscan region
+and any bad lines or columns at the edges of the image. Figures 2c and 2d show
+a plot of a line and column, respectively. They show the edges which should be
+trimmed from the image. Later (section 3.5)
+you will edit the parameters for 'ccdproc' and enter the overscan and trim
+section.
+
+The bad pixel file will be used after the images have been flattened. In many
+cases the flatfielding will correct the bad pixel regions also so it is best
+left until the end. If you specify the bad pixel file during the processing
+be aware that the corrections are done on the file first.
+.le
+.bp
+.ls \fI3.4 Preparing Individual Calibration Frames\fR
+
+If you have taken many calibration frames (bias, dome flats, darks
+and sky flats) that you wish to combine in order to remove cosmic
+rays, we suggest you to perform a combination of images separately for
+each night. In some cases, when the instrument response remains
+stable during your run, it is worth combining data from many nights,
+especially the darks and sky flats, to improve the signal-to-noise
+ratio. If you have already combined the data on the mountain skip
+over this section and go on to the next one.
+
+Most likely you used "getpix" to transfer your data from the LSI
+to the SUN so you have preserved the naming convention. This makes
+it very easy to combine your images.
+
+There are tasks which combine each type of object together. For the
+bias do an 'epar' on the 'zerocombine' task, and fill the parameters
+according to the list given below. We suggest selecting the 'avsigclip'
+rejection operation which applies a
+sigma clipping algorithm to each pixel to remove cosmic rays. This
+algorithm requires at least three input images (best with
+more than 10) to work effectively. According to your particular needs you may
+select other options to combine the data like minmax, ccdclip, etc.
+No scaling is performed on the biases.
+If your bias frames vary greatly, then there
+is something wrong with your setup. In this case, have someone check
+out the electronics.
+
+.nf
+ cc> epar zerocombine (check the list given below)
+.fi
+
+Then combine the bias frames. Optionally you may add a '&' at the end
+of the command line to submit the task as a background job.
+
+.nf
+ cc> zerocombine bias*.imh output=zero1 &
+.fi
+
+Now, proceed with the combination of the darks.
+
+.nf
+ cc> epar darkcombine (check the list given below)
+ cc> darkcombine dark*.imh output=dark1 &
+.fi
+
+Before combining the flat frames, you must
+find a region free of bad pixels to be used to scale the individual
+flat frames. The box should be chosen where there is signal.
+Once you have determined the position of the box, you
+should first run 'imstat' for all your images using this region.
+
+.nf
+ cc> imstat flat*[200:250,300:330]
+
+ # IMAGE NPIX MEAN STDDEV MIN MAX
+ flat001.imh[200:250,300:330] 37901 5489. 1510. 678. 9020.
+ flat002.imh[200:250,300:330] 37901 5485. 1508. 694. 8484.
+ flat003.imh[200:250,300:330] 37901 5478. 1507. 691. 8472.
+ flat004.imh[200:250,300:330] 37901 5475. 1506. 671. 8397.
+ flat005.imh[200:250,300:330] 37901 5474. 1506. 659. 8540.
+ flat006.imh[200:250,300:330] 37901 5472. 1505. 663. 8422.
+ flat007.imh[200:250,300:330] 37901 5467. 1504. 655. 15513.
+ flat008.imh[200:250,300:330] 37901 5464. 1502. 673. 8471.
+ flat009.imh[200:250,300:330] 37901 5458. 1501. 684. 8503.
+.fi
+
+If the mean varies by a large amount, say greater than a few percent, then
+you should use the mode section for the scaling.
+In the example below the flats are combined with scaling.
+Enter this region in the 'statsec' parameter in the following format,
+
+.nf
+ [x1:x2,y1:y2]
+.fi
+
+where the values x1 and x2 are the limits of the box in the x-axis, y1
+and y2 are the limits along the y-axis. This will only be
+used if 'median' is specified in the 'scale' parameter of the task
+'flatcombine'. In this example we have chosen to combine the individual
+flats using the 'ccdclip' option, which rejects pixels using the CCD noise
+parameters, namely the read-out-noise and the gain. You must enter these
+values in the parameters 'rdnoise' and 'gain' in 'flatcombine'. In this
+example we have entered a read-out-noise of 5 electrons, and a gain of
+2.5 electrons/ADU.
+
+.nf
+ cc> epar flatcombine (check the list given below)
+.fi
+
+Proceed with the combination of the flats.
+
+.nf
+ cc> flatcombine flat.*imh output=flat1 &
+.fi
+
+If you have 3 or more sky flats, they may be combined in the same manner
+as the dome flats (change the 'ccdtype' parameter to 'other').
+
+.nf
+ cc> epar flatcombine (check the list given below)
+ cc> flatcombine sky.*imh output=sky1 &
+.fi
+
+The output at this point is a set of images clean of cosmic rays called zero1,
+dark1, flat1, and sky1, where the 1 stands for the first night and the flats
+and skys end in their respective filter type ie, flat1U, flat1B,... Using the
+parameter subsets, the combination occurred for all the flats and skys of the
+same filter type (subset). We suggest that you examine these images, either by
+displaying, or imploting them. For example;
+
+.nf
+ cc> display zero1
+ cc> implot zero1
+.fi
+
+We suggest also to look at the logfile created by the package 'ccdred' in
+order to check that the images were properly combined by the same filter
+type.
+
+.nf
+ cc> page ccdlog
+.fi
+.bp
+
+.nf
+ \fIzerocombine\fR
+
+ input = "bias*.imh" List of zero level images to combine
+ (output = "zero1") Output zero level name
+ (\fIcombine\fR = "average") Type of combine operation
+ (\fIreject\fR = "avsigclip") Type of rejection
+ (\fIccdtype\fR = "zero") CCD image type to combine
+ (process = no) Process images before combining?
+ (delete = no) Delete input images after combining?
+ (clobber = no) Clobber existing output image?
+ (\fIscale\fR = "none") Image scaling
+ (statsec = "") Image section for computing statistics
+ (nlow = 0) minmax: Number of low pixels to reject
+ (nhigh = 1) minmax: Number of high pixels to reject
+ (nkeep = 1) Minimum to keep (pos) or maximum to reject
+ (mclip = yes) Use median in sigma clipping algorithms?
+ (lsigma = 3.) Lower sigma clipping factor
+ (hsigma = 3.) Upper sigma clipping factor
+ (rdnoise = "0") ccdclip: CCD readout noise (electrons)
+ (gain = "1") ccdclip: CCD gain (electrons/DN)
+ (snoise = "0.") ccdclip: Sensitivity noise (fraction)
+ (pclip = -0.5) pclip: Percentile clipping parameter
+ (blank = 0.) Value if there are no pixels
+ (mode = "ql")
+
+ \fIdarkcombine\fR
+
+ input = "dark.*imh" List of dark images to combine
+ (output = "dark1") Output flat field root name
+ (\fIcombine\fR = "average") Type of combine operation
+ (\fIreject\fR = "avsigclip") Type of rejection
+ (\fIccdtype\fR = "dark") CCD image type to combine
+ (process = no) Process images before combining?
+ (delete = no) Delete input images after combining?
+ (clobber = no) Clobber existing output image?
+ (\fIscale\fR = "exposure") Image scaling
+ (statsec = "") Image section for computing statistics
+ (nlow = 1) minmax: Number of low pixels to reject
+ (nhigh = 1) minmax: Number of high pixels to reject
+ (nkeep = 1) Minimum to keep (pos) or maximum to reject
+ (mclip = yes) Use median in sigma clipping algorithms?
+ (lsigma = 3.) Lower sigma clipping factor
+ (hsigma = 3.) Upper sigma clipping factor
+ (rdnoise = "0.") ccdclip: CCD readout noise (electrons)
+ (gain = "1.") ccdclip: CCD gain (electrons/DN)
+ (snoise = "0.") ccdclip: Sensitivity noise (fraction)
+ (pclip = -0.5) pclip: Percentile clipping parameter
+ (blank = 0.) Value if there are no pixels
+ (mode = "ql")
+
+ \fIflatcombine for dome flats\fR
+
+ input = "flat.*imh" List of flat field images to combine
+ (output = "flat1") Output flat field root name
+ (combine = "median") Type of combine operation
+ (reject = "ccdclip") Type of rejection
+ (ccdtype = "flat") CCD image type to combine
+ (process = no) Process images before combining?
+ (subsets = yes) Combine images by subset parameter?
+ (delete = no) Delete input images after combining?
+ (clobber = no) Clobber existing output image?
+ (scale = "median") Image scaling
+ (statsec = "[m:n,p:q]") Image section for computing statistics
+ (nlow = 1) minmax: Number of low pixels to reject
+ (nhigh = 1) minmax: Number of high pixels to reject
+ (nkeep = 1) Minimum to keep (pos) or maximum to reject
+ (mclip = yes) Use median in sigma clipping algorithms?
+ (lsigma = 3.) Lower sigma clipping factor
+ (hsigma = 3.) Upper sigma clipping factor
+ (rdnoise = "5") ccdclip: CCD readout noise (electrons)
+ (gain = "2.5") ccdclip: CCD gain (electrons/DN)
+ (snoise = "0.") ccdclip: Sensitivity noise (fraction)
+ (pclip = -0.5) pclip: Percentile clipping parameter
+ (blank = 1.) Value if there are no pixels
+ (mode = "ql")
+
+ \fIflatcombine for sky flats\fR
+
+ input = "sky.*imh" List of flat field images to combine
+ (output = "sky1") Output flat field root name
+ (combine = "median") Type of combine operation
+ (reject = "ccdclip") Type of rejection
+ (ccdtype = "other") CCD image type to combine
+ (process = no) Process images before combining?
+ (subsets = yes) Combine images by subset parameter?
+ (delete = no) Delete input images after combining?
+ (clobber = no) Clobber existing output image?
+ (scale = "median") Image scaling
+ (statsec = "[m:n,p:q]") Image section for computing statistics
+ (nlow = 1) minmax: Number of low pixels to reject
+ (nhigh = 1) minmax: Number of high pixels to reject
+ (nkeep = 1) Minimum to keep (pos) or maximum to reject
+ (mclip = yes) Use median in sigma clipping algorithms?
+ (lsigma = 3.) Lower sigma clipping factor
+ (hsigma = 3.) Upper sigma clipping factor
+ (rdnoise = "5") ccdclip: CCD readout noise (electrons)
+ (gain = "2.5") ccdclip: CCD gain (electrons/DN)
+ (snoise = "0.") ccdclip: Sensitivity noise (fraction)
+ (pclip = -0.5) pclip: Percentile clipping parameter
+ (blank = 1.) Value if there are no pixels
+ (mode = "ql")
+.fi
+.le
+.bp
+.ls \fI3.5 Processing the calibration frames\fR
+
+Although all the following steps may be done only in one step, our
+approach is to do them separately to allow you to start at any point in
+this section in case you have already started reducing the images on
+the mountain.
+
+You must start by overscan subtracting and trimming 'zero1'. Edit the
+parameters for the 'ccdproc' task according to the list given below.
+There is a series of parameters that are set to 'yes' and 'no'. You must set
+only 'overscan' and 'trim' to 'yes' and the rest to 'no'. Also
+'ccdtype' must be
+set to 'zero'. Be sure to properly specify the parameters
+'biassec' and 'trimsec' which you determined while reading section 3.3.2.
+The range of columns comes first separated by a ':' and the range of lines
+is again separated by a ':', i.e., [29:425,21:402].
+
+\fIDo not change these parameters until having
+processed all your images\fR.
+
+.nf
+ cc> epar ccdproc (check the list given below)
+ cc> ccdproc zero1
+.fi
+
+If the parameter 'interactive' was set to 'yes' you will be required to
+fit interactively the overscan region with a certain function. Once
+presented by the task with the plot of the overscan region (see figure 3)
+you may change the fitting function, for example, with ':function chebyshev'
+and its order with
+':order 4'. To try a new fit type 'f'. We suggest a spline3 of order 2.
+You may also select the sample to be fit using the 's' command twice.
+If you are happy with
+the fit type 'q' to quit. The task will then process 'zero1' accordingly.
+
+Continue by overscan subtracting, trimming and bias subtracting 'dark1'.
+In this case you have to change in 'ccdproc' the 'ccdtype' parameter
+to 'dark' and the
+'zerocor' parameter to 'yes'.
+
+.nf
+ cc> epar ccdproc (check the list given below)
+ cc> ccdproc dark1
+.fi
+
+The dark image must be examined before proceeding. \fIFor instance, if the
+dark level is low enough (<10 counts/hour/pixel)
+compared to the flats, you will
+probably disregard dark subtracting your images, to avoid
+introducing noise in your data.\fR
+However, if you notice some structure in the dark image, it would be
+worth trying to dark correct the data. In the following examples, for
+generality's sake, we consider dark subtraction as part of the overall
+processing. If this is not your case, do not forget to set the 'darkcor'
+parameter in 'ccdproc' to 'no' and leave it alone.
+
+Then process the flats. Check that the 'ccdtype' parameter is set
+to 'flat', that 'overscan', 'trim', 'zerocor' and 'darkcor' are all set
+to 'yes' and execute the task.
+
+.nf
+ cc> epar ccdproc (check the list given below)
+ cc> ccdproc flat1*imh
+.fi
+
+IRAF records all the reduction operations in the image headers. You
+may check from the headers of 'zero1', 'dark1', 'sky1' and 'flat1' that
+BT-FLAG, BI-FLAG, DK-FLAG are properly set. For instance,
+
+.nf
+ cc> imheader flat1R l+
+.fi
+
+It is also possible to check this by using the 'ccdlist' task which will check
+the header automatically and list the operations which have been performed on
+the image.
+
+.nf
+ cc> ccdlist flat1R
+
+.fi
+You should get the following,
+
+.nf
+ flat1R[496,501][real][flat][R][OTZ]:dflat R
+
+.fi
+'ccdlist' should tell you the image name (flat1R), the image size [496,501]
+left after trimming, the pixel type [real] of the image (the processed
+images should normally have pixels in real format, as opposed to
+the raw images which generally have pixels in 'short' format),
+the image type [flat], the filter used in the observation
+[R], the level of processing of the image [OTZ], and the image title (dflat R).
+
+At this level you should have the flats processed up through [OTZ] which
+means that the image has been [O]verscan subtracted, [T]rimmed, and
+[Z]ero subtracted. Additional codes for other operations in 'ccdproc'
+are [F]lat correction, [B]ad pixel correction, [I]illumination correction.
+
+.nf
+ \fIccdproc for zero1\fR
+
+ images = "zero1" List of CCD images to correct
+ (\fIccdtype\fR = "zero") CCD image type to correct
+ (max_cache = 0) Maximum image caching memory (in Mbytes)
+ (noproc = no) List processing steps only?
+ (fixpix = no) Fix bad CCD lines and columns?
+ (\fIoverscan\fR = yes) Apply overscan strip correction?
+ (\fItrim\fR = yes) Trim the image?
+ (\fIzerocor\fR = no) Apply zero level correction?
+ (\fIdarkcor\fR = no) Apply dark count correction?
+ (\fIflatcor\fR = no) Apply flat field correction?
+ (illumcor = no) Apply iillumination correction?
+ (fringecor = no) Apply fringe correction?
+ (readcor = no) Convert zero level image to readout cor?
+ (scancor = no) Convert flat field image to scan correction?
+ (readaxis = "line") Read out axis (column|line)
+ (fixfile = "") File describing the bad lines and columns
+ (\fIbiassec\fR = "[m:n,*]") Overscan strip image section
+ (\fItrimsec\fR = "[r:s,t:u]") Trim data section
+ (\fIzero\fR = "zero1") Zero level calibration image
+ (\fIdark\fR = "dark1") Dark count calibration image
+ (\fIflat\fR = "") Flat field images
+ (illum = "") Iillumination correction images
+ (fringe = "") Fringe correction images
+ (minreplace = 1.) Minimum flat field value
+ (scantype = "shortscan") Scan type (shortscan|longscan)
+ (nscan = 1) Number of short scan lines\n
+ (interactive = yes) Fit overscan interactively?
+ (function = "spline3") Fitting function
+ (order = 2) Number of polynomial terms or spline pieces
+ (sample = "*") Sample points to fit
+ (naverage = 1) Number of sample points to combine
+ (niterate = 1) Number of rejection iterations
+ (low_reject = 3.) Low sigma rejection factor
+ (high_reject = 3.) High sigma rejection factor
+ (grow = 0.) Rejection growing radius
+ (mode = "ql")
+
+ \fIccdproc for dark1\fR
+
+ images = "dark1" List of CCD images to correct
+ (\fIccdtype\fR = "dark") CCD image type to correct
+ (max_cache = 0) Maximum image caching memory (in Mbytes)
+ (noproc = no) List processing steps only?
+ (fixpix = no) Fix bad CCD lines and columns?
+ (\fIoverscan\fR = yes) Apply overscan strip correction?
+ (\fItrim\fR = yes) Trim the image?
+ (\fIzerocor\fR = yes) Apply zero level correction?
+ (\fIdarkcor\fR = no) Apply dark count correction?
+ (\fIflatcor\fR = no) Apply flat field correction?
+ (illumcor = no) Apply iillumination correction?
+ (fringecor = no) Apply fringe correction?
+ (readcor = no) Convert zero level image to readout corr?
+ (scancor = no) Convert flat field image to scan correction?
+ (readaxis = "line") Read out axis (column|line)
+ (fixfile = "") File describing the bad lines and columns
+ (\fIbiassec\fR = "[m:n,*]") Overscan strip image section
+ (\fItrimsec\fR = "[r:s,t:u]") Trim data section
+ (\fIzero\fR = "zero1") Zero level calibration image
+ (\fIdark\fR = "dark1") Dark count calibration image
+ (\fIflat\fR = "") Flat field images
+ (illum = "") Iillumination correction images
+ (fringe = "") Fringe correction images
+ (minreplace = 1.) Minimum flat field value
+ (scantype = "shortscan") Scan type (shortscan|longscan)
+ (nscan = 1) Number of short scan lines\n
+ (interactive = yes) Fit overscan interactively?
+ (function = "spline3") Fitting function
+ (order = 2) Number of polynomial terms or spline pieces
+ (sample = "*") Sample points to fit
+ (naverage = 1) Number of sample points to combine
+ (niterate = 1) Number of rejection iterations
+ (low_reject = 3.) Low sigma rejection factor
+ (high_reject = 3.) High sigma rejection factor
+ (grow = 0.) Rejection growing radius
+ (mode = "ql")
+
+ \fIccdproc for flat1\fR
+
+ images = "flat1*imh" List of CCD images to correct
+ (\fIccdtype\fR = "flat") CCD image type to correct
+ (max_cache = 0) Maximum image caching memory (in Mbytes)
+ (noproc = no) List processing steps only?
+ (fixpix = no) Fix bad CCD lines and columns?
+ (\fIoverscan\fR = yes) Apply overscan strip correction?
+ (\fItrim\fR = yes) Trim the image?
+ (\fIzerocor\fR = yes) Apply zero level correction?
+ (\fIdarkcor\fR = yes) Apply dark count correction?
+ (\fIflatcor\fR = no) Apply flat field correction?
+ (illumcor = no) Apply iillumination correction?
+ (fringecor = no) Apply fringe correction?
+ (readcor = no) Convert zero level image to readout corr?
+ (scancor = no) Convert flat field image to scan correction?
+ (readaxis = "line") Read out axis (column|line)
+ (fixfile = "") File describing the bad lines and columns
+ (\fIbiassec\fR = "[m:n,*]") Overscan strip image section
+ (\fItrimsec\fR = "[r:s,t:u]") Trim data section
+ (\fIzero\fR = "zero1") Zero level calibration image
+ (\fIdark\fR = "dark1") Dark count calibration image
+ (\fIflat\fR = "") Flat field images
+ (illum = "") Iillumination correction images
+ (fringe = "") Fringe correction images
+ (minreplace = 1.) Minimum flat field value
+ (scantype = "shortscan") Scan type (shortscan|longscan)
+ (nscan = 1) Number of short scan lines\n
+ (interactive = yes) Fit overscan interactively?
+ (function = "spline3") Fitting function
+ (order = 2) Number of polynomial terms or spline pieces
+ (sample = "*") Sample points to fit
+ (naverage = 1) Number of sample points to combine
+ (niterate = 1) Number of rejection iterations
+ (low_reject = 3.) Low sigma rejection factor
+ (high_reject = 3.) High sigma rejection factor
+ (grow = 0.) Rejection growing radius
+ (mode = "ql")
+.fi
+.le
+.bp
+.ls \fI3.6 Preparing a Final Flat Field\fR
+
+Next we want to check the iillumination of the flat by applying it to the sky
+flat. Load the 'imred' and 'ccdred' packages if they are
+not already loaded.
+There is no tried and true method for testing the iillumination of
+the sky flats except for applying them on a long exposure taken in the same
+filter and implotting it or doing image statistics.
+
+We must use 'ccdproc' to overscan subtract, trim, bias subtract, dark subtract
+(if needed), and flat field the sky images. Again, we assume here
+that the dark is
+necessary for the reductions. Be sure that the images you are using for
+the flat field division have the proper filter identification.
+First edit the parameters for 'ccdproc', and then run
+this task to process your skys to see if the iillumination of the dome
+flat is uniform;
+
+.nf
+ cl> noao
+ im> imred
+ im> ccdred
+ cc> epar ccdproc (check the parameter list)
+ cc> ccdproc sky1R
+.fi
+
+Now we must check the sky to see if it really is flat. This is done
+using 'implot' and plotting some lines or a group of lines,
+
+.nf
+ cc> implot sky1R
+ :l 150 200
+ :c 200 250
+ q
+.fi
+
+Ideally if the iillumination was uniform, sky1R should not show any variation.
+In plotting several lines together, you may get a small slope (see figure 4).
+If you see any
+variations, including a slope even near the edges of the image, then you must
+run the task 'mkskyflat'. Select a smoothing box size which preserves the large
+scale features while adequately suppressing the noise. The scale of the
+largest features expected shouldn't be smaller than say 1/10 to 1/12 the
+image size.
+
+.nf
+ cc> epar mkskyflat (check the parameter list)
+ cc> mkskyflat sky1R finalflat1R
+.fi
+
+The output image is the corrected flat image so call it "finalflat1R".
+We need to recopy the sky flat to process it again. Do an imcopy of the sky1R
+from the backup image after deleting the processed one.
+
+.nf
+ cc> imdel sky1R
+ cc> imcopy Bsky1R sky1R
+ cc> epar ccdproc (change the parameter 'flat' from
+ flat1R to finalflat1R)
+ cc> ccdproc sky1R
+.fi
+
+Again, check to see if the sky is really flat. If it is flat
+(see figure 5), then you are
+done and must process the flats for your other filters. If it is not flat,
+go back to the beginning and ask for help. It may be that you need to play
+with the smoothing parameters. Repeat these steps until you are satisfied.
+Now you can process your images.
+
+.nf
+
+ \fIccdproc for sky flats\fR
+
+ images = "sky1*imh" List of CCD images to correct
+ (\fIccdtype\fR = "other") CCD image type to correct
+ (max_cache = 0) Maximum image caching memory (in Mbytes)
+ (noproc = no) List processing steps only?
+ (fixpix = no) Fix bad CCD lines and columns?
+ (\fIoverscan\fR = yes) Apply overscan strip correction?
+ (\fItrim\fR = yes) Trim the image?
+ (\fIzerocor\fR = yes) Apply zero level correction?
+ (\fIdarkcor\fR = yes) Apply dark count correction?
+ (\fIflatcor\fR = yes) Apply flat field correction?
+ (illumcor = no) Apply iillumination correction?
+ (fringecor = no) Apply fringe correction?
+ (readcor = no) Convert zero level image to readout corr?
+ (scancor = no) Convert flat field image to scan correction?
+ (readaxis = "line") Read out axis (column|line)
+ (fixfile = "") File describing the bad lines and columns
+ (\fIbiassec\fR = "[m:n,*]") Overscan strip image section
+ (\fItrimsec\fR = "[r:s,t:u]") Trim data section
+ (\fIzero\fR = "zero1") Zero level calibration image
+ (\fIdark\fR = "dark1") Dark count calibration image
+ (\fIflat\fR = "flat1*imh") Flat field images
+ (illum = "") Iillumination correction images
+ (fringe = "") Fringe correction images
+ (minreplace = 1.) Minimum flat field value
+ (scantype = "shortscan") Scan type (shortscan|longscan)
+ (nscan = 1) Number of short scan lines\n
+ (interactive = yes) Fit overscan interactively?
+ (function = "spline3") Fitting function
+ (order = 2) Number of polynomial terms or spline pieces
+ (sample = "*") Sample points to fit
+ (naverage = 1) Number of sample points to combine
+ (niterate = 1) Number of rejection iterations
+ (low_reject = 3.) Low sigma rejection factor
+ (high_reject = 3.) High sigma rejection factor
+ (grow = 0.) Rejection growing radius
+ (mode = "ql")
+.fi
+.bp
+.nf
+ \fImkskyflat\fR
+
+ input = "sky1R" Input CCD images
+ output = "finalflat1R" Output images (same as input if none)
+ (ccdtype = "") CCD image type to select
+ (\fIxboxmin\fR = 0.1) Minimum smoothing box size in x at edges
+ (\fIxboxmax\fR = 0.1) Maximum smoothing box size in x
+ (\fIyboxmin\fR = 0.1) Minimum smoothing box size in y at edges
+ (\fIyboxmax\fR = 0.1) Maximum smoothing box size in y
+ (clip = yes) Clip input pixels?
+ (lowsigma = 2.5) Low clipping sigma
+ (highsigma = 2.5) High clipping sigma
+ (ccdproc = "") CCD processing parameters
+ (mode = "ql")
+.fi
+.le
+.bp
+.ls \fI3.7 Processing the Images\fR
+
+This can be setup to be done all at once. The final flat has been made so now
+we divide it into your objects.
+If the calibration frames themselves
+have not been processed it will do this as well. The program takes into
+account the differing filters. Be sure that you have deleted all the individual
+calibration frames that were combined. Edit the parameters for 'ccdproc' and run
+it. For tasks that take a long time, it is a good idea to set them going as a
+background job and send the output to a file which you can watch to keep track
+of the progress. You may wish to make a list of the objects to be processed
+to avoid reprocessing your sky flats.
+
+.nf
+ cc> epar ccdproc (check the parameter list)
+ cc> ccdproc obj*.imh
+.fi
+
+To check the progress of the task, just type
+
+.nf
+ cc> tail ccdlog
+.fi
+
+This will print out the last lines of the file named 'ccdlog'
+which is the latest
+operation done by the task 'ccdproc'.
+Once this is done, check your images to see
+that they have been properly flat fielded. If you are satisfied, then you may
+now check your images for bad pixel regions, the structure of which may not have
+been processed out of your images.
+
+We suggest also to do a 'ccdlist' on the objects in order to
+check whether the frames have been duly processed, i.e.,
+
+.nf
+ cc> ccdlist obj*.imh
+.fi
+
+You should get a listing of your images in the format that follows,
+
+.nf
+
+ obj1010.imh[496,501][real][object][R][OTZF]:rubin 152 R
+ obj1011.imh[496,501][real][object][I][OTZF]:rubin 152 I
+ obj1012.imh[496,501][real][object][B][OTZF]:rubin 149 B
+ obj1013.imh[496,501][real][object][V][OTZF]:rubin 149 V
+ obj1014.imh[496,501][real][object][R][OTZF]:rubin 149 R
+ obj1015.imh[496,501][real][object][I][OTZF]:rubin 149 I
+ obj1016.imh[496,501][real][object][B][OTZF]:rubin 149 B
+ obj1017.imh[496,501][real][object][V][OTZF]:rubin 149 V
+ obj1018.imh[496,501][real][object][R][OTZF]:rubin 149 R
+ obj1019.imh[496,501][real][object][I][OTZF]:rubin 149 I
+.fi
+
+where the [OTZF] code reveals the degree of processing of the images.
+
+.nf
+ \fIccdproc for objects\fR
+
+ images = "obj*imh)" List of CCD images to correct
+ (\fIccdtype\fR = "object") CCD image type to correct
+ (max_cache = 0) Maximum image caching memory (in Mbytes)
+ (noproc = no) List processing steps only?
+ (fixpix = no) Fix bad CCD lines and columns?
+ (\fIoverscan\fR = yes) Apply overscan strip correction?
+ (\fItrim\fR = yes) Trim the image?
+ (\fIzerocor\fR = yes) Apply zero level correction?
+ (\fIdarkcor\fR = yes) Apply dark count correction?
+ (\fIflatcor\fR = yes) Apply flat field correction?
+ (illumcor = no) Apply iillumination correction?
+ (fringecor = no) Apply fringe correction?
+ (readcor = no) Convert zero level image to readout corr?
+ (scancor = no) Convert flat field image to scan correction?
+ (readaxis = "line") Read out axis (column|line)
+ (fixfile = "") File describing the bad lines and columns
+ (\fIbiassec\fR = "[m:n,*]") Overscan strip image section
+ (\fItrimsec\fR = "[r:s,t:u]") Trim data section
+ (\fIzero\fR = "zero1") Zero level calibration image
+ (\fIdark\fR = "dark1") Dark count calibration image
+ (\fIflat\fR = "finalflat1*imh") Flat field images
+ (illum = "") Iillumination correction images
+ (fringe = "") Fringe correction images
+ (minreplace = 1.) Minimum flat field value
+ (scantype = "shortscan") Scan type (shortscan|longscan)
+ (nscan = 1) Number of short scan lines\n
+ (interactive = yes) Fit overscan interactively?
+ (function = "spline3") Fitting function
+ (order = 2) Number of polynomial terms or spline pieces
+ (sample = "*") Sample points to fit
+ (naverage = 1) Number of sample points to combine
+ (niterate = 1) Number of rejection iterations
+ (low_reject = 3.) Low sigma rejection factor
+ (high_reject = 3.) High sigma rejection factor
+ (grow = 0.) Rejection growing radius
+ (mode = "ql")
+
+.fi
+
+.le
+.bp
+.ls \fI3.8 Creating the Bad Pixel File\fR
+
+Now it is time to check your images to see if structure remains in the bad
+pixel regions. If you were careful to observe your objects far away from any
+obvious bad regions then you may only need to 'fix' pixels for cosmetic reasons.
+We suggest you to examine these files using the display window,
+imtool (this can only be done at one of the SUN consoles), and then plotting
+them using 'implot'. Start by loading the 'noao', 'images', 'tv', 'imred',
+and 'ccdred' packages. Display
+a processed image and plot it using 'implot',
+
+.nf
+ cl> noao
+ no> images
+ im> tv
+ tv> imred
+ im> ccdred
+ cc> display obj002 1
+ cc> implot obj002
+.fi
+
+Do not exit from implot, but move the cursor to the imtool window and press
+'F6'. The cursor coordinates are now visible at the bottom of the screen.
+Find the position of a bad pixel using this, return to the graph and
+plot it using 'implot' with the ':l #'(line) and ':c #'(column) commands.
+You can define them more precisely using 'implot' by overplotting lines and
+columns around the center of the bad regions. Do this by typing 'o' followed
+by ':c #' and ':l #'. Once you have these regions written down, check some of
+your images to see if the bad pixels are a problem, ie >1% in signal. If it is
+a problem then create a file called 'badpix' with the listing of
+the pixels you wish to fix;
+
+.nf
+ cc> edit badpix (according to the following format)
+.fi
+
+The following example is to illustrate the format of a bad pixel file.
+
+.nf
+ 84 87 1 450
+ 87 90 105 109
+ 87 89 110 111
+ 124 126 112 116
+ 206 206 80 80
+.fi
+
+Each line stands for a rectangular region of the image to be fixed. The regions
+are specified by four numbers giving the starting and ending columns followed
+by the starting and ending lines. The starting and ending points may be the
+same to specify a single column, line or pixel. Note that each region is
+"fixed" by interpolating across its shortest dimension and that regions are
+processed in the order that they appear in the bad pixel list. For bad regions
+of complex shape, some care may be required in specifying the regions in order
+to achieve an optimal result. \fIIt is strongly recommended that you test your
+bad pixel file by using it to correct a copy of one of your images before going
+into production\fR. This bad pixel file will be specified in the task 'ccdproc'
+in the parameter 'fixfile'. So now edit and run the task:
+
+.nf
+ cc> epar ccdproc
+ cc> ccdproc obj*.imh
+.fi
+
+Remember that 'ccdproc' already knows that the images
+have been processed so those
+operations will not be performed again. Now you have final images that are ready
+to be used. If you plan to do photometry in IRAF see section VI of this manual.
+
+.nf
+ \fIccdproc\fR
+
+ images = "obj*imh)" List of CCD images to correct
+ (\fIccdtype\fR = "object") CCD image type to correct
+ (max_cache = 0) Maximum image caching memory (in Mbytes)
+ (noproc = no) List processing steps only?
+ (\fIfixpix\fR = yes) Fix bad CCD lines and columns?
+ (\fIoverscan\fR = yes) Apply overscan strip correction?
+ (\fItrim\fR = yes) Trim the image?
+ (\fIzerocor\fR = yes) Apply zero level correction?
+ (\fIdarkcor\fR = yes) Apply dark count correction?
+ (\fIflatcor\fR = yes) Apply flat field correction?
+ (illumcor = no) Apply iillumination correction?
+ (fringecor = no) Apply fringe correction?
+ (readcor = no) Convert zero level image to readout corr?
+ (scancor = no) Convert flat field image to scan correction?
+ (readaxis = "line") Read out axis (column|line)
+ (\fIfixfile\fR = "badpix") File describing the bad lines and columns
+ (\fIbiassec\fR = "[m:n,*]") Overscan strip image section
+ (\fItrimsec\fR = "[r:s,t:u]") Trim data section
+ (\fIzero\fR = "zero1") Zero level calibration image
+ (\fIdark\fR = "dark1") Dark count calibration image
+ (\fIflat\fR = "finalflat1*imh") Flat field images
+ (illum = "") Iillumination correction images
+ (fringe = "") Fringe correction images
+ (minreplace = 1.) Minimum flat field value
+ (scantype = "shortscan") Scan type (shortscan|longscan)
+ (nscan = 1) Number of short scan lines\n
+ (interactive = yes) Fit overscan interactively?
+ (function = "spline3") Fitting function
+ (order = 2) Number of polynomial terms or spline pieces
+ (sample = "*") Sample points to fit
+ (naverage = 1) Number of sample points to combine
+ (niterate = 1) Number of rejection iterations
+ (low_reject = 3.) Low sigma rejection factor
+ (high_reject = 3.) High sigma rejection factor
+ (grow = 0.) Rejection growing radius
+ (mode = "ql")
+
+.fi
+.le
+.bp
+.ls \fI3.9 Writing the Data to Tape\fR
+
+Allocate the device, for the SUNs it is "mta". Then mount your tape, don't
+forget to put in a write ring. If you wish to use the exabyte drive, use "mtx"
+for the device name. Load the package 'dataio' and do an epar on 'wfits'.
+
+.nf
+ cl> dataio
+ da> epar wfits
+ da> wfits *.imh mta.6250 new+
+.fi
+
+The parameter newtape should be "yes"
+if you are starting on a new tape. Otherwise you will not want to overwrite
+data which has already been placed on a tape, so use "no".
+
+After writing all the desired files to tape, deallocate the drive and retrieve
+your tape.
+
+.nf
+ da> dealloc mta
+.fi
+.le
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/quadproc.hlp b/noao/imred/quadred/src/quad/doc/quadproc.hlp
new file mode 100644
index 00000000..8d445097
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/quadproc.hlp
@@ -0,0 +1,672 @@
+.help quadproc Sept93 arcon.quad
+.ih
+NAME
+quadproc -- Process multi-readout CCD images
+.ih
+USAGE
+quadproc images
+.ih
+PARAMETERS
+.ls images
+List of input CCD images to process. The list may include processed
+images and calibration images.
+.le
+.ls ccdtype = ""
+CCD image type to select from the input image list. If no type is given
+then all input images will be selected. The recognized types are described
+in \fBccdtypes\fR.
+.le
+.ls max_cache = 0
+Maximum image caching memory (in Mbytes). If there is sufficient memory
+the calibration images, such as zero level, dark count, and flat fields,
+will be cached in memory when processing many input images. This
+reduces the disk I/O and makes the task run a little faster. If the
+value is zero image caching is not used.
+.le
+.ls noproc = no
+List processing steps only?
+.le
+
+.ce
+PROCESSING SWITCHES
+.ls fixpix = yes
+Fix bad CCD lines and columns by linear interpolation from neighboring
+lines and columns? If yes then a bad pixel file must be specified.
+.le
+.ls overscan = yes
+Apply overscan or prescan bias correction? If yes then the overscan
+image section and the readout axis must be specified.
+.le
+.ls trim = yes
+Trim the image of the overscan region and bad edge lines and columns?
+If yes then the trim section must be specified.
+.le
+.ls zerocor = yes
+Apply zero level correction? If yes a zero level image must be specified.
+.le
+.ls darkcor = yes
+Apply dark count correction? If yes a dark count image must be specified.
+.le
+.ls flatcor = yes
+Apply flat field correction? If yes flat field images must be specified.
+.le
+.ls illumcor = no
+Apply iillumination correction? If yes iillumination images must be specified.
+.le
+.ls fringecor = no
+Apply fringe correction? If yes fringe images must be specified.
+.le
+.ls readcor = no
+Convert zero level images to readout correction images? If yes then
+zero level images are averaged across the readout axis to form one
+dimensional zero level readout correction images.
+.le
+.ls scancor = no
+Convert flat field images to scan mode flat field images? If yes then the
+form of scan mode correction is specified by the parameter \fIscantype\fR.
+.le
+
+.ce
+PROCESSING PARAMETERS
+.ls readaxis = "line"
+Read out axis specified as "line" or "column".
+.le
+.ls fixfile
+File describing the bad lines and columns. If "image" is specified then
+the file is specified in the image header or instrument translation file.
+See Section 2. of Description for further information on bad pixel files.
+.le
+.ls biassec
+Overscan bias strip image section. If "image" is specified then the overscan
+bias section is specified in the image header or instrument translation file.
+See Section 3. of Description for further information on setting this parmeter.
+.le
+.ls trimsec
+image section for trimming. If "image" is specified then the trim
+image section is specified in the image header or instrument translation file.
+See Section 4. of Description for further information on setting this parmeter.
+.le
+.ls zero = ""
+Zero level calibration image. The zero level image may be one or two
+dimensional. The CCD image type and subset are not checked for these
+images and they take precedence over any zero level calibration images
+given in the input list.
+.le
+.ls dark = ""
+Dark count calibration image. The CCD image type and subset are not checked
+for these images and they take precedence over any dark count calibration
+images given in the input list.
+.le
+.ls flat = ""
+Flat field calibration images. The flat field images may be one or
+two dimensional. The CCD image type is not checked for these
+images and they take precedence over any flat field calibration images given
+in the input list. The flat field image with the same subset as the
+input image being processed is selected.
+.le
+.ls illum = ""
+Iillumination correction images. The CCD image type is not checked for these
+images and they take precedence over any iillumination correction images given
+in the input list. The iillumination image with the same subset as the
+input image being processed is selected.
+.le
+.ls fringe = ""
+Fringe correction images. The CCD image type is not checked for these
+images and they take precedence over any fringe correction images given
+in the input list. The fringe image with the same subset as the
+input image being processed is selected.
+.le
+.ls minreplace = 1.
+When processing flat fields, pixel values below this value (after
+all other processing such as overscan, zero, and dark corrections) are
+replaced by this value. This allows flat fields processed by \fBquadproc\fR
+to be certain to avoid divide by zero problems when applied to object
+images.
+.le
+.ls scantype = "shortscan"
+Type of scan format used in creating the CCD images. The modes are:
+.ls "shortscan"
+The CCD is scanned over a number of lines and then read out as a regular
+two dimensional image. In this mode unscanned flat fields are numerically
+scanned to form scanned flat fields comparable to the observations. If
+the flat field calibration images are taken in scanned mode then
+\fIscancor\fR should be no and the processing performed in the same manner
+as in unscanned mode.
+.le
+.ls "longscan"
+In this mode the CCD is clocked and read out continuously to form a long
+strip. Flat fields are averaged across the readout axis to
+form a one dimensional flat field readout correction image. This assumes
+that all recorded image lines are clocked over the entire active area of the
+CCD.
+.le
+.le
+.ls nscan
+Number of scan readout lines used in short scan mode. This parameter is used
+when the scan type is "shortscan".
+.le
+
+.ce
+OVERSCAN FITTING PARAMETERS
+.ls interactive = no
+Fit the overscan vector interactively? If yes the overscan vector is fit
+interactively using the \fBicfit\fR package. If no then the fitting parameters
+given below are used.
+.le
+.ls function = "legendre"
+Overscan fitting function. The function types are "legendre" polynomial,
+"chebyshev" polynomial, "spline1" linear spline, and "spline3" cubic
+spline.
+.le
+.ls order = 1
+Number of polynomial terms or spline pieces in the overscan fit.
+.le
+.ls sample = "*"
+Sample points to use in the overscan fit. The string "*" specified all
+points otherwise an \fBicfit\fR range string is used.
+.le
+.ls naverage = 1
+Number of points to average or median to form fitting points. Positive
+numbers specify averages and negative numbers specify medians.
+.le
+.ls niterate = 1
+Number of rejection iterations to remove deviant points from the overscan fit.
+If 0 then no points are rejected.
+.le
+.ls low_reject = 3., high_reject = 3.
+Low and high sigma rejection factors for rejecting deviant points from the
+overscan fit.
+.le
+.ls grow = 0.
+One dimensional growing radius for rejection of neighbors to deviant points.
+.le
+.ih
+DESCRIPTION
+\fBQuadproc\fR processes CCD images to remove all "instrumental signatures" from
+the data. The operations performed are:
+.ls
+.nf
+o correct detector defects (bad lines and columns)
+o determine readout bias level using overscan and subtract it
+o trim off the overscan regions and unwanted border pixels
+o subtract zero level bias
+o subtract dark counts
+o correct for pixel-to-pixel sensitivity variations
+o correct for non-uniform iillumination
+o correct for fringing
+.fi
+.le
+.sp 1
+\fBQuadproc\fR is a cl script based on the task \fBccdproc\fR in the
+\fBccdred\fR package. It is specifically designed to deal with Arcon data
+obtained in multi-readout mode (see \fBquadformat\fR). A feature of such
+images is that each readout typically has a slightly different, DC bias
+level, gain, and readout noise. As a result both zero frames and uniformly
+illuminated exposures show a characteristic chequer board pattern, the
+sections of the image read through each amplifier having different levels.
+In addition, there will be a separate overscan strip, used to monitor the zero
+level, for each readout. The location of these overscan strips in the raw
+frame depends on which amplifiers are used. \fBQuadproc\fR splits each
+multi-readout image into subimages, one for each amplifier, and also calculates
+the biassec and trimsec appropriately for each. It then calls \fBccdproc\fR to
+perform the first three operations listed above. The sub-images are then glued
+back together. Finaly, \fBccdproc\fR is called a second time to perform all the
+remaining reduction steps.
+
+\fBQuadproc\fR MUST be used for the reduction of multi-readout data up to and
+including the trimming step, and it is convenient to use it for the entire
+reduction process. However, once ALL images have been trimmed it is possible
+to finish the reductions using \fBccdproc\fR if the \fBquad\fR package is not
+available at your home institution. \fBQuadproc\fR recognizes mono-readout
+images and processes them directly using \fBccdproc\fR. If your images are a
+mixture of multi- and mono- readout use \fBquadproc\fR; if you only have
+mono-readout data use \fBccdproc\fR.
+
+\fBQuadproc\fR is identical to \fBccdproc\fR in the way it is used, and has
+exactly the same parameters; as far as possible it also behaves in the same way.
+To run it, all one has to do is set the parameters and then begin processing
+the images. The task takes care of most of the record keeping and
+automatically does the prerequisite processing of calibration images. For
+ease of reference, the following sections provide a simple outline of how to
+use the task, together with a description of the operations performed. They
+are taken almost verbatim from the help page for \fBccdproc\fR. If you are
+already familiar with that task you should read sections 2., 3. and 4. below,
+which include information on the preparation of the badpixel file, and on how
+to specify \fBbiassec\fR and \fBtrimsec\fR parameters. See section 12. for a
+description of the differences between the two tasks. For a user's guide and
+cookbook for the \fBquad\fR package see \fBguide\fR.
+.sh
+1. Parameters
+There are many parameters but they may be easily reviewed and modified using
+the task \fBeparam\fR.
+The input CCD images to be processed are given as an image list.
+Previously processed images are ignored and calibration images are
+recognized, provided the CCD image types are in the image header (see
+\fBinstruments\fR and \fBccdtypes\fR). \fBQuadproc\fR separates multi- and
+mono-readout images in the input list and handles them accordingly.
+Therefore it is permissible to use simple image templates such as "*.imh".
+The \fIccdtype\fR parameter may be used to select only certain types of CCD
+images to process (see \fBccdtypes\fR).
+
+The processing operations are selected by boolean (yes/no) parameters.
+Because calibration images are recognized and processed appropriately,
+the processing operations for object images should be set. Any combination of
+operations may be specified. Two of the operations, \fBreadcor\fR and \fBscancor\fR, are only applicable to zero level and flat field images respectively. These
+are used for certain types of CCDs and modes of operation.
+
+The processing steps selected have related parameters which must be
+set. These are things like image sections defining the overscan and
+trim regions and calibration images. There are a number of parameters
+used for fitting the overscan or prescan bias section. These are
+parameters used by the standard IRAF curve fitting package \fBicfit\fR.
+The parameters are described in more detail in the following sections.
+
+In addition to the task parameters there are package parameters
+which affect \fBquadproc\fR. These include the instrument and subset
+files, the text and plot log files, the output pixel datatype,
+the verbose parameter for logging to the terminal, and the backup
+prefix. These are described in \fBquad\fR.
+
+Calibration images are specified by task parameters and/or in the
+input image list. If more than one calibration image is specified
+then the first one encountered is used. Calibration images specified by
+task parameters take precedence over calibration images in the input list.
+These images also need not have a CCD image type parameter since the task
+parameter identifies the type of calibration image. This method is
+best if there is only one calibration image for all images
+to be processed, almost always true for zero level and dark
+count images. If no calibration image is specified by task parameter
+then calibration images in the input image list are identified and
+used. This requires that the images have CCD image types recognized
+by the package. This method is useful if one may simply say "*.imh"
+as the image list to process all images or if the images are broken
+up into groups, in "@" files for example, each with their own calibration
+frames.
+.sh
+2. Fixpix
+Regions of bad lines and columns may be replaced by linear
+interpolation from neighboring lines and columns when the parameter
+\fIfixpix\fR is set. The bad regions are specified in a bad pixel
+file. The file consists of lines with four fields, the starting and
+ending columns and the starting and ending lines. Any number of
+regions may be specified. Currently, the coordinates given for the bad regions
+must be those that would be applicable if the CCD was used in SINGLE READOUT
+MODE, even if multi-readout images are being reduced. A task is being written
+to aid in the preparation of an appropriate bad-pixel file given measurements
+made on a raw multi-readout image.
+
+Comment lines beginning with the character '#' may be included. If a comment
+line preceding the bad regions contains the word "untrimmed" then the
+coordinate system refers to the original format of the images; i.e. before
+trimming. If an image has been trimmed previously then the trim region
+specified in the image header is used to convert the coordinates in the bad
+pixel file to those of the trimmed image. If the file does not contain the
+word "untrimmed" then the coordinate system must match that of the image
+being corrected; i.e. untrimmed coordinates if the image has not been
+trimmed and trimmed coordinates if the image has been trimmed.
+Standard bad pixel files should always be specified in terms of the original
+format.
+
+The bad pixel file may be specified explicitly with the parameter \fIfixfile\fR
+or indirectly if the parameter has the value "image". In the latter case
+the instrument file must contain the name of the file.
+.sh
+3. Overscan
+The portion of the image used to determine the readout bias level is specified
+with the parameter \fBbiassec\fR. This may be an explicit image section, or it
+may be set to the special value "image". In the latter case the value given in
+the image header is used. The image header value uses the entire overscan
+strip without allowing any margin between the data section and the bias
+section. Because Arcon uses a DC-coupled preamplifier the transition
+between data and overscan is very sharp indeed. Nonetheless, we recommend that
+you do skip the first few pixels of the overscan strip. To decide this issue
+for yourself, use implot to plot the average of several lines from a high
+exposure level image such as a flat field. Expand the transition region
+between data and overscan and decide how many pixels of the overscan are
+contaminated.
+
+In the case of multi-readout images, the way in which an explicit value for
+\fBbiassec\fR must be set, is unfortunately somewhat non-intuitive. Currently,
+the value recorded in the image header is that which would be appropriate had
+the detector been read out using a single amplifier; an explicit image section
+must be specified in the same way. \fBQuadproc\fR calculates the sections
+to use for the sub-images corresponding to each readout based on such "single
+readout" sections. To determine the section you must enter, use \fBimhead\fR
+or \fBhselect\fR to determine the value of \fBbiassec\fR stored in the image
+header. If this is, for instance, "[1025:1060,1:1028]" then setting
+\fBbiassec\fR = "[1029:1060,1:1028]" would leave a margin of 4 pixels
+(1029 - 1025). Note that if two readouts are used in the horizontal direction
+(quad or serial-split dual readout) the overscan strip for each amplifier is
+only half as wide as that in single readout mode. Thus in the example a 15
+pixel (36 / 2 - 3) wide strip is used for each readout.
+
+If an overscan or prescan correction is specified (\fIoverscan\fR
+parameter) then the specified image section is averaged
+along the readout axis (\fIreadaxis\fR parameter) to form a
+correction vector. A function is fit to this vector and for each readout
+line (image line or column) the function value for that line is
+subtracted from the image line. The fitting function is generally
+either a constant (polynomial of 1 term) or a high order function
+which fits the large scale shape of the overscan vector. Bad pixel
+rejection is also used to eliminate cosmic ray events. The function
+fitting may be done interactively using the standard \fBicfit\fR
+iteractive graphical curve fitting tool. Regardless of whether the fit
+is done interactively, the overscan vector and the fit may be recorded
+for later review in a metacode plot file named by the parameter
+\fIquad.plotfile\fR. The mean value of the bias function is also recorded in
+the image header and log file.
+
+The overscan subtraction performed by \fBquadproc\fR corrects the
+amplifier-to-amplifier differences in the bias level, so that no
+readout structure should be visible in processed zero images. However, you
+will still see the chequer board structure in flatfield and object exposures
+(unless the sky level is zero) because of gain difference between the
+amplifiers.
+.sh
+4. Trim
+When the parameter \fItrim\fR is set the input image will be trimmed to
+the image section given by the parameter \fItrimsec\fR. This may be an explicit
+image section, or it may be set to the special value "image". In the latter
+case the value given in the image header is used. The image header value keeps
+the entire imaging section of the CCD.
+
+In the case of multi-readout images, the way in which an explicit value for
+\fBtrimsec\fR must be set, is unfortunately somewhat non-intuitive. Currently,
+the value recorded in the image header is that which would be appropriate had
+the detector been read out using a single amplifier; an explicit image section
+must be specified in the same way. \fBQuadproc\fR calculates the sections
+to use for the sub-images corresponding to each readout based on such "single
+readout" sections. In addition one is currently restricted to trimming exactly
+the same number of columns from each side of the CCD; there is no such
+restriction on the number of lines which can be trimmed from the top and bottom
+edges of the image. To determine the section you must enter, use \fBimhead\fR
+or \fBhselect\fR to determine the value of \fBtrimsec\fR stored in the image
+header. If this is, for instance, "[1:1024,1:1028]" then setting
+\fBtrimsec\fR = "[10:1015,20:998]" would trim 9 columns from the left and right
+edges and 19 and 29 lines from the bottom and top edges respectively. If you
+need to perform an asymmetric trim in the horizontal direction this can be
+done, after processing, by using \fBimcopy\fR to copy the required portion of
+the image.
+
+The trim section used for science images should, of course, be the same as
+that used for the calibration images.
+.sh
+5. Zerocor
+After the readout bias is subtracted, as defined by the overscan or prescan
+region, there may still be a zero level bias. This level may be two
+dimensional or one dimensional (the same for every readout line). A
+zero level calibration is obtained by taking zero length exposures;
+generally many are taken and combined. To apply this zero
+level calibration the parameter \fIzerocor\fR is set. In addition if
+the zero level bias is only readout dependent then the parameter \fIreadcor\fR
+is set to reduce two dimensional zero level images to one dimensional
+images. The zero level images may be specified by the parameter \fIzero\fR
+or given in the input image list (provided the CCD image type is defined).
+
+When the zero level image is needed to correct an input image it is checked
+to see if it has been processed and, if not, it is processed automatically.
+Processing of zero level images consists of bad pixel replacement,
+overscan correction, trimming, and averaging to one dimension if the
+readout correction is specified.
+.sh
+6. Darkcor
+Dark counts are subtracted by scaling a dark count calibration image to
+the same exposure time as the input image and subtracting. The
+exposure time used is the dark time which may be different than the
+actual integration or exposure time. A dark count calibration image is
+obtained by taking a very long exposure with the shutter closed; i.e.
+an exposure with no light reaching the detector. The dark count
+correction is selected with the parameter \fIdarkcor\fR and the dark
+count calibration image is specified either with the parameter
+\fIdark\fR or as one of the input images. The dark count image is
+automatically processed as needed. Processing of dark count images
+consists of bad pixel replacement, overscan and zero level correction,
+and trimming.
+.sh
+7. Flatcor
+The relative detector pixel response is calibrated by dividing by a
+scaled flat field calibration image. A flat field image is obtained by
+exposure to a spatially uniform source of light such as an lamp or
+twilight sky. Flat field images may be corrected for the spectral
+signature in spectroscopic images (see \fBresponse\fR and
+\fBapnormalize\fR), or for iillumination effects (see \fBmkillumflat\fR
+or \fBmkskyflat\fR). For more on flat fields and iillumination corrections
+see \fBflatfields\fR. The flat field response is dependent on the
+wavelength of light so if different filters or spectroscopic wavelength
+coverage are used a flat field calibration for each one is required.
+The different flat fields are automatically selected by a subset
+parameter (see \fBsubsets\fR).
+
+Flat field calibration is selected with the parameter \fBflatcor\fR
+and the flat field images are specified with the parameter \fBflat\fR
+or as part of the input image list. The appropriate subset is automatically
+selected for each input image processed. The flat field image is
+automatically processed as needed. Processing consists of bad pixel
+replacement, overscan subtraction, zero level subtraction, dark count
+subtraction, and trimming. Also if a scan mode is used and the
+parameter \fIscancor\fR is specified then a scan mode correction is
+applied (see below). The processing also computes the mean of the
+flat field image which is used later to scale the flat field before
+division into the input image. For scan mode flat fields the ramp
+part is included in computing the mean which will affect the level
+of images processed with this flat field. Note that there is no check for
+division by zero in the interest of efficiency. If division by zero
+does occur a fatal error will occur. The flat field can be fixed by
+replacing small values using a task such as \fBimreplace\fR or
+during processing using the \fIminreplace\fR parameter. Note that the
+\fIminreplace\fR parameter only applies to flat fields processed by
+\fBquadproc\fR.
+.sh
+8. Illumcor
+CCD images processed through the flat field calibration may not be
+completely flat (in the absence of objects). In particular, a blank
+sky image may still show gradients. This residual nonflatness is called
+the iillumination pattern. It may be introduced even if the detector is
+uniformly illuminated by the sky because the flat field lamp
+iillumination may be nonuniform. The iillumination pattern is found from a
+blank sky, or even object image, by heavily smoothing and rejecting
+objects using sigma clipping. The iillumination calibration image is
+divided into the data being processed to remove the iillumination
+pattern. The iillumination pattern is a function of the subset so there
+must be an iillumination correction image for each subset to be
+processed. The tasks \fBmkillumcor\fR and \fBmkskycor\fR are used to
+create the iillumination correction images. For more on iillumination
+corrections see \fBflatfields\fR.
+
+An alternative to treating the iillumination correction as a separate
+operation is to combine the flat field and iillumination correction
+into a corrected flat field image before processing the object
+images. This will save some processing time but does require creating
+the flat field first rather than correcting the images at the same
+time or later. There are two methods, removing the large scale
+shape of the flat field and combining a blank sky image iillumination
+with the flat field. These methods are discussed further in the
+tasks which create them; \fBmkillumcor\fR and \fBmkskycor\fR.
+.sh
+9. Fringecor
+There may be a fringe pattern in the images due to the night sky lines.
+To remove this fringe pattern a blank sky image is heavily smoothed
+to produce an iillumination image which is then subtracted from the
+original sky image. The residual fringe pattern is scaled to the
+exposure time of the image to be fringe corrected and then subtracted.
+Because the intensity of the night sky lines varies with time an
+additional scaling factor may be given in the image header.
+The fringe pattern is a function of the subset so there must be
+a fringe correction image for each subset to be processed.
+The task \fBmkfringecor\fR is used to create the fringe correction images.
+.sh
+10. Readcor
+If a zero level correction is desired (\fIzerocor\fR parameter)
+and the parameter \fIreadcor\fR is yes then a single zero level
+correction vector is applied to each readout line or column. Use of a
+readout correction rather than a two dimensional zero level image
+depends on the nature of the detector or if the CCD is operated in
+longscan mode (see below). The readout correction is specified by a
+one dimensional image (\fIzero\fR parameter) and the readout axis
+(\fIreadaxis\fR parameter). If the zero level image is two dimensional
+then it is automatically processed to a one dimensional image by
+averaging across the readout axis. Note that this modifies the zero
+level calibration image.
+.sh
+11. Scancor
+CCD detectors may be operated in several modes in astronomical
+applications. The most common is as a direct imager where each pixel
+integrates one point in the sky or spectrum. However, the design of most CCD's
+allows the sky to be scanned across the CCD while shifting the
+accumulating signal at the same rate. \fBQuadproc\fR provides for two
+scanning modes called "shortscan" and "longscan". The type of scan
+mode is set with the parameter \fIscanmode\fR.
+
+In "shortscan" mode the detector is scanned over a specified number of
+lines (not necessarily at sideral rates). The lines that scroll off
+the detector during the integration are thrown away. At the end of the
+integration the detector is read out in the same way as an unscanned
+observation. The advantage of this mode is that the small scale flat
+field response is averaged in one dimension over the number of lines
+scanned. A flat field may be observed in the same way in which case
+there is no difference in the processing from unscanned imaging and the
+parameter \fIscancor\fR should be no. However, one obtains an increase
+in the statistical accuracy of the flat fields if they are not scanned
+during the observation but digitally scanned during the processing. In
+shortscan mode with \fIscancor\fR set to yes, flat field images are
+digitally scanned, if needed, by the specified number of scan lines
+(\fInscan\fR parameter).
+
+In "longscan" mode the detector is continuously read out to produce
+an arbitrarily long strip. Provided data which has not passed over
+the entire detector is thrown away, the flat field corrections will
+be one dimensional. If \fIscancor\fR is specified and the
+scan mode is "longscan" then a one dimensional flat field correction
+will be applied. If the specified flat field (\fIflat\fR parameter)
+is a two dimensional image then when the flat field image is processed
+it will be averaged across the readout axis to form a one dimensional
+correction image.
+.sh
+12. Outline of Processing Steps
+
+Because of the special handling required for multi-readout data
+\fBquadproc\fR internally reduces the data in two stages.
+
+.ls Stage one
+The operations which may be performed in the first stage are badpixel
+correction, determination and subtraction of the readout bias level, and
+trimming. This stage is only performed if one or more of the \fBfixpix\fR,
+\fBoverscan\fR or \fBtrim\fR flags is set to yes.
+
+First, all the calibration images which will be needed are identified. Any
+which were obtained in multi-readout mode AND which have not already been
+trimmed are selected for processing during this stage. This is necessary to
+ensure that the calibration images will be reduced properly. Similarly, the
+input list is searched and all multi-readout images, which have not already
+been trimmed are selected for processing.
+
+The images selected in this way are then processed sequentially. Each is split
+into separate images one for each amplifier. The values of the trimsec and
+biassec header keywords for each of these sub-images are set as required.
+\fBccdproc\fR is then run to correct bad pixels, determine and subtract the
+readout bias and trim each sub-image. Finaly, the pieces are glued back
+together again to form the complete image and the header information is
+tidied up. The resulting image is initialy created as a temporary image.
+When stage one processing is complete the original image is deleted (or
+renamed using the specified backup prefix) and the corrected image replaces
+the original image. Using a temporary image protects the data in the
+event of an abort or computer failure. Keeping the original image name
+eliminates much of the record keeping and the need to generate new
+image names.
+.le
+.ls Stage two
+\fBCcdproc\fR is now run a second time to process ALL input images. For those
+images which were NOT selected for processing during stage one all the selected
+processing steps are carried out during this second pass. For those which were
+selected in stage one only the remaining processing steps will be performed.
+Again the output processed image is initialy created as a temporary image.
+When stage two processing is complete the original image is deleted (or
+renamed using the specified backup prefix) and the corrected image replaces
+the original image.
+.le
+
+The following difference in the behaviour of \fBquadproc\fB and \fBccdproc\fR
+should be noted:
+.ls
+Because it is a script, and because it is reads and writes each image several
+times during processing \fBquadproc\fR is not very efficiant. This will be
+rectified when the present prototype code is replaced by the final version.
+.le
+.ls
+If backups are enable then \fBquadproc\fR will produce two intermediate
+images for every input image which is modified in both processing stages.
+These backup images may quickly fill up the available disk space.
+.le
+.ls
+Images may not be processed in the order they appear in the input list. Stage
+one processing is performed (if necessary) on all calibration images, then on
+all images in the input list. Any images which have already been trimmed, or
+which were taken in mono-readout mode will be skipped. Stage two processing is
+then done sequentially on all images in the input list.
+.le
+.sh
+13. Processing Arithmetic
+The \fBquadproc\fR task has two data paths, one for real image pixel datatypes
+and one for short integer pixel datatype. In addition internal arithmetic
+is based on the rules of FORTRAN. For efficiency there is
+no checking for division by zero in the flat field calibration.
+The following rules describe the processing arithmetic and data paths.
+
+.ls (1)
+If the input, output, or any calibration image is of type real the
+real data path is used. This means all image data is converted to
+real on input. If all the images are of type short all input data
+is kept as short integers. Thus, if all the images are of the same type
+there is no datatype conversion on input resulting in greater
+image I/O efficiency.
+.le
+.ls (2)
+In the real data path the processing arithmetic is always real and,
+if the output image is of short pixel datatype, the result
+is truncated.
+.le
+.ls (3)
+The overscan vector and the scale factors for dark count, flat field,
+iillumination, and fringe calibrations are always of type real. Therefore,
+in the short data path any processing which includes these operations
+will be coerced to real arithmetic and the result truncated at the end
+of the computation.
+.le
+.sh
+14. In the Absence of Image Header Information
+The tasks in the \fBquad\fR package are most convenient to use when
+the CCD image type, subset, and exposure time are contained in the
+image header. This is true for all data obtained with Arcon. The ability to
+redefine which header parameters contain this information makes it possible
+to use the package at many different observatories (see \fBinstruments\fR).
+However, in the absence of any image header information the tasks may still
+be used effectively. There are two ways to proceed. One way is to use
+\fBccdhedit\fR to place the information in the image header.
+
+The second way is to specify the processing operations more explicitly
+than is needed when the header information is present. The parameter
+\fIccdtype\fR is set to "" or to "none". The calibration images are
+specified explicitly by task parameter since they cannot be recognized
+in the input list. Only one subset at a time may be processed.
+
+If dark count and fringe corrections are to be applied the exposure
+times must be added to all the images. Alternatively, the dark count
+and fringe images may be scaled explicitly for each input image. This
+works because the exposure times default to 1 if they are not given in
+the image header.
+.ih
+EXAMPLES
+The user's \fBguide\fR presents a tutorial in the use of this task.
+
+1. In general all that needs to be done is to set the task parameters
+and enter
+
+ cl> quadproc *.imh &
+
+This will run in the background and process all images which have not
+been processed previously.
+.ih
+SEE ALSO
+quadformat, ccdproc, instruments, ccdtypes, flatfields, icfit, quad, guide,
+mkillumcor, mkskycor, mkfringecor
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/quadreadout.hlp b/noao/imred/quadred/src/quad/doc/quadreadout.hlp
new file mode 100644
index 00000000..355fdb61
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/quadreadout.hlp
@@ -0,0 +1,19 @@
+With Arcon it is possible to read out a CCD using more than one amplifier in
+parallel, leading to a substantial reduction in readout time. Once properly
+reduced, such data is indistinguishable from that obtained when reading out
+through only a single amplifier. However, the raw images are rather different
+and consequently must be processed somewhat differently. Firstly, each readout
+will typically have a slightly different, zero level, gain, and readout noise,
+and may differ slightly in its departures from perfect linearity. As a result
+both zero frames and uniformly illuminated exposures will show a characteristic
+chequer board pattern, the sections of the data read through each amplifier
+having different levels. Secondly, there will be a separate overscan strip,
+used to monitor the zero level, for each readout. The location of these overscan
+strips in the raw frame depends on which amplifiers are used. When all four
+amplifiers are used the four overscan regions form a vertical stripe down the
+centre of the raw image. A CCD read out through two amplifiers can have its
+two overscan strips, running side by side down the center of the picture; or
+they may be one above the other, on the same side of the picture; or the strip
+for the upper and lower halves of the CCD can be at opposited sides of the
+image (in which case there will also be a horizontal displacement of the data
+in the two sections).
diff --git a/noao/imred/quadred/src/quad/doc/setinstrument.hlp b/noao/imred/quadred/src/quad/doc/setinstrument.hlp
new file mode 100644
index 00000000..410dd20f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/setinstrument.hlp
@@ -0,0 +1,97 @@
+.help setinstrument Oct87 noao.imred.ccdred
+.ih
+NAME
+setinstrument -- Set instrument parameters
+.ih
+USAGE
+setinstrument instrument
+.ih
+PARAMETERS
+.ls instrument
+Instrument identification for instrument parameters to be set. If '?'
+then a list of the instrument identifiers is printed.
+.le
+.ls site = "kpno"
+Site ID.
+.le
+.ls directory = "ccddb$"
+Instrument directory containing instrument files. The instrument files
+are found in the subdirectory given by the site ID.
+.le
+.ls review = yes
+Review the instrument parameters? If yes then \fBeparam\fR is run for
+the parameters of \fBccdred\fR and \fBccdproc\fR.
+.le
+.ls query
+Parameter query if initial instrument is not found.
+.le
+.ih
+DESCRIPTION
+The purpose of the task is to allow the user to easily set default
+parameters for a new instrument. The default parameters are generally
+defined by support personal in an instrument directory for a particular
+site. The instrument directory is the concatenation of the specified
+directory and the site. For example if the directory is "ccddb$" and
+the site is "kpno" then the instrument directory is "ccddb$kpno/".
+The user may have his own set of instrument files in a local directory.
+The current directory is used by setting the directory and site to the
+null string ("").
+
+The user specifies an instrument identifier. This instrument may
+be specific to a particular observatory, telescope, instrument, and
+detector. If the character '?' is specified or the instrument file is
+not found then a list of instruments
+in the instrument directory is produced by paging the file "instruments.men".
+The task then performs the following operations:
+.ls (1)
+If an instrument translation file with the name given by the instrument
+ID and the extension ".dat" is found then the instrument translation
+file parameter, \fIccdred.instrument\fR, is set to this file.
+If it does not exist then the user is queried again. Note that a
+null instrument, "", is allowed to set no translation file.
+.le
+.ls (2)
+If an instrument setup script with the name given by the instrument ID
+and the extension ".cl" is found then the commands in the file are
+executed (using the command \fIcl < script\fR. This script generally
+sets default parameters.
+.le
+.ls (3)
+If the review flag is set the task \fBeparam\fR is run to allow the user
+to examine and modify the parameters for the package \fBccdred\fR and task
+\fBccdproc\fR.
+.le
+.ih
+EXAMPLES
+1. To get a list of the instruments;
+
+.nf
+ cl> setinstrument ?
+ [List of instruments]
+
+2. To set the instrument and edit the processing parameters:
+
+ cl> setinstrument ccdlink
+ [Edit CCDRED parameters]
+ [Edit CCDPROC parameters]
+
+3. To use your own instrument translation file and/or setup script in
+your working directory.
+
+ cl> setinst.site=""
+ cl> setinst.dir=""
+ cl> setinst myinstrument
+
+To make these files see help under \fBinstruments\fR. Copying and modifying
+system files is also straightforward.
+
+ cl> copy ccddb$kpno/fits.dat .
+ cl> edit fits.dat
+ cl> setinst.site=""
+ cl> setinst.dir=""
+ cl> setinst fits
+.fi
+.ih
+SEE ALSO
+instruments, ccdred, ccdproc
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/subsets.hlp b/noao/imred/quadred/src/quad/doc/subsets.hlp
new file mode 100644
index 00000000..2823bd6d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/subsets.hlp
@@ -0,0 +1,97 @@
+.help subsets Jun87 noao.imred.ccdred
+.ih
+NAME
+subsets -- Description of CCD subsets
+.ih
+DESCRIPTION
+The \fBccdred\fR package groups observation into subsets.
+The image header parameter used to identify the subsets is defined
+in the instrument translation file (see help for \fBinstruments\fR).
+For example to select subsets by the header parameter "filters" the
+instrument translation file would contain the line:
+
+ subset filters
+
+Observations are generally grouped into subsets based on a common
+instrument configuration such as a filter, aperture mask,
+grating setting, etc. This allows combining images from several
+different subsets automatically and applying the appropriate
+flat field image when processing the observations. For example
+if the subsets are by filter then \fBflatcombine\fR will search
+through all the images, find the flat field images (based on the
+CCD type parameter), and combine the flat field images from
+each filter separately. Then when processing the images the
+flat field with the same filter as the observation is used.
+
+Each subset is assigned a short identifier. This is listed when
+using \fBccdlist\fR and is appended to a root name when combining
+images. Because the subset parameter in the image header may be
+any string there must be a mapping applied to generate unique
+identifiers. This mapping is defined in the file given by
+the package parameter \fIccdred.ssfile\fR. The file consists of
+lines with two fields:
+
+ 'subset string' subset_id
+
+where the subset string is the image header string and the subset_id is
+the identifier. A field must be quoted if it contains blanks. The
+user may create this file but generally it is created by the tasks. The
+tasks use the first word of the subset string as the default identifier
+and a number is appended if the first word is not unique. The
+following steps define the subset identifier:
+
+.ls (1)
+Search the subset file, if present, for a matching subset string and
+use the defined subset identifier.
+.le
+.ls (2)
+If there is no matching subset string use the first word of the
+image header subset string and, if it is not unique,
+add successive integers until it is unique.
+.le
+.ls (3)
+If the identifier is not in the subset file create the file and add an
+entry if necessary.
+.le
+.ih
+EXAMPLES
+1. The subset file is "subsets" (the default). The subset parameter is
+translated to "f1pos" in the image header (the old NOAO CCD parameter)
+which is an integer filter position. After running a task, say
+"ccdlist *.imh" to cause all filters to be checked, the subset file contains:
+
+.nf
+ '2' 2
+ '5' 5
+ '3' 3
+.fi
+
+The order reflects the order in which the filters were encountered.
+Suppose the user wants to have more descriptive names then the subset
+file can be created or edited to the form:
+
+.nf
+ '2' U
+ '3' B
+ '4' V
+.fi
+
+(This is only an example and does not mean these are standard filters.)
+
+2. As another example suppose the image header parameter is "filter" and
+contains more descriptive strings. The subset file might become:
+
+.nf
+ 'GG 385 Filter' GG
+ 'GG 495 Filter' GG1
+ 'RG 610 Filter' RG
+ 'H-ALPHA' H_ALPHA
+.fi
+
+In this case use of the first word was not very good but it is unique.
+It is better if the filters are encoded with the thought that the first
+word will be used by \fBccdred\fR; it should be short and unique.
+.ih
+SEE ALSO
+instruments
+.endhelp
diff --git a/noao/imred/quadred/src/quad/doc/zerocombine.hlp b/noao/imred/quadred/src/quad/doc/zerocombine.hlp
new file mode 100644
index 00000000..ad1b021d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/doc/zerocombine.hlp
@@ -0,0 +1,127 @@
+.help zerocombine Sep93 arcon.quad
+.ih
+NAME
+zerocombine -- Combine and process zero level images
+.ih
+USAGE
+zerocombine input
+.ih
+PARAMETERS
+.ls input
+List of zero level images to combine. The \fIccdtype\fR parameter
+may be used to select the zero level images from a list containing all
+types of data.
+.le
+.ls output = "Zero"
+Output zero level root image name.
+.le
+.ls combine = "average" (average|median)
+Type of combining operation performed on the final set of pixels (after
+rejection). The choices are
+"average" or "median". The median uses the average of the two central
+values when the number of pixels is even.
+.le
+.ls reject = "minmax" (none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip)
+Type of rejection operation. See \fBcombine\fR for details.
+.le
+.ls ccdtype = "zero"
+CCD image type to combine. If no image type is given then all input images
+are combined.
+.le
+.ls process = no
+Process the input images before combining?
+.le
+.ls delete = no
+Delete input images after combining? Only those images combined are deleted.
+.le
+.ls clobber = no
+Clobber existing output images?
+.le
+.ls scale = "none" (none|mode|median|mean|exposure)
+Multiplicative image scaling to be applied. The choices are none, scale
+by the mode, median, or mean of the specified statistics section, or scale
+by the exposure time given in the image header.
+.le
+.ls statsec = ""
+Section of images to use in computing image statistics for scaling.
+If no section is given then the entire region of the image is
+sampled (for efficiency the images are sampled if they are big enough).
+.le
+
+.ce
+Algorithm Parameters
+.ls nlow = 0, nhigh = 1 (minmax)
+The number of low and high pixels to be rejected by the "minmax" algorithm.
+.le
+.ls nkeep = 1
+The minimum number of pixels to retain or the maximum number to reject
+when using the clipping algorithms (ccdclip, crreject, sigclip,
+avsigclip, or pclip). When given as a positive value this is the minimum
+number to keep. When given as a negative value the absolute value is
+the maximum number to reject. This is actually converted to a number
+to keep by adding it to the number of images.
+.le
+.ls mclip = yes (ccdclip, crreject, sigclip, avsigcliip)
+Use the median as the estimate for the true intensity rather than the
+average with high and low values excluded in the "ccdclip", "crreject",
+"sigclip", and "avsigclip" algorithms? The median is a better estimator
+in the presence of data which one wants to reject than the average.
+However, computing the median is slower than the average.
+.le
+.ls lsigma = 3., hsigma = 3. (ccdclip, crreject, sigclip, avsigclip, pclip)
+Low and high sigma clipping factors for the "ccdclip", "crreject", "sigclip",
+"avsigclip", and "pclip" algorithms. They multiply a "sigma" factor
+produced by the algorithm to select a point below and above the average or
+median value for rejecting pixels. The lower sigma is ignored for the
+"crreject" algorithm.
+.le
+.ls rdnoise = "0.", gain = "1.", snoise = "0." (ccdclip, crreject)
+CCD readout noise in electrons, gain in electrons/DN, and sensitivity noise
+as a fraction. These parameters are used with the "ccdclip" and "crreject"
+algorithms. The values may be either numeric or an image header keyword
+which contains the value.
+.le
+.ls pclip = -0.5 (pclip)
+Percentile clipping algorithm parameter. If greater than
+one in absolute value then it specifies a number of pixels above or
+below the median to use for computing the clipping sigma. If less
+than one in absolute value then it specifies the fraction of the pixels
+above or below the median to use. A positive value selects a point
+above the median and a negative value selects a point below the median.
+The default of -0.5 selects approximately the quartile point.
+See \fBcombine\fR for further details.
+.le
+.ls blank = 0.
+Output value to be used when there are no pixels.
+.le
+.ih
+DESCRIPTION
+The zero level images in the input image list are combined.
+The input images may be processed first if desired.
+The original images may be deleted automatically if desired.
+
+This task is a script which applies \fBquadproc\fR and \fBcombine\fR. The
+parameters and combining algorithms are described in detail in the help for
+\fBcombine\fR. This script has default parameters specifically set for
+zero level images and simplifies the combining parameters. There are other
+combining options not included in this task. For these additional
+features, such as thresholding, offseting, masking, and projecting, use
+\fBcombine\fR.
+
+The version of \fBzerocombine\fR in the \fBquad\fR package differs from that
+in \fBccdred\fR in that \fBquadproc\fR rather than \fBccdproc\fR is used to
+process the images if this is requested. The \fBquad\fR version MUST be
+used if process=yes and the input list contains any multi-readout images which
+have not been overscan corrected and trimmed.
+
+.ih
+EXAMPLES
+1. The image data contains four zero level images.
+To automatically select them and combine them as a background job
+using the default combining algorithm:
+
+ cl> zerocombine ccd*.imh&
+.ih
+SEE ALSO
+quadproc, combine
+.endhelp
diff --git a/noao/imred/quadred/src/quad/gainmeasure.par b/noao/imred/quadred/src/quad/gainmeasure.par
new file mode 100644
index 00000000..00e183af
--- /dev/null
+++ b/noao/imred/quadred/src/quad/gainmeasure.par
@@ -0,0 +1,6 @@
+flat1,s,a,"",,,First high level exposure
+flat2,s,a,"",,,Second high level exposure
+zero1,s,a,"",,,First zero level exposure
+zero2,s,a,"",,,Second zero level exposure
+section,s,a,"",,,Image section for calculations
+print_headers,b,h,yes,,,Print column headers
diff --git a/noao/imred/quadred/src/quad/gainmeasure.x b/noao/imred/quadred/src/quad/gainmeasure.x
new file mode 100644
index 00000000..592cf7cf
--- /dev/null
+++ b/noao/imred/quadred/src/quad/gainmeasure.x
@@ -0,0 +1,170 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+define OPT_REFLECT 4
+
+# GAINMEASURE -- Calculate the gain (e/ADU) and RON of a CCD using the CTIO
+# (Bruce Attwood) algorithm.
+# Input are a pair of high signal level exposures (Flat1, Flat2) and a pair of
+# zero exposures (Zero1, Zero2). We then calculate:
+#
+# epadu = <Flat1> + <Flat2> - (<Zero1> + <Zero2>) / var{Diff_F} - Var{Diff_Z}
+# RON = RMS {Diff_Z} * epadu / sqrt(2)
+#
+# Where:
+#
+# diff_Z = Zero1 - Zero2
+# diff_F = Flat1 - Flat2
+#
+# The statistics must be calculated for regions free of bad pixels and other
+# defects, and with reasonably uniform illumination.
+
+procedure t_gainmeasure ()
+
+pointer flat1, flat2 #TI High level images
+pointer zero1, zero2 #TI Zero level images
+char section[SZ_LINE] #TI Section for calculation
+
+char buffer[SZ_LINE]
+int npix, x1, x2, y1, y2, amp
+pointer sp, f1, f2, z1, z2, fd, zd, qg
+real f1bar, f2bar, z1bar, z2bar, fdbar, zdbar
+real f1sigma, f2sigma, z1sigma, z2sigma, fdsigma, zdsigma
+real div, epadu, ron
+bool headers
+
+pointer immap(), imgs2r()
+bool clgetb(), quadsect()
+int hdmaccf()
+
+begin
+ # Open instrument file
+ call clgstr ("instrument", buffer, SZ_FNAME)
+ call hdmopen (buffer)
+
+ # Map input images
+ call clgstr ("flat1", buffer, SZ_LINE)
+ flat1 = immap (buffer, READ_ONLY, 0)
+
+ call clgstr ("flat2", buffer, SZ_LINE)
+ flat2 = immap (buffer, READ_ONLY, 0)
+
+ call clgstr ("zero1", buffer, SZ_LINE)
+ zero1 = immap (buffer, READ_ONLY, 0)
+
+ call clgstr ("zero2", buffer, SZ_LINE)
+ zero2 = immap (buffer, READ_ONLY, 0)
+
+ # Get section over which measurement is to be made.
+ call clgstr ("section", section, SZ_LINE)
+
+ # See if headers are to be printed
+ headers = clgetb ("print_headers")
+
+ # Set-up quadgeom structure. We blithely assume all images are the same.
+ call quadalloc (qg)
+
+ if (hdmaccf (flat1, "HDR_REV") == NO) {
+ call quadgeom (flat1, qg, "", "")
+ } else {
+ call qghdr2 (flat1, qg)
+ }
+# call quaddump (qg)
+
+ if (headers) {
+ call printf ("#")
+ do amp = 1, QG_NAMPS (qg) {
+ call printf ("%9wAmp%2s%5w")
+ call pargstr (Memc[QG_AMPID (qg, amp)])
+ }
+ call printf ("\n")
+
+ call printf ("#")
+ do amp = 1, QG_NAMPS (qg) {
+ call printf ("%5wGain%4wRON%3w")
+ }
+ call printf ("\n")
+ call printf ("#")
+ do amp = 1, QG_NAMPS (qg) {
+ call printf ("%3w(e-/ADU)%2w(e-)%2w")
+ }
+ call printf ("\n")
+ }
+
+ call printf ("%1w")
+ do amp = 1, QG_NAMPS (qg) {
+
+ if (quadsect (qg, section, OPT_REFLECT, amp, x1, x2, y1, y2)) {
+
+ npix = (abs(y2 - y1) + 1) * (abs(x2 - x1) + 1)
+
+ # Allocate working arrays
+ call smark (sp)
+ call salloc (fd, npix, TY_REAL)
+ call salloc (zd, npix, TY_REAL)
+
+ # Read data
+ f1 = imgs2r (flat1, x1, x2, y1, y2)
+ f2 = imgs2r (flat2, x1, x2, y1, y2)
+ z1 = imgs2r (zero1, x1, x2, y1, y2)
+ z2 = imgs2r (zero2, x1, x2, y1, y2)
+
+ # Calculate differences
+ call asubr (Memr[f1], Memr[f2], Memr[fd], npix)
+ call asubr (Memr[z1], Memr[z2], Memr[zd], npix)
+
+ # Calculate means and standard deviations
+ call aavgr (Memr[f1], npix, f1bar, f1sigma)
+ call aavgr (Memr[f2], npix, f2bar, f2sigma)
+ call aavgr (Memr[z1], npix, z1bar, z1sigma)
+ call aavgr (Memr[z2], npix, z2bar, z2sigma)
+ call aavgr (Memr[fd], npix, fdbar, fdsigma)
+ call aavgr (Memr[zd], npix, zdbar, zdsigma)
+
+# call eprintf ("f1bar=%g f1sigma=%g\n")
+# call pargr (f1bar)
+# call pargr (f1sigma)
+# call eprintf ("f2bar=%g f2sigma=%g\n")
+# call pargr (f2bar)
+# call pargr (f2sigma)
+# call eprintf ("z1bar=%g z1sigma=%g\n")
+# call pargr (z1bar)
+# call pargr (z1sigma)
+# call eprintf ("z2bar=%g z2sigma=%g\n")
+# call pargr (z2bar)
+# call pargr (z2sigma)
+# call eprintf ("fdbar=%g fdsigma=%g\n")
+# call pargr (fdbar)
+# call pargr (fdsigma)
+# call eprintf ("zdbar=%g zdsigma=%g\n")
+# call pargr (zdbar)
+# call pargr (zdsigma)
+
+ div = fdsigma**2 - zdsigma**2
+ if (div > 0.0) {
+ epadu = ((f1bar + f2bar) - (z1bar + z2bar)) / div
+ ron = epadu * zdsigma / 1.41421356
+ } else {
+ epadu = INDEF
+ ron = INDEF
+ }
+
+ # Print results
+ call printf ("%3w%6.2f%2w%6.2f%2w")
+ call pargr (epadu)
+ call pargr (ron)
+
+ # Free working arrays
+ call sfree (sp)
+
+ }
+ }
+
+ call printf ("\n")
+
+ # Tidy up
+ call imunmap (flat1)
+ call imunmap (flat2)
+ call imunmap (zero1)
+ call imunmap (zero2)
+end
diff --git a/noao/imred/quadred/src/quad/hdrmap.com b/noao/imred/quadred/src/quad/hdrmap.com
new file mode 100644
index 00000000..5aa74185
--- /dev/null
+++ b/noao/imred/quadred/src/quad/hdrmap.com
@@ -0,0 +1,4 @@
+# Common for HDRMAP package.
+
+pointer stp # Symbol table pointer
+common /hdmcom/ stp
diff --git a/noao/imred/quadred/src/quad/hdrmap.x b/noao/imred/quadred/src/quad/hdrmap.x
new file mode 100644
index 00000000..ebcb253e
--- /dev/null
+++ b/noao/imred/quadred/src/quad/hdrmap.x
@@ -0,0 +1,544 @@
+include <error.h>
+include <syserr.h>
+
+.help hdrmap
+.nf-----------------------------------------------------------------------------
+HDRMAP -- Map translation between task parameters and image header parameters.
+
+In order for tasks to be partially independent of the image header
+parameter names used by different instruments and observatories a
+translation is made between task parameters and image header
+parameters. This translation is given in a file consisting of the task
+parameter name, the image header parameter name, and an optional
+default value. This file is turned into a symbol table. If the
+translation file is not found a null pointer is returned. The package will
+then use the task parameter names directly. Also if there is no
+translation given in the file for a particular parameter it is passed
+on directly. If a parameter is not in the image header then the symbol
+table default value, if given, is returned. This package is layered on
+the IMIO header package.
+
+ hdmopen (fname)
+ hdmclose ()
+ hdmwrite (fname, mode)
+ hdmname (parameter, str, max_char)
+ hdmgdef (parameter, str, max_char)
+ hdmpdef (parameter, str, max_char)
+ y/n = hdmaccf (im, parameter)
+ hdmgstr (im, parameter, str, max_char)
+ ival = hdmgeti (im, parameter)
+ rval = hdmgetr (im, parameter)
+ hdmpstr (im, parameter, str)
+ hdmputi (im, parameter, value)
+ hdmputr (im, parameter, value)
+ hdmgstp (stp)
+ hdmpstp (stp)
+ hdmdelf (im, parameter)
+ hdmparm (name, parameter, max_char)
+
+hdmopen -- Open the translation file and map it into a symbol table pointer.
+hdmclose -- Close the symbol table pointer.
+hdmwrite -- Write out translation file.
+hdmname -- Return the image header parameter name.
+hdmpname -- Put the image header parameter name.
+hdmgdef -- Get the default value as a string (null if none).
+hdmpdef -- Put the default value as a string.
+hdmaccf -- Return whether the image header parameter exists (regardless of
+ whether there is a default value).
+hdmgstr -- Get a string valued parameter. Return default value if not in the
+ image header. Return null string if no default or image value.
+hdmgeti -- Get an integer valued parameter. Return default value if not in
+ the image header and error condition if no default or image value.
+hdmgetr -- Get a real valued parameter. Return default value if not in
+ the image header or error condition if no default or image value.
+hdmpstr -- Put a string valued parameter in the image header.
+hdmputi -- Put an integer valued parameter in the image header.
+hdmputr -- Put a real valued parameter in the image header.
+hdmgstp -- Get the symbol table pointer to save it while another map is used.
+hdmpstp -- Put the symbol table pointer to restore a map.
+hdmdelf -- Delete a field.
+hdmparm -- Return the parameter name corresponding to an image header name.
+.endhelp -----------------------------------------------------------------------
+
+# Symbol table definitions.
+define LEN_INDEX 32 # Length of symtab index
+define LEN_STAB 1024 # Length of symtab string buffer
+define SZ_SBUF 128 # Size of symtab string buffer
+
+define SZ_NAME 79 # Size of translation symbol name
+define SZ_DEFAULT 79 # Size of default string
+define SYMLEN 80 # Length of symbol structure
+
+# Symbol table structure
+define NAME Memc[P2C($1)] # Translation name for symbol
+define DEFAULT Memc[P2C($1+40)] # Default value of parameter
+
+
+# HDMOPEN -- Open the translation file and map it into a symbol table pointer.
+
+procedure hdmopen (fname)
+
+char fname[ARB] # Image header map file
+
+int fd, open(), fscan(), nscan(), errcode()
+pointer sp, parameter, sym, stopen(), stenter()
+include "hdrmap.com"
+
+begin
+ # Create an empty symbol table.
+ stp = stopen (fname, LEN_INDEX, LEN_STAB, SZ_SBUF)
+
+ # Return if file not found.
+ iferr (fd = open (fname, READ_ONLY, TEXT_FILE)) {
+ if (errcode () != SYS_FNOFNAME)
+ call erract (EA_WARN)
+ return
+ }
+
+ call smark (sp)
+ call salloc (parameter, SZ_NAME, TY_CHAR)
+
+ # Read the file an enter the translations in the symbol table.
+ while (fscan(fd) != EOF) {
+ call gargwrd (Memc[parameter], SZ_NAME)
+ if ((nscan() == 0) || (Memc[parameter] == '#'))
+ next
+ sym = stenter (stp, Memc[parameter], SYMLEN)
+ call gargwrd (NAME(sym), SZ_NAME)
+ call gargwrd (DEFAULT(sym), SZ_DEFAULT)
+ }
+
+ call close (fd)
+ call sfree (sp)
+end
+
+
+# HDMCLOSE -- Close the symbol table pointer.
+
+procedure hdmclose ()
+
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ call stclose (stp)
+end
+
+
+# HDMWRITE -- Write out translation file.
+
+procedure hdmwrite (fname, mode)
+
+char fname[ARB] # Image header map file
+int mode # Access mode (APPEND, NEW_FILE)
+
+int fd, open(), stridxs()
+pointer sym, sthead(), stnext(), stname()
+errchk open
+include "hdrmap.com"
+
+begin
+ # If there is no symbol table do nothing.
+ if (stp == NULL)
+ return
+
+ fd = open (fname, mode, TEXT_FILE)
+
+ sym = sthead (stp)
+ for (sym = sthead (stp); sym != NULL; sym = stnext (stp, sym)) {
+ if (stridxs (" ", Memc[stname (stp, sym)]) > 0)
+ call fprintf (fd, "'%s'%30t")
+ else
+ call fprintf (fd, "%s%30t")
+ call pargstr (Memc[stname (stp, sym)])
+ if (stridxs (" ", NAME(sym)) > 0)
+ call fprintf (fd, " '%s'%10t")
+ else
+ call fprintf (fd, " %s%10t")
+ call pargstr (NAME(sym))
+ if (DEFAULT(sym) != EOS) {
+ if (stridxs (" ", DEFAULT(sym)) > 0)
+ call fprintf (fd, " '%s'")
+ else
+ call fprintf (fd, " %s")
+ call pargstr (DEFAULT(sym))
+ }
+ call fprintf (fd, "\n")
+ }
+
+ call close (fd)
+end
+
+
+# HDMNAME -- Return the image header parameter name
+
+procedure hdmname (parameter, str, max_char)
+
+char parameter[ARB] # Parameter name
+char str[max_char] # String containing mapped parameter name
+int max_char # Maximum characters in string
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call strcpy (NAME(sym), str, max_char)
+ else
+ call strcpy (parameter, str, max_char)
+end
+
+
+# HDMPNAME -- Put the image header parameter name
+
+procedure hdmpname (parameter, str)
+
+char parameter[ARB] # Parameter name
+char str[ARB] # String containing mapped parameter name
+
+pointer sym, stfind(), stenter()
+include "hdrmap.com"
+
+begin
+ if (stp == NULL)
+ return
+
+ sym = stfind (stp, parameter)
+ if (sym == NULL) {
+ sym = stenter (stp, parameter, SYMLEN)
+ DEFAULT(sym) = EOS
+ }
+
+ call strcpy (str, NAME(sym), SZ_NAME)
+end
+
+
+# HDMGDEF -- Get the default value as a string (null string if none).
+
+procedure hdmgdef (parameter, str, max_char)
+
+char parameter[ARB] # Parameter name
+char str[max_char] # String containing default value
+int max_char # Maximum characters in string
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call strcpy (DEFAULT(sym), str, max_char)
+ else
+ str[1] = EOS
+end
+
+
+# HDMPDEF -- PUt the default value as a string.
+
+procedure hdmpdef (parameter, str)
+
+char parameter[ARB] # Parameter name
+char str[ARB] # String containing default value
+
+pointer sym, stfind(), stenter()
+include "hdrmap.com"
+
+begin
+ if (stp == NULL)
+ return
+
+ sym = stfind (stp, parameter)
+ if (sym == NULL) {
+ sym = stenter (stp, parameter, SYMLEN)
+ call strcpy (parameter, NAME(sym), SZ_NAME)
+ }
+
+ call strcpy (str, DEFAULT(sym), SZ_DEFAULT)
+end
+
+
+# HDMACCF -- Return whether the image header parameter exists (regardless of
+# whether there is a default value).
+
+int procedure hdmaccf (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+int imaccf()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ return (imaccf (im, NAME(sym)))
+ else
+ return (imaccf (im, parameter))
+end
+
+
+# HDMGSTR -- Get a string valued parameter. Return default value if not in
+# the image header. Return null string if no default or image value.
+
+procedure hdmgstr (im, parameter, str, max_char)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+char str[max_char] # String value to return
+int max_char # Maximum characters in returned string
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ iferr (call imgstr (im, NAME(sym), str, max_char))
+ call strcpy (DEFAULT(sym), str, max_char)
+ } else {
+ iferr (call imgstr (im, parameter, str, max_char))
+ str[1] = EOS
+ }
+end
+
+
+# HDMGETR -- Get a real valued parameter. Return default value if not in
+# the image header. Return error condition if no default or image value.
+
+real procedure hdmgetr (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+int ip, ctor()
+real value, imgetr()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ iferr (value = imgetr (im, NAME(sym))) {
+ ip = 1
+ if (ctor (DEFAULT(sym), ip, value) == 0)
+ call error (0, "HDMGETR: No value found")
+ }
+ } else
+ value = imgetr (im, parameter)
+
+ return (value)
+end
+
+
+# HDMGETI -- Get an integer valued parameter. Return default value if not in
+# the image header. Return error condition if no default or image value.
+
+int procedure hdmgeti (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+int ip, ctoi()
+int value, imgeti()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ iferr (value = imgeti (im, NAME(sym))) {
+ ip = 1
+ if (ctoi (DEFAULT(sym), ip, value) == 0)
+ call error (0, "HDMGETI: No value found")
+ }
+ } else
+ value = imgeti (im, parameter)
+
+ return (value)
+end
+
+
+# HDMPSTR -- Put a string valued parameter in the image header.
+
+procedure hdmpstr (im, parameter, str)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+char str[ARB] # String value
+
+int imaccf(), imgftype()
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL) {
+ if (imaccf (im, NAME(sym)) == YES)
+ if (imgftype (im, NAME(sym)) != TY_CHAR)
+ call imdelf (im, NAME(sym))
+ call imastr (im, NAME(sym), str)
+ } else {
+ if (imaccf (im, parameter) == YES)
+ if (imgftype (im, parameter) != TY_CHAR)
+ call imdelf (im, parameter)
+ call imastr (im, parameter, str)
+ }
+end
+
+
+# HDMPUTI -- Put an integer valued parameter in the image header.
+
+procedure hdmputi (im, parameter, value)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+int value # Integer value to put
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call imaddi (im, NAME(sym), value)
+ else
+ call imaddi (im, parameter, value)
+end
+
+
+# HDMPUTR -- Put a real valued parameter in the image header.
+
+procedure hdmputr (im, parameter, value)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+real value # Real value to put
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call imaddr (im, NAME(sym), value)
+ else
+ call imaddr (im, parameter, value)
+end
+
+
+# HDMGSTP -- Get the symbol table pointer to save a translation map.
+# The symbol table is restored with HDMPSTP.
+
+procedure hdmgstp (ptr)
+
+pointer ptr # Symbol table pointer to return
+
+include "hdrmap.com"
+
+begin
+ ptr = stp
+end
+
+
+# HDMPSTP -- Put a symbol table pointer to restore a header map.
+# The symbol table is optained with HDMGSTP.
+
+procedure hdmpstp (ptr)
+
+pointer ptr # Symbol table pointer to restore
+
+include "hdrmap.com"
+
+begin
+ stp = ptr
+end
+
+
+# HDMDELF -- Delete a field. It is an error if the field does not exist.
+
+procedure hdmdelf (im, parameter)
+
+pointer im # IMIO pointer
+char parameter[ARB] # Parameter name
+
+pointer sym, stfind()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = stfind (stp, parameter)
+ else
+ sym = NULL
+
+ if (sym != NULL)
+ call imdelf (im, NAME(sym))
+ else
+ call imdelf (im, parameter)
+end
+
+
+# HDMPARAM -- Get parameter given the image header name.
+
+procedure hdmparam (name, parameter, max_char)
+
+char name[ARB] # Image header name
+char parameter[max_char] # Parameter
+int max_char # Maximum size of parameter string
+
+bool streq()
+pointer sym, sthead(), stname(), stnext()
+include "hdrmap.com"
+
+begin
+ if (stp != NULL)
+ sym = sthead (stp)
+ else
+ sym = NULL
+
+ while (sym != NULL) {
+ if (streq (NAME(sym), name)) {
+ call strcpy (Memc[stname(stp, sym)], parameter, max_char)
+ return
+ }
+ sym = stnext (stp, sym)
+ }
+ call strcpy (name, parameter, max_char)
+end
diff --git a/noao/imred/quadred/src/quad/irlincor.par b/noao/imred/quadred/src/quad/irlincor.par
new file mode 100644
index 00000000..77739715
--- /dev/null
+++ b/noao/imred/quadred/src/quad/irlincor.par
@@ -0,0 +1,12 @@
+# irlincor parameter file
+input,s,a,"",,,Input images
+output,s,a,"",,,Output images
+section,s,h,"",,,Image section to correct
+coeff1,r,h,1.0,,,First coefficient of correction equation
+coeff2,r,h,0.0,,,Second coefficient of correction equation
+coeff3,r,h,0.0,,,Third coefficient of correction equation
+coeff4,r,h,0.0,,,Fourth coefficient of correction equation
+coeff5,r,h,0.0,,,Fifth coefficient of correction equation
+coeff6,r,h,0.0,,,Sixth coefficient of correction equation
+coeff7,r,h,0.0,,,Seventh coefficient of correction equation
+maxadu,r,h,INDEF,0,,Maximum number of ADU
diff --git a/noao/imred/quadred/src/quad/mkpkg b/noao/imred/quadred/src/quad/mkpkg
new file mode 100644
index 00000000..9243e633
--- /dev/null
+++ b/noao/imred/quadred/src/quad/mkpkg
@@ -0,0 +1,56 @@
+# QUAD mkpkg file (Mon Mar 28 14:07:29 CST 1994)
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $update libpkg.a
+ $omake x_quad.x
+ $link x_quad.o libpkg.a -lxtools -o xx_quad.e
+ ;
+
+install:
+ $move xx_quad.e noaobin$x_quad.e
+ ;
+
+libpkg.a:
+
+ $ifolder (qsplits.x, qsplit.gx) $generic -k -t silrd qsplit.gx $endif
+
+ ccddelete.x
+ ccdgetparam.x
+ ccdlog.x
+ ccdprcselect.x "ccdtypes.h"
+ ccdsection.x <ctype.h>
+ ccdssselect.x "ccdtypes.h"
+ ccdsubsets.x
+ ccdtypes.x "ccdtypes.h"
+ gainmeasure.x "quadgeom.h" <imhdr.h>
+ hdrmap.x "hdrmap.com" <error.h> <syserr.h>
+ qghdr2.x "quadgeom.h" <imhdr.h>
+ qguser.x "quadgeom.h"
+ qpcalimage.x "ccdtypes.h" <error.h> <imset.h>
+ qpselect.x "ccdtypes.h"
+ qsplitd.x "quadgeom.h" <imhdr.h>
+ qspliti.x "quadgeom.h" <imhdr.h>
+ qsplitl.x "quadgeom.h" <imhdr.h>
+ qsplitr.x "quadgeom.h" <imhdr.h>
+ qsplits.x "quadgeom.h" <imhdr.h>
+ quadalloc.x "quadgeom.h" <imhdr.h>
+ quaddelete.x "quadgeom.h"
+ quadgeom.x "quadgeom.h" <imhdr.h>
+ quadgeomred.x "quadgeom.h" <imhdr.h>
+ quadjoin.x "quadgeom.h" <imhdr.h>
+ quadmap.x "quadgeom.h" <error.h> <imhdr.h>
+ quadmerge.x "quadgeom.h" <imhdr.h>
+ quadscale.x "quadgeom.h" <imhdr.h>
+ quadsections.x "quadgeom.h" <imhdr.h>
+ quadsplit.x "quadgeom.h" <imhdr.h>
+ test.x "quadgeom.h"
+ timelog.x <time.h>
+ ;
diff --git a/noao/imred/quadred/src/quad/new.par b/noao/imred/quadred/src/quad/new.par
new file mode 100644
index 00000000..8700d447
--- /dev/null
+++ b/noao/imred/quadred/src/quad/new.par
@@ -0,0 +1,8 @@
+input,s,a,"",,,Input image name
+instrument,s,a,"",,,Instrument file
+xtrim1,i,h,0,0,,
+xtrim2,i,h,0,0,,
+ytrim1,i,h,0,0,,
+ytrim2,i,h,0,0,,
+xskip1,i,h,0,0,,
+xskip2,i,h,0,0,,
diff --git a/noao/imred/quadred/src/quad/old.par b/noao/imred/quadred/src/quad/old.par
new file mode 100644
index 00000000..e77315b3
--- /dev/null
+++ b/noao/imred/quadred/src/quad/old.par
@@ -0,0 +1,2 @@
+input,s,a,"",,,Input image name
+instrument,s,a,"",,,Instrument file
diff --git a/noao/imred/quadred/src/quad/qccdproc.par b/noao/imred/quadred/src/quad/qccdproc.par
new file mode 100644
index 00000000..f20207a7
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qccdproc.par
@@ -0,0 +1,43 @@
+images,s,a,"",,,List of CCD images to correct
+ccdtype,s,h,"",,,CCD image type to correct
+max_cache,i,h,0,0,,Maximum image caching memory (in Mbytes)
+noproc,b,h,no,,,"List processing steps only?
+"
+fixpix,b,h,yes,,,Fix bad CCD lines and columns?
+overscan,b,h,yes,,,Apply overscan strip correction?
+trim,b,h,yes,,,Trim the image?
+zerocor,b,h,yes,,,Apply zero level correction?
+darkcor,b,h,no,,,Apply dark count correction?
+flatcor,b,h,yes,,,Apply flat field correction?
+illumcor,b,h,no,,,Apply illumination correction?
+fringecor,b,h,no,,,Apply fringe correction?
+readcor,b,h,no,,,Convert zero level image to readout correction?
+scancor,b,h,no,,,"Convert flat field image to scan correction?
+"
+readaxis,s,h,"line","column|line",, Read out axis (column|line)
+fixfile,s,h,"",,,File describing the bad lines and columns
+biassec,s,h,"",,,Overscan strip image section
+trimsec,s,h,"",,,Trim data section
+zero,s,h,"",,,Zero level calibration image
+dark,s,h,"",,,Dark count calibration image
+flat,s,h,"",,,Flat field images
+illum,s,h,"",,,Illumination correction images
+fringe,s,h,"",,,Fringe correction images
+minreplace,r,h,1.,,,Minimum flat field value
+scantype,s,h,"shortscan","shortscan|longscan",,Scan type (shortscan|longscan)
+nscan,i,h,1,1,,"Number of short scan lines
+"
+interactive,b,h,no,,,Fit overscan interactively?
+function,s,h,"legendre",,,Fitting function
+order,i,h,1,1,,Number of polynomial terms or spline pieces
+sample,s,h,"*",,,Sample points to fit
+naverage,i,h,1,,,Number of sample points to combine
+niterate,i,h,1,0,,Number of rejection iterations
+low_reject,r,h,3.,0.,,Low sigma rejection factor
+high_reject,r,h,3.,0.,,High sigma rejection factor
+grow,r,h,0.,0.,,"Rejection growing radius
+"
+verbose,b,h,)_.verbose,,,Print log information to the standard output?
+logfile,f,h,)_.logfile,,,Text log file
+backup,s,h,)_.backup,,,Backup directory or prefix
+output,s,h,"",,,Not used
diff --git a/noao/imred/quadred/src/quad/qdarkcombine.cl b/noao/imred/quadred/src/quad/qdarkcombine.cl
new file mode 100644
index 00000000..7f0ef6e7
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qdarkcombine.cl
@@ -0,0 +1,48 @@
+# DARKCOMBINE -- Process and combine dark count CCD images.
+
+procedure darkcombine (input)
+
+string input {prompt="List of dark images to combine"}
+file output="Dark" {prompt="Output dark image root name"}
+string combine="average" {prompt="Type of combine operation",
+ enum="average|median"}
+string reject="avsigclip" {prompt="Type of rejection",
+ enum="none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip"}
+string ccdtype="dark" {prompt="CCD image type to combine"}
+bool process=yes {prompt="Process images before combining?"}
+bool delete=no {prompt="Delete input images after combining?"}
+bool clobber=no {prompt="Clobber existing output image?"}
+string scale="exposure" {prompt="Image scaling",
+ enum="none|mode|median|mean|exposure"}
+string statsec="" {prompt="Image section for computing statistics"}
+int nlow=1 {prompt="minmax: Number of low pixels to reject"}
+int nhigh=1 {prompt="minmax: Number of high pixels to reject"}
+int nkeep=1 {prompt="Minimum to keep (pos) or maximum to reject (neg)"}
+bool mclip=yes {prompt="Use median in sigma clipping algorithms?"}
+real lsigma=3. {prompt="Lower sigma clipping factor"}
+real hsigma=3. {prompt="Upper sigma clipping factor"}
+string rdnoise="0." {prompt="ccdclip: CCD readout noise (electrons)"}
+string gain="1." {prompt="ccdclip: CCD gain (electrons/DN)"}
+string snoise="0." {prompt="ccdclip: Sensitivity noise (fraction)"}
+real pclip=-0.5 {prompt="pclip: Percentile clipping parameter"}
+real blank=0. {prompt="Value if there are no pixels"}
+
+begin
+ string ims
+
+ ims = input
+
+ # Process images first if desired.
+ if (process == YES)
+ quadproc (ims, ccdtype=ccdtype)
+
+ # Combine the dark images.
+ combine (ims, output=output, plfile="", sigma="", combine=combine,
+ reject=reject, ccdtype=ccdtype, subsets=no, delete=delete,
+ clobber=clobber, project=no, outtype="real", offsets="none",
+ masktype="none", blank=blank, scale=scale, zero="none", weight=no,
+ statsec=statsec, lthreshold=INDEF, hthreshold=INDEF, nlow=nlow,
+ nhigh=nhigh, nkeep=nkeep, mclip=mclip, lsigma=lsigma, hsigma=hsigma,
+ rdnoise=rdnoise, gain=gain, snoise=snoise, sigscale=0.1,
+ pclip=pclip, grow=0)
+end
diff --git a/noao/imred/quadred/src/quad/qflatcombine.cl b/noao/imred/quadred/src/quad/qflatcombine.cl
new file mode 100644
index 00000000..7a0eb7ce
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qflatcombine.cl
@@ -0,0 +1,49 @@
+# FLATCOMBINE -- Process and combine flat field CCD images.
+
+procedure flatcombine (input)
+
+string input {prompt="List of flat field images to combine"}
+file output="Flat" {prompt="Output flat field root name"}
+string combine="average" {prompt="Type of combine operation",
+ enum="average|median"}
+string reject="avsigclip" {prompt="Type of rejection",
+ enum="none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip"}
+string ccdtype="flat" {prompt="CCD image type to combine"}
+bool process=yes {prompt="Process images before combining?"}
+bool subsets=yes {prompt="Combine images by subset parameter?"}
+bool delete=no {prompt="Delete input images after combining?"}
+bool clobber=no {prompt="Clobber existing output image?"}
+string scale="mode" {prompt="Image scaling",
+ enum="none|mode|median|mean|exposure"}
+string statsec="" {prompt="Image section for computing statistics"}
+int nlow=1 {prompt="minmax: Number of low pixels to reject"}
+int nhigh=1 {prompt="minmax: Number of high pixels to reject"}
+int nkeep=1 {prompt="Minimum to keep (pos) or maximum to reject (neg)"}
+bool mclip=yes {prompt="Use median in sigma clipping algorithms?"}
+real lsigma=3. {prompt="Lower sigma clipping factor"}
+real hsigma=3. {prompt="Upper sigma clipping factor"}
+string rdnoise="0." {prompt="ccdclip: CCD readout noise (electrons)"}
+string gain="1." {prompt="ccdclip: CCD gain (electrons/DN)"}
+string snoise="0." {prompt="ccdclip: Sensitivity noise (fraction)"}
+real pclip=-0.5 {prompt="pclip: Percentile clipping parameter"}
+real blank=1. {prompt="Value if there are no pixels"}
+
+begin
+ string ims
+
+ ims = input
+
+ # Process images first if desired.
+ if (process == YES)
+ quadproc (ims, ccdtype=ccdtype)
+
+ # Combine the flat field images.
+ combine (ims, output=output, plfile="", sigma="", combine=combine,
+ reject=reject, ccdtype=ccdtype, subsets=subsets, delete=delete,
+ clobber=clobber, project=no, outtype="real", offsets="none",
+ masktype="none", blank=blank, scale=scale, zero="none", weight=no,
+ statsec=statsec, lthreshold=INDEF, hthreshold=INDEF, nlow=nlow,
+ nhigh=nhigh, nkeep=nkeep, mclip=mclip, lsigma=lsigma, hsigma=hsigma,
+ rdnoise=rdnoise, gain=gain, snoise=snoise, sigscale=0.1,
+ pclip=pclip, grow=0)
+end
diff --git a/noao/imred/quadred/src/quad/qghdr2.x b/noao/imred/quadred/src/quad/qghdr2.x
new file mode 100644
index 00000000..6a483a5b
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qghdr2.x
@@ -0,0 +1,216 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+define SZ_KEYWRD 8 # Chars in FITS keyword
+
+# QGHDR2 -- Set up section information in quadgeom structure based on
+# information in the image header.
+
+procedure qghdr2 (im, qg)
+
+pointer im #I Pointer to input image.
+pointer qg #IO Pointer to open quadgeom structure.
+
+pointer sp, keyword, hdrvalue, section
+int amp
+int ax1, ax2, axs, ay1, ay2, ays
+int bx1, bx2, bxs, by1, by2, bys
+int cx1, cx2, cxs, cy1, cy2, cys
+int dx1, dx2, dxs, dy1, dy2, dys
+int tx1, tx2, txs, ty1, ty2, tys
+
+int hdmaccf()
+
+begin
+
+ # Get stack space
+ call smark (sp)
+ call salloc (keyword, SZ_KEYWRD, TY_CHAR)
+ call salloc (hdrvalue, SZ_LINE, TY_CHAR)
+ call salloc (section, SZ_LINE, TY_CHAR)
+
+ # Get input image dimensions.
+ QG_NX (qg, 0) = IM_LEN(im, 1)
+ QG_NY (qg, 0) = IM_LEN(im, 2)
+
+ # Get number of active amplifiers in Y and X.
+ call hdmgstr (im, "nampsyx", Memc[hdrvalue], SZ_LINE)
+ call sscan (Memc[hdrvalue])
+ call gargi (QG_NAMPSY(qg))
+ call gargi (QG_NAMPSX(qg))
+
+ QG_NAMPS(qg) = QG_NAMPSY(qg) * QG_NAMPSX(qg)
+ if (QG_NAMPS(qg) > QG_MAXAMPS)
+ call error (0, "CCD has too many read-outs for this program")
+
+ # Get decode and order list of active amplifiers.
+ call hdmgstr (im, "amplist", Memc[hdrvalue], SZ_LINE)
+ call ampnames (qg, Memc[hdrvalue])
+
+ # Read geometry keywords for each amplifier from header.
+ do amp = 1, QG_NAMPS (qg) {
+
+ # Ampsec (ASECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_KEYWRD, "ASEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ call hdmgstr (im, Memc[keyword], Memc[section], SZ_LINE)
+
+ ax1 = 1
+ ax2 = QG_NX(qg, 0) / QG_NAMPSX(qg)
+ axs = 1
+ ay1 = 1
+ ay2 = QG_NY(qg, 0) / QG_NAMPSY(qg)
+ ays = 1
+
+ call ccd_section (Memc[section], ax1, ax2, axs, ay1, ay2, ays)
+ QG_AX1(qg, amp) = ax1
+ QG_AX2(qg, amp) = ax2
+ QG_AY1(qg, amp) = ay1
+ QG_AY2(qg, amp) = ay2
+
+ # Set X and Y dimensions of subimage read out by each amplifier
+ QG_NX(qg, amp) = ax2 - ax1 + 1
+ QG_NY(qg, amp) = ay2 - ay1 + 1
+
+ # Datasec (DSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_KEYWRD, "DSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ call hdmgstr (im, Memc[keyword], Memc[section], SZ_LINE)
+
+ dx1 = ax1
+ dx2 = ax2
+ dxs = 1
+ dy1 = ay1
+ dy2 = ay2
+ dys = 1
+ call ccd_section (Memc[section], dx1, dx2, dxs, dy1, dy2, dys)
+ QG_DX1(qg, amp) = dx1 - ax1 + 1
+ QG_DX2(qg, amp) = dx2 - ax1 + 1
+ QG_DY1(qg, amp) = dy1 - ay1 + 1
+ QG_DY2(qg, amp) = dy2 - ay1 + 1
+
+ # CCDsec (CSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_KEYWRD, "CSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ call hdmgstr (im, Memc[keyword], Memc[section], SZ_LINE)
+
+ cx1 = dx1
+ cx2 = dx2
+ cxs = 1
+ cy1 = dy1
+ cy2 = dy2
+ cys = 1
+ call ccd_section (Memc[section], cx1, cx2, cxs, cy1, cy2, cys)
+ QG_CX1(qg, amp) = cx1
+ QG_CX2(qg, amp) = cx2
+ QG_CY1(qg, amp) = cy1
+ QG_CY2(qg, amp) = cy2
+
+ # Trimsec (TSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_KEYWRD, "TSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ if (hdmaccf (im, Memc[keyword]) == YES) {
+ call hdmgstr (im, Memc[keyword], Memc[section], SZ_LINE)
+
+ tx1 = dx1
+ tx2 = dx2
+ txs = 1
+ ty1 = dy1
+ ty2 = dy2
+ tys = 1
+ call ccd_section (Memc[section], tx1, tx2, txs, ty1, ty2, tys)
+ QG_TX1(qg, amp) = tx1 - ax1 + 1
+ QG_TX2(qg, amp) = tx2 - ax1 + 1
+ QG_TY1(qg, amp) = ty1 - ay1 + 1
+ QG_TY2(qg, amp) = ty2 - ay1 + 1
+
+ QG_PHANTOM(qg, amp) = NO
+
+ } else {
+ QG_TX1(qg, amp) = 0
+ QG_TX2(qg, amp) = 0
+ QG_TY1(qg, amp) = 0
+ QG_TY2(qg, amp) = 0
+
+ # If the image has not been reduced this must be a phantom
+ if (hdmaccf (im, "trim") == NO) {
+ QG_PHANTOM(qg, amp) = YES
+ } else {
+ QG_PHANTOM(qg, amp) = NO
+ }
+ }
+
+ # Biassec (BSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_KEYWRD, "BSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ if (hdmaccf (im, Memc[keyword]) == YES) {
+ call hdmgstr (im, Memc[keyword], Memc[section], SZ_LINE)
+
+ bx1 = 0
+ bx2 = 0
+ bxs = 1
+ by1 = 0
+ by2 = 0
+ bys = 1
+ call ccd_section (Memc[section], bx1, bx2, bxs, by1, by2, bys)
+ QG_BX1(qg, amp) = bx1 - ax1 + 1
+ QG_BX2(qg, amp) = bx2 - ax1 + 1
+ QG_BY1(qg, amp) = by1 - ay1 + 1
+ QG_BY2(qg, amp) = by2 - ay1 + 1
+ } else {
+ QG_BX1(qg, amp) = 0
+ QG_BX2(qg, amp) = 0
+ QG_BY1(qg, amp) = 0
+ QG_BY2(qg, amp) = 0
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+procedure ampnames (qg, amplist)
+
+pointer qg #I/O Pointer to open quadgeom structure
+char amplist[ARB] #I List of active amplifiers
+
+int amp, nch
+pointer sp, ampnum
+
+int strdic(), itoc()
+
+begin
+ call smark (sp)
+ call salloc (ampnum, QG_NAMPS (qg), TY_INT)
+
+ # parse amplist into array of ordinal numbers
+ call sscan (amplist)
+ do amp = 1, QG_NAMPS (qg) {
+ call gargi (Memi[ampnum+amp-1])
+ }
+
+ # Sort ordinal numbers into increasing order
+ call asrti (Memi[ampnum], Memi[ampnum], QG_NAMPS(qg))
+
+ # Convert ordinal numbers back into id strings
+ do amp = 1, QG_NAMPS (qg) {
+ call malloc (QG_AMPID(qg, amp), SZ_AMPID, TY_CHAR)
+ nch = itoc (Memi[ampnum+amp-1], Memc[QG_AMPID(qg, amp)], SZ_AMPID)
+ }
+
+ # Set AMPTYPE codes
+ do amp = 1, QG_NAMPS (qg) {
+ QG_AMPTYPE (qg, amp) = strdic (Memc[QG_AMPID (qg, amp)],
+ Memc[QG_AMPID (qg, amp)], SZ_AMPID, AMPDICT)
+ }
+
+ call sfree (sp)
+
+end
diff --git a/noao/imred/quadred/src/quad/qguser.x b/noao/imred/quadred/src/quad/qguser.x
new file mode 100644
index 00000000..5d4bf349
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qguser.x
@@ -0,0 +1,126 @@
+include "quadgeom.h"
+
+# QGUSER -- modify open quadgeom structure for user specified trim and
+# overscan.
+
+procedure qguser (qg, xtrim1, xtrim2, ytrim1, ytrim2, xskip1, xskip2)
+
+pointer qg # Pointer to open quadgeom structure.
+int xtrim1 # Number of pixels to trim at right.
+int xtrim2 # Number of pixels to trim at left.
+int ytrim1 # Number of pixels to trim at bottom.
+int ytrim2 # Number of pixels to trim at top.
+int xskip1 # Number of pixels to skip at start of overscan in X.
+int xskip2 # Number of pixels to skip at end of overscan in X.
+
+int amp, x, y
+int bx1, bx2, by1, by2
+
+begin
+
+ # Modify overscan margins
+ Do amp = 1, QG_NAMPS (qg) {
+
+ switch (QG_AMPTYPE(qg, amp)) {
+ case AMP11, AMP21: # Left hand side
+ if (IS_INDEFI (xskip1)) {
+ bx1 = QG_BX1(qg, amp)
+ } else {
+ bx1 = QG_DX2(qg, amp) + xskip1 + 1
+ }
+
+ if (IS_INDEFI (xskip2)) {
+ bx2 = QG_BX2(qg, amp)
+ } else {
+ bx2 = QG_AX2(qg, amp) - QG_AX1(qg, amp) - xskip2 + 1
+ }
+
+ case AMP12, AMP22: # Right hand side
+ if (IS_INDEFI (xskip2)) {
+ bx1 = QG_BX1(qg, amp)
+ } else {
+ bx1 = 1 + xskip2
+ }
+ if (IS_INDEFI (xskip1)) {
+ bx2 = QG_BX2(qg, amp)
+ } else {
+ bx2 = QG_DX1(qg, amp) - xskip1 - 1
+ }
+
+ }
+ by1 = QG_BY1(qg, amp)
+ by2 = QG_BY2(qg, amp)
+
+ if (bx1 > bx2) {
+ bx1 = 0
+ bx2 = 0
+ by1 = 0
+ by2 = 0
+ }
+
+ QG_BX1(qg, amp) = bx1
+ QG_BX2(qg, amp) = bx2
+ QG_BY1(qg, amp) = by1
+ QG_BY2(qg, amp) = by2
+
+ }
+
+ # Modify trim margins
+
+ # Set left hand edge
+ if (! IS_INDEFI(xtrim1)) {
+ do y = 1, QG_NAMPSY(qg) {
+ do x = 1, QG_NAMPSX(qg) {
+
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM(qg, amp) == NO) {
+ QG_TX1(qg, amp) = QG_DX1(qg, amp) + xtrim1
+ break
+ }
+ }
+ }
+ }
+
+ # Set right hand edge
+ if (! IS_INDEFI(xtrim2)) {
+ do y = 1, QG_NAMPSY(qg) {
+ do x = QG_NAMPSX(qg), 1, -1 {
+
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM(qg, amp) == NO) {
+ QG_TX2(qg, amp) = QG_DX2(qg, amp) - xtrim2
+ break
+ }
+ }
+ }
+ }
+
+
+ # Set lower edge
+ if (! IS_INDEFI(ytrim1)) {
+ do x = 1, QG_NAMPSX(qg) {
+ do y = 1, QG_NAMPSY(qg) {
+
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM(qg, amp) == NO) {
+ QG_TY1(qg, amp) = QG_DY1(qg, amp) + ytrim1
+ break
+ }
+ }
+ }
+ }
+
+ # Set upper edge
+ if (! IS_INDEFI(ytrim2)) {
+ do x = 1, QG_NAMPSX(qg) {
+ do y = QG_NAMPSY(qg), 1, -1 {
+
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM(qg, amp) == NO) {
+ QG_TY2(qg, amp) = QG_DY2(qg, amp) - ytrim2
+ break
+ }
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qhistogram.cl b/noao/imred/quadred/src/quad/qhistogram.cl
new file mode 100644
index 00000000..4b5c1958
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qhistogram.cl
@@ -0,0 +1,58 @@
+procedure qhistogram (image)
+
+begin
+ string tmp, meta, im, subimage, amp, section
+ int nx, ny
+# real zz1, zz2, mean, mode, min, max, sigma
+
+ im = image
+
+ tmp = mktemp ("uparm$tmp")
+ fdtmp = tmp
+ meta = mktemp ("uparm$meta")
+
+ # Project image section on to quadrant boundaries.
+ #quadsections (im, window=window, section="", template="$I$S $A $S\n",
+ #xskip1=INDEF, xskip2=INDEF, xtrim1=INDEF, xtrim2=INDEF,
+ #ytrim1=INDEF, ytrim2=INDEF, >> tmp)
+ quadsections (im, window=window, section="", template="$I$S $A $S\n",
+ >> tmp)
+
+# # Set up histogram limits
+# switch (substr (scaling, 1, 1) {
+# case "s": set
+# zz1 = z1
+# zz2 = z2
+
+# case minmax"
+
+
+ if (listout) {
+ printf ("%s\n", im)
+ while (fscan (fdtmp, subimage, amp, section) != EOF) {
+
+ printf ("\tAmp%s: section=%s\n\n", amp, section)
+
+ imhist (subimage, z1=z1, z2=z2, binwidth=binwidth, nbins=nbins,
+ autoscale=autoscale, top_closed=top_closed, hist_type=hist_type,
+ listout=listout, plot_type=plot_type, logy=logy, device=device)
+ }
+
+ } else {
+ while (fscan (fdtmp, subimage) != EOF) {
+
+ imhist (subimage, z1=z1, z2=z2, binwidth=binwidth, nbins=nbins,
+ autoscale=autoscale, top_closed=top_closed, hist_type=hist_type,
+ listout=listout, plot_type=plot_type, logy=logy, device=device,
+ >>G meta)
+
+ }
+ ccdgetparam (im, "nampsyx") | scan (ny, nx)
+ gkim (meta, device=device, output=plotfile, nx=nx, ny=ny, rotate=no,
+ fill=yes, interactive=no, cursor="")
+
+ delete (meta, ver-)
+ }
+
+ delete (tmp, ver-)
+end
diff --git a/noao/imred/quadred/src/quad/qhistogram.par b/noao/imred/quadred/src/quad/qhistogram.par
new file mode 100644
index 00000000..1ba40ec1
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qhistogram.par
@@ -0,0 +1,17 @@
+image,s,a,,,,Image name
+window,s,h,"datasec","|datasec|trimsec|biassec|reflect|duplicate|",,Window to apply to image
+z1,r,h,INDEF,,,Minimum histogram intensity
+z2,r,h,INDEF,,,Maximum histogram intensity
+binwidth,r,h,INDEF,,,Resolution of histogram in intensity units
+nbins,i,h,512,1,,Number of bins in histogram
+autoscale,b,h,yes,,,Adjust nbins and z2 for integer data?
+top_closed,b,h,no,,,Include z2 in the top bin?
+hist_type,s,h,"normal","normal|cumulative|difference|second_difference",,"Type of histogram"
+listout,b,h,no,,,List instead of plot histogram?
+plot_type,s,h,"line","line|box",,Type of vectors to plot
+logy,b,h,yes,,,Log scale y-axis?
+device,s,h,"stdgraph",,,Output graphics device
+plotfile,s,h,"",,,"Output graphics file
+"
+fdtmp,*s,h,,,,Internal use only
+mode,s,h,ql,,,
diff --git a/noao/imred/quadred/src/quad/qnoproc.cl b/noao/imred/quadred/src/quad/qnoproc.cl
new file mode 100644
index 00000000..9f7d048f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qnoproc.cl
@@ -0,0 +1,77 @@
+procedure qnoproc (image_list)
+
+begin
+ string image, buffer, imtype
+ int i, len, nampsx, nampsy, nlines
+ bool dofix, dotrim, doover
+
+ imtype = "." // envget ("imtype")
+ i = stridx (",", imtype)
+ if (i > 0)
+ imtype = substr (imtype, 1, i-1)
+ i = strlen (imtype)
+
+ dofix = fixpix
+ doover = overscan
+ dotrim = trim
+
+ fd = image_list
+ while (fscan (fd, image) != EOF) {
+
+ len = strlen (image)
+ if (substr(image, len-i+1, len) == imtype) {
+ image = substr (image, 1, len-i)
+ }
+
+ # Report what processing steps will be performed by qproc
+ printf ("%s:", image)
+
+ if (fixpix) {
+ ccdgetparam (image, "fixpix") | scan (buffer)
+ dofix = (buffer == "UNDEFINED!")
+ }
+
+ if (overscan) {
+ ccdgetparam (image, "overscan") | scan (buffer)
+ doover = (buffer == "UNDEFINED!")
+ }
+
+ if (trim) {
+ ccdgetparam (image, "trim") | scan (buffer)
+ dotrim = (buffer == "UNDEFINED!")
+ }
+
+ if (dofix || dotrim || doover) {
+ ccdgetparam (image, "nampsyx") | scan (nampsy, nampsx)
+ if (nampsx == 2 && nampsy == 2) {
+ printf (" (Quad-readout image)\n")
+ } else if (nampsx == 2 || nampsy == 2) {
+ printf (" (Dual-readout image: nampsx=%d nampsy=%d)\n",
+ nampsx, nampsy)
+ } else {
+ printf ("\n")
+ }
+
+ if (doover) {
+ printf (" [TO BE DONE] Trim section is:\n")
+ #quadsections (image, window="trimsec", section="",
+ #template="%18tAMP$A $S\n", xskip1=xskip1, xskip2=xskip2,
+ #xtrim1=xtrim1, xtrim2=xtrim2, ytrim1=ytrim1, ytrim2=ytrim2)
+ quadsections (image, window="trimsec", section="",
+ template="%18tAMP$A $S\n")
+ }
+
+ if (dofix)
+ printf (" [TO BE DONE] Bad pixel file is %s\n", fixfile)
+
+ if (doover) {
+ printf (" [TO BE DONE] Overscan section is:\n")
+ #quadsections (image, window="biassec", section="",
+ #template="%18tAMP$A $S\n", xskip1=xskip1, xskip2=xskip2,
+ #xtrim1=xtrim1, xtrim2=xtrim2, ytrim1=ytrim1, ytrim2=ytrim2)
+ quadsections (image, window="biassec", section="",
+ template="%18tAMP$A $S\n")
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qnoproc.par b/noao/imred/quadred/src/quad/qnoproc.par
new file mode 100644
index 00000000..7e01c141
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qnoproc.par
@@ -0,0 +1,15 @@
+image_list,s,a,"",,,List of CCD images to correct
+fixpix,b,h,yes,,,Fix bad CCD lines and columns?
+overscan,b,h,yes,,,Apply overscan strip correction?
+trim,b,h,yes,,,Trim the image?
+fixfile,s,h,"",,,"File describing the bad lines and columns
+
+# TRIM AND OVERSCAN MARGINS (overide header values)"
+xskip1,i,h,INDEF,0,,X pixels to skip at start of overscan
+xskip2,i,h,INDEF,0,,X pixels to skip at end of overscan
+xtrim1,i,h,INDEF,0,,X pixels to trim at start of data
+xtrim2,i,h,INDEF,0,,X pixels to trim at end of data
+ytrim1,i,h,INDEF,0,,Y pixels to trim at start of data
+ytrim2,i,h,INDEF,0,,"Y pixels to trim at end of data
+"
+fd,*s,h,,,,Internal use only
diff --git a/noao/imred/quadred/src/quad/qpcalimage.par b/noao/imred/quadred/src/quad/qpcalimage.par
new file mode 100644
index 00000000..ddeb506d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qpcalimage.par
@@ -0,0 +1,3 @@
+quadproc,pset,h,,,,CCD processing parameters
+only_param,b,h,no,,,Only return calibration images from parameters
+check,b,h,yes,,,Complain if any calibration images are unspecified
diff --git a/noao/imred/quadred/src/quad/qpcalimage.x b/noao/imred/quadred/src/quad/qpcalimage.x
new file mode 100644
index 00000000..2e0ee40b
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qpcalimage.x
@@ -0,0 +1,525 @@
+include <error.h>
+include <imset.h>
+include "ccdtypes.h"
+
+define SZ_SUBSET 16 # Maximum size of subset string
+define IMAGE Memc[$1+($2-1)*SZ_FNAME] # Image string
+define SUBSET Memc[$1+($2-1)*SZ_SUBSET] # Subset string
+
+procedure t_qpcalimage ()
+
+pointer im, subsets, list
+int i, j
+bool flatcor, illumcor, fringecor, found, check
+char instrument[SZ_LINE], image[SZ_FNAME], buffer[SZ_SUBSET-1]
+
+pointer immap(), imtopenp()
+int imtgetim()
+bool clgetb(), streq()
+
+begin
+ # Open list of images and instrument file
+ list = imtopenp ("images")
+ call clgstr ("instrument", instrument, SZ_LINE)
+ call hdmopen (instrument)
+
+ if (clgetb ("only_param")) {
+ call cal_open (NULL)
+ } else {
+ call cal_open (list)
+ }
+
+ check = clgetb ("check")
+
+ if (clgetb ("zerocor")) {
+ iferr (call cal_find (ZERO, "", image, SZ_FNAME)) {
+ if (check) {
+ call erract (EA_WARN)
+ }
+
+ } else {
+ call printf ("%s\n")
+ call pargstr (image)
+ }
+ }
+
+ if (clgetb ("darkcor")) {
+ iferr (call cal_find (DARK, "", image, SZ_FNAME)) {
+ if (check)
+ call erract (EA_WARN)
+
+ } else {
+ call printf ("%s\n")
+ call pargstr (image)
+ }
+ }
+
+ flatcor = clgetb ("flatcor")
+ illumcor = clgetb ("illumcor")
+ fringecor = clgetb ("fringecor")
+
+ if (flatcor || illumcor || fringecor) {
+
+ i = 1
+ found = false
+ while (imtgetim (list, image, SZ_FNAME) != EOF) {
+ # Open the image. Silently skip any non-existant images
+ iferr (im = immap (image, READ_ONLY, 0))
+ next
+
+ call ccdsubset (im, buffer, SZ_SUBSET-1)
+ call imunmap (im)
+
+ # Check to see if we have already dealt with this subset
+ do j = 1, i - 1 {
+ found = (streq (buffer, SUBSET (subsets, j)))
+ if (found)
+ break
+ }
+
+ if (!found) {
+
+ # Add subset to list of processed subsets
+ if (i == 1)
+ call malloc (subsets, i * SZ_SUBSET, TY_CHAR)
+ else
+ call realloc (subsets, i * SZ_SUBSET, TY_CHAR)
+
+ call strcpy (buffer, SUBSET(subsets, i), SZ_SUBSET-1)
+ i = i + 1
+
+ # Find and print names of associated calibration images
+ if (flatcor) {
+ iferr (call cal_find (FLAT, buffer, image, SZ_FNAME)) {
+ if (check)
+ call erract (EA_WARN)
+
+ } else {
+ call printf ("%s\n")
+ call pargstr (image)
+ }
+ }
+
+ if (illumcor) {
+ iferr (call cal_find (ILLUM, buffer, image, SZ_FNAME)) {
+ if (check)
+ call erract (EA_WARN)
+
+ } else {
+ call printf ("%s\n")
+ call pargstr (image)
+ }
+ }
+
+ if (fringecor) {
+ iferr (call cal_find (FRINGE, buffer, image, SZ_FNAME)){
+ if (check)
+ call erract (EA_WARN)
+
+ } else {
+ call printf ("%s\n")
+ call pargstr (image)
+ }
+ }
+ }
+ }
+ }
+
+ call hdmclose ()
+ call imtclose (list)
+ call mfree (subsets, TY_CHAR)
+ call cal_close ()
+
+end
+
+# CAL_FIND -- Return a calibration image of the specified type and subset
+# CAL_IMAGE -- Return a calibration image for a specified input image.
+# CAL_OPEN -- Open the calibration image list.
+# CAL_CLOSE -- Close the calibration image list.
+# CAL_LIST -- Add images to the calibration image list.
+#
+# The open procedure is called first to get the calibration image
+# lists and add them to an internal list. Calibration images from the
+# input list are also added so that calibration images may be specified
+# either from the calibration image list parameters or in the input image list.
+# Existence errors and duplicate calibration images are ignored.
+# Validity checks are made when the calibration images are requested.
+#
+# During processing the calibration image names are requested for each input
+# image. The calibration image list is searched for a calibration image of
+# the right type and subset. If more than one is found the first one is
+# returned and a warning given for the others. The warning is only issued
+# once. If no calibration image is found then an error is returned.
+#
+# The calibration image list must be closed at the end of processing the
+# input images.
+
+# CAL_FIND -- Return a calibration image of a particular type and subset.
+# Search the calibration list for the first calibration image of the desired
+# type and subset. Print a warning if there is more than one possible
+# calibration image and return an error if there is no calibration image.
+
+procedure cal_find (ccdtype, subset, image, maxchars)
+
+int ccdtype #I Callibration CCD image type
+char subset[ARB] #I Calibration image subset
+char image[maxchars] #O Calibration image (returned)
+int maxchars #I Maximum number chars in image name
+
+int i
+char errmsg[SZ_LINE]
+bool strne()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subsets
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, images, nimages
+
+begin
+
+ switch (ccdtype) {
+ case ZERO, DARK:
+ do i = 1, nimages {
+ if (Memi[ccdtypes+i-1] != ccdtype)
+ next
+
+ call strcpy (IMAGE(images,i), image, maxchars)
+ return
+ }
+
+ case FLAT, ILLUM, FRINGE:
+ do i = 1, nimages {
+ if (Memi[ccdtypes+i-1] != ccdtype)
+ next
+ if (strne (SUBSET(subsets,i), subset))
+ next
+
+ call strcpy (IMAGE(images,i), image, maxchars)
+ return
+ }
+ }
+
+ # If no calibration image is found then it is an error.
+ switch (ccdtype) {
+ case ZERO:
+ call error (0, "No zero level calibration image found")
+ case DARK:
+ call error (0, "No dark count calibration image found")
+ case FLAT:
+ call sprintf (errmsg, SZ_LINE,
+ "No flat field calibration image of subset %s found")
+ call pargstr (subset)
+ call error (0, errmsg)
+ case ILLUM:
+ call sprintf (errmsg, SZ_LINE,
+ "No illumination calibration image of subset %s found")
+ call pargstr (subset)
+ call error (0, errmsg)
+ case FRINGE:
+ call sprintf (errmsg, SZ_LINE,
+ "No fringe calibration image of subset %s found")
+ call pargstr (subset)
+ call error (0, errmsg)
+ }
+end
+
+# CAL_IMAGE -- Return a calibration image of a particular type.
+# Search the calibration list for the first calibration image of the desired
+# type and subset. Print a warning if there is more than one possible
+# calibration image and return an error if there is no calibration image.
+
+procedure cal_image (im, ccdtype, image, maxchars)
+
+pointer im # Image to be processed
+int ccdtype # Callibration CCD image type
+char image[maxchars] # Calibration image (returned)
+int maxchars # Maximum number chars in image name
+
+int i, n
+pointer sp, subset, str
+bool strne(), ccd_cmp()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subsets
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, images, nimages
+
+begin
+ call smark (sp)
+ call salloc (subset, SZ_SUBSET, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ switch (ccdtype) {
+ case ZERO, DARK:
+ n = 0
+ do i = 1, nimages {
+ if (Memi[ccdtypes+i-1] != ccdtype)
+ next
+ n = n + 1
+ if (n == 1)
+ call strcpy (IMAGE(images,i), image, maxchars)
+ else {
+# call eprintf (
+# "Warning: Extra calibration image %s ignored\n")
+# call pargstr (IMAGE(images,i))
+
+ # Reset the image type to eliminate further warnings.
+ Memi[ccdtypes+i-1] = UNKNOWN
+ }
+ }
+ case FLAT, ILLUM, FRINGE:
+ call ccdsubset (im, Memc[subset], SZ_SUBSET)
+
+ n = 0
+ do i = 1, nimages {
+ if (Memi[ccdtypes+i-1] != ccdtype)
+ next
+ if (strne (SUBSET(subsets,i), Memc[subset]))
+ next
+ n = n + 1
+ if (n == 1)
+ call strcpy (IMAGE(images,i), image, maxchars)
+ else {
+# call eprintf (
+# "Warning: Extra calibration image %s ignored\n")
+# call pargstr (IMAGE(images,i))
+
+ # Reset the image type to eliminate further warnings.
+ Memi[ccdtypes+i-1] = UNKNOWN
+ }
+ }
+ }
+
+ # If no calibration image is found then it is an error.
+ if (n == 0)
+ switch (ccdtype) {
+ case ZERO:
+ call error (0, "No zero level calibration image found")
+ case DARK:
+ call error (0, "No dark count calibration image found")
+ case FLAT:
+ call sprintf (Memc[str], SZ_LINE,
+ "No flat field calibration image of subset %s found")
+ call pargstr (Memc[subset])
+ call error (0, Memc[str])
+ case ILLUM:
+ call sprintf (Memc[str], SZ_LINE,
+ "No illumination calibration image of subset %s found")
+ call pargstr (Memc[subset])
+ call error (0, Memc[str])
+ case FRINGE:
+ call sprintf (Memc[str], SZ_LINE,
+ "No fringe calibration image of subset %s found")
+ call pargstr (Memc[subset])
+ call error (0, Memc[str])
+ }
+
+ # Check that the input image is not the same as the calibration image.
+ call imstats (im, IM_IMAGENAME, Memc[str], SZ_LINE)
+ if (ccd_cmp (Memc[str], image)) {
+ call sprintf (Memc[str], SZ_LINE,
+ "Calibration image %s is the same as the input image")
+ call pargstr (image)
+ call error (0, Memc[str])
+ }
+
+ call sfree (sp)
+end
+
+
+# CAL_OPEN -- Create a list of calibration images from the input image list
+# and the calibration image lists.
+
+procedure cal_open (list)
+
+int list # List of input images
+int list1 # List of calibration images
+
+pointer sp, str
+int ccdtype, strdic(), imtopenp()
+bool clgetb()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subset numbers
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, images, nimages
+
+errchk cal_list
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ call clgstr ("ccdtype", Memc[str], SZ_LINE)
+ call xt_stripwhite (Memc[str])
+ if (Memc[str] == EOS)
+ ccdtype = NONE
+ else
+ ccdtype = strdic (Memc[str], Memc[str], SZ_LINE, CCDTYPES)
+
+ # Add calibration images to list.
+ nimages = 0
+ if (ccdtype != ZERO && clgetb ("zerocor")) {
+ list1 = imtopenp ("zero")
+ call cal_list (list1, ZERO)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && clgetb ("darkcor")) {
+ list1 = imtopenp ("dark")
+ call cal_list (list1, DARK)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && ccdtype != FLAT &&
+ clgetb ("flatcor")) {
+ list1 = imtopenp ("flat")
+ call cal_list (list1, FLAT)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && ccdtype != FLAT &&
+ ccdtype != ILLUM && clgetb ("illumcor")) {
+ list1 = imtopenp ("illum")
+ call cal_list (list1, ILLUM)
+ call imtclose (list1)
+ }
+ if (ccdtype != ZERO && ccdtype != DARK && ccdtype != FLAT &&
+ ccdtype != FRINGE && clgetb ("fringecor")) {
+ list1 = imtopenp ("fringe")
+ call cal_list (list1, FRINGE)
+ call imtclose (list1)
+ }
+ if (list != NULL) {
+ call cal_list (list, UNKNOWN)
+ call imtrew (list)
+ }
+
+ call sfree (sp)
+end
+
+
+# CAL_CLOSE -- Free memory from the internal calibration image list.
+
+procedure cal_close ()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subset
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, images, nimages
+
+begin
+ if (nimages > 0) {
+ call mfree (ccdtypes, TY_INT)
+ call mfree (subsets, TY_CHAR)
+ call mfree (images, TY_CHAR)
+ }
+end
+
+
+# CAL_LIST -- Add calibration images to an internal list.
+# Map each image and get the CCD image type and subset.
+# If the ccdtype is given as a procedure argument this overrides the
+# image header type. For the calibration images add the type, subset,
+# and image name to dynamic arrays. Ignore duplicate names.
+
+procedure cal_list (list, listtype)
+
+pointer list # Image list
+int listtype # CCD type of image in list.
+ # Overrides header type if not UNKNOWN.
+
+int i, ccdtype, ccdtypei(), imtgetim()
+pointer sp, image, im, immap()
+bool streq()
+
+pointer ccdtypes # Pointer to array of calibration ccdtypes
+pointer subsets # Pointer to array of calibration subsets
+pointer images # Pointer to array of calibration image names
+int nimages # Number of images
+common /calib/ ccdtypes, subsets, images, nimages
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+
+ while (imtgetim (list, Memc[image], SZ_FNAME) != EOF) {
+ # Open the image. If an explicit type is given it is an
+ # error if the image can't be opened.
+ iferr (im = immap (Memc[image], READ_ONLY, 0)) {
+ if (listtype == UNKNOWN)
+ next
+ else
+ call erract (EA_ERROR)
+ }
+
+ # Override image header CCD type if a list type is given.
+ if (listtype == UNKNOWN)
+ ccdtype = ccdtypei (im)
+ else
+ ccdtype = listtype
+
+ switch (ccdtype) {
+ case ZERO, DARK, FLAT, ILLUM, FRINGE:
+ # Check for duplication.
+ for (i=1; i<=nimages; i=i+1)
+ if (streq (Memc[image], IMAGE(images,i)))
+ break
+ if (i <= nimages)
+ break
+
+ # Allocate memory for a new image.
+ if (i == 1) {
+ call malloc (ccdtypes, i, TY_INT)
+ call malloc (subsets, i * SZ_SUBSET, TY_CHAR)
+ call malloc (images, i * SZ_FNAME, TY_CHAR)
+ } else {
+ call realloc (ccdtypes, i, TY_INT)
+ call realloc (subsets, i * SZ_FNAME, TY_CHAR)
+ call realloc (images, i * SZ_FNAME, TY_CHAR)
+ }
+
+ # Enter the ccdtype, subset, and image name.
+ Memi[ccdtypes+i-1] = ccdtype
+ call ccdsubset (im, SUBSET(subsets,i), SZ_SUBSET-1)
+ call strcpy (Memc[image], IMAGE(images,i), SZ_FNAME-1)
+ nimages = i
+ }
+ call imunmap (im)
+ }
+# call eprintf ("nimages=%d\n")
+# call pargi (nimages)
+# do i = 1, nimages {
+# call eprintf ("ccdtype=%d subset=%s image=%s\n")
+# call pargi (Memi[ccdtypes+i-1])
+# call pargstr (SUBSET (subsets, i))
+# call pargstr (IMAGE (images, i))
+# }
+
+ call sfree (sp)
+end
+
+# CCD_CMP -- Compare two image names with extensions ignored.
+
+bool procedure ccd_cmp (image1, image2)
+
+char image1[ARB] # First image
+char image2[ARB] # Second image
+
+int i, j, strmatch(), strlen(), strncmp()
+bool streq()
+
+begin
+ if (streq (image1, image2))
+ return (true)
+
+ i = max (strmatch (image1, ".imh"), strmatch (image1, ".hhh"))
+ if (i == 0)
+ i = strlen (image1)
+ j = max (strmatch (image2, ".imh"), strmatch (image2, ".hhh"))
+ if (j == 0)
+ j = strlen (image2)
+
+ return (strncmp (image1, image2, max (i, j)) == 0)
+end
diff --git a/noao/imred/quadred/src/quad/qproc.cl b/noao/imred/quadred/src/quad/qproc.cl
new file mode 100644
index 00000000..d0040d18
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qproc.cl
@@ -0,0 +1,109 @@
+procedure qproc (image_list)
+
+begin
+ struct buffer
+ string image, answr, imtype
+ int i, len, nampsx, nampsy
+
+ imtype = "." // envget ("imtype")
+ i = stridx (",", imtype)
+ if (i > 0)
+ imtype = substr (imtype, 1, i-1)
+ i = strlen (imtype)
+
+ cache ("quadsplit", "quadjoin", "qccdproc", "quadproc")
+
+
+ # Validate fixfile
+ if (fixpix) {
+ match ("single_readout", fixfile) | scan (buffer)
+ if (stridx ("#", buffer) == 0) {
+ buffer = "fixfile " // fixfile //
+ " cannot be used with multi-readout images"
+ error (0, buffer)
+ }
+ }
+
+ # Initialise interactive query
+ if (qccdproc.interactive) {
+ answer.p_value = "yes"
+ answr = "yes"
+ } else {
+ answr = "NO"
+ }
+
+ fd = image_list
+ while (fscan (fd, image) != EOF) {
+
+ len = strlen (image)
+ if (substr(image, len-i+1, len) == imtype) {
+ image = substr (image, 1, len-i)
+ }
+
+ # Split out one image for each quadrant and set header sections
+ #quadsplit (image, output="",
+ #xskip1=xskip1, xskip2=xskip2, xtrim1=xtrim1, xtrim2=xtrim2,
+ #ytrim1=ytrim1, ytrim2=ytrim2, clobber=yes)
+ quadsplit (image, output="", clobber=yes)
+
+
+ # Find out of interactive fit is required for this image
+ if (answr == "yes" || answr == "no") {
+ printf ("Fit overscan vector for %s interactively\n", image) |
+ scan (buffer)
+ answer.p_prompt=buffer
+ answr = answer
+ }
+
+ # Overscan correct and trim
+ if (answr == "yes" || answr == "YES") {
+ qccdproc.interactive = yes
+
+ print ("YES") | qccdproc (image//".??"//imtype, fixpix=fixpix,
+ overscan=overscan, trim=trim, readaxis=readaxis,
+ fixfile=fixfile, biassec="image", trimsec="image",
+ ccdtype="", max_cache=0, noproc=no, zerocor=no, darkcor=no,
+ flatcor=no, illumcor=no, fringecor=no, readcor=no,
+ scancor=no, zero="", dark="", flat="", illum="", fringe="",
+ minreplace=1., scantype="shortscan", nscan=1, backup="",
+ logfile="", verbose=no, >> "dev$null")
+
+ # Set parameters of quadproc used for overscan fitting to match
+ # the ccdproc values which may have been adjusted interactively.
+ # We do this on every pass in case there is a later interupt
+ # of task execution.
+ quadproc.function.p_value = qccdproc.function
+ quadproc.order.p_value = qccdproc.order
+ quadproc.sample.p_value = qccdproc.sample
+ quadproc.naverage.p_value = qccdproc.naverage
+ quadproc.niterate.p_value = qccdproc.niterate
+ quadproc.low_reject.p_value = qccdproc.low_reject
+ quadproc.high_reject.p_value = qccdproc.high_reject
+ quadproc.grow.p_value = qccdproc.grow
+
+ # Force the parameter update
+ update ("quadproc")
+
+ } else {
+ qccdproc.interactive = no
+
+ qccdproc (image//".??"//imtype, fixpix=fixpix,
+ overscan=overscan, trim=trim, readaxis=readaxis,
+ fixfile=fixfile, biassec="image", trimsec="image",
+ ccdtype="", max_cache=0, noproc=no, zerocor=no, darkcor=no,
+ flatcor=no, illumcor=no, fringecor=no, readcor=no,
+ scancor=no, zero="", dark="", flat="", illum="", fringe="",
+ minreplace=1., scantype="shortscan", nscan=1, backup="",
+ logfile="", verbose=no)
+ }
+
+ # Combine processed quadrants into single image
+ quadjoin (image, output="", delete=yes)
+
+ }
+
+ # Reset interactive flag if we haven't recieved a definative NO
+ if (answr == "no") {
+ qccdproc.interactive = yes
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qproc.par b/noao/imred/quadred/src/quad/qproc.par
new file mode 100644
index 00000000..6a713a5d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qproc.par
@@ -0,0 +1,15 @@
+image_list,s,a,"",,,List of CCD images to correct
+fixpix,b,h,yes,,,Fix bad CCD lines and columns?
+overscan,b,h,yes,,,Apply overscan strip correction?
+trim,b,h,yes,,,Trim the image?
+readaxis,s,h,"line","column|line",, Read out axis (column|line)
+fixfile,s,h,"",,,File describing the bad lines and columns
+xskip1,i,h,INDEF,0,,X pixels to skip at start of overscan
+xskip2,i,h,INDEF,0,,X pixels to skip at end of overscan
+xtrim1,i,h,INDEF,0,,X pixels to trim at start of data
+xtrim2,i,h,INDEF,0,,X pixels to trim at end of data
+ytrim1,i,h,INDEF,0,,Y pixels to trim at start of data
+ytrim2,i,h,INDEF,0,,Y pixels to trim at end of data
+answer,s,ql,"yes","|yes|no|YES|NO|",,"Fit overscan vector for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx interactively
+"
+fd,*s,h,,,,Internal use only
diff --git a/noao/imred/quadred/src/quad/qpselect.par b/noao/imred/quadred/src/quad/qpselect.par
new file mode 100644
index 00000000..d1a7aa56
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qpselect.par
@@ -0,0 +1,4 @@
+input,s,a,"",,,Input image list
+output,s,h,"STDOUT",,,Output image list
+ccdtype,s,h,"",,,CCD image type to be listed
+stop,b,h,"no",,,"Stop, rather than pass, selected images"
diff --git a/noao/imred/quadred/src/quad/qpselect.x b/noao/imred/quadred/src/quad/qpselect.x
new file mode 100644
index 00000000..8bd2acb2
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qpselect.x
@@ -0,0 +1,108 @@
+# QPSELECT -- Filter a list of image names passing on only those that are of
+# the specified ccdtype -AND-
+#
+# If stop = yes
+# 1) Are multi-readout -AND-
+# 2) Have not been trimmed
+# If stop = no
+# 1) Are single-readout -OR-
+# 2) Have been trimmed
+
+include "ccdtypes.h"
+
+procedure t_qpselect ()
+
+pointer inlist #TI List of input image name.
+char output[SZ_FNAME] #TI List of output image names.
+char instrument[SZ_FNAME] #TI Instrument translation file.
+char ccdtype[SZ_LINE] #TI ccdtype to select.
+bool stop #TI stop rather than pass selected images
+
+int type, nampx, nampy
+char image[SZ_LINE], nampsyx[SZ_LINE]
+pointer fdout, im
+
+int strdic(), imtopenp(), imtgetim(), hdmaccf(), imaccess()
+int ccdtypei()
+bool clgetb()
+
+pointer open(), immap()
+
+begin
+ # Open input and output image lists
+ inlist = imtopenp ("input")
+ call clgstr ("output", output, SZ_LINE)
+ fdout = open (output, APPEND, TEXT_FILE)
+
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Get ccdtype to select.
+ call clgstr ("ccdtype", ccdtype, SZ_LINE)
+ type = strdic (ccdtype, ccdtype, SZ_LINE, CCDTYPES)
+
+ # Get stop
+ stop = clgetb ("stop")
+
+ while (imtgetim (inlist, image, SZ_LINE) != EOF) {
+
+ # Silently skip any non-existant images
+ if (imaccess (image, READ_ONLY) == NO)
+ next
+
+ im = immap (image, READ_ONLY, 0)
+
+ if ((ccdtype[1] != EOS) && (type != ccdtypei (im))) {
+ call imunmap (im)
+ next
+ }
+
+ if (stop) {
+
+ if (hdmaccf (im, "trim") == YES) {
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+
+ } else if (hdmaccf (im, "nampsyx") == NO) {
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+
+ } else {
+
+ call hdmgstr (im, "nampsyx", nampsyx, SZ_LINE)
+ call sscan (nampsyx)
+ call gargi (nampx)
+ call gargi (nampy)
+
+ if (nampx == 1 && nampy == 1) {
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+ }
+ }
+
+ } else {
+
+ if ((hdmaccf (im, "trim") == NO) &&
+ (hdmaccf (im, "nampsyx") == YES)) {
+
+ call hdmgstr (im, "nampsyx", nampsyx, SZ_LINE)
+ call sscan (nampsyx)
+ call gargi (nampx)
+ call gargi (nampy)
+
+ if (nampx != 1 || nampy != 1) {
+ call fprintf (fdout, "%s\n")
+ call pargstr (image)
+ }
+ }
+ }
+
+ call imunmap (im)
+ }
+
+ # Tidy up
+ call close (fdout)
+ call hdmclose ()
+ call imtclose (inlist)
+end
diff --git a/noao/imred/quadred/src/quad/qsplit.gx b/noao/imred/quadred/src/quad/qsplit.gx
new file mode 100644
index 00000000..3d5b1873
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qsplit.gx
@@ -0,0 +1,97 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QSPLITx -- Split multi-readout image into separate images one for each
+# readout.
+
+procedure qsplit$t (in, out, qg)
+
+pointer in #I Image pointer for input image
+pointer out[ARB] #I Image pointer for output images
+pointer qg #I pointer to quadgeom structure
+
+long ivec[IM_MAXDIM], ovec[IM_MAXDIM, QG_MAXAMPS]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+bool all_phantom
+
+int imgnl$t(), impnl$t()
+
+begin
+ # Setup start vectors for sequential reads ...
+ call amovkl (long(1), ivec, IM_MAXDIM)
+ # ... and writes
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ovec[1, amp], IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+
+ # Check to see if there are any non phantom regions in this tier
+ all_phantom = true
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ all_phantom = false
+ break
+ }
+ }
+
+ if (all_phantom) {
+
+ # Reset start vector for reads to skip phantom data
+ ivec[2] = ivec[2] + long (QG_NY (qg, amp2))
+
+ } else {
+
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnl$t (in, ibuf, ivec)
+ ptr = ibuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ junk = impnl$t (out[amp], obuf, ovec[1, amp])
+ call amov$t (Mem$t[ptr], Mem$t[obuf], QG_NX(qg, amp))
+ }
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+ }
+end
+
+# QJOINx -- Join multi-readout sub-images into a single image.
+
+procedure qjoin$t (in, out, qg)
+
+pointer in[ARB] #I Image pointer for input images.
+pointer out #I Image pointer for output image.
+pointer qg #I pointer to quadgeom structure.
+
+long ivec[IM_MAXDIM, QG_MAXAMPS], ovec[IM_MAXDIM]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+
+int imgnl$t(), impnl$t()
+
+begin
+ # Setup start vectors for sequential reads ...
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ivec[1, amp], IM_MAXDIM)
+ # ... and writes
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = impnl$t (out, obuf, ovec)
+ ptr = obuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ junk = imgnl$t (in[amp], ibuf, ivec[1, amp])
+ call amov$t (Mem$t[ibuf], Mem$t[ptr], QG_NX(qg, amp))
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qsplitd.x b/noao/imred/quadred/src/quad/qsplitd.x
new file mode 100644
index 00000000..b7680f4d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qsplitd.x
@@ -0,0 +1,97 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QSPLITx -- Split multi-readout image into separate images one for each
+# readout.
+
+procedure qsplitd (in, out, qg)
+
+pointer in #I Image pointer for input image
+pointer out[ARB] #I Image pointer for output images
+pointer qg #I pointer to quadgeom structure
+
+long ivec[IM_MAXDIM], ovec[IM_MAXDIM, QG_MAXAMPS]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+bool all_phantom
+
+int imgnld(), impnld()
+
+begin
+ # Setup start vectors for sequential reads ...
+ call amovkl (long(1), ivec, IM_MAXDIM)
+ # ... and writes
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ovec[1, amp], IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+
+ # Check to see if there are any non phantom regions in this tier
+ all_phantom = true
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ all_phantom = false
+ break
+ }
+ }
+
+ if (all_phantom) {
+
+ # Reset start vector for reads to skip phantom data
+ ivec[2] = ivec[2] + long (QG_NY (qg, amp2))
+
+ } else {
+
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnld (in, ibuf, ivec)
+ ptr = ibuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ junk = impnld (out[amp], obuf, ovec[1, amp])
+ call amovd (Memd[ptr], Memd[obuf], QG_NX(qg, amp))
+ }
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+ }
+end
+
+# QJOINx -- Join multi-readout sub-images into a single image.
+
+procedure qjoind (in, out, qg)
+
+pointer in[ARB] #I Image pointer for input images.
+pointer out #I Image pointer for output image.
+pointer qg #I pointer to quadgeom structure.
+
+long ivec[IM_MAXDIM, QG_MAXAMPS], ovec[IM_MAXDIM]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+
+int imgnld(), impnld()
+
+begin
+ # Setup start vectors for sequential reads ...
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ivec[1, amp], IM_MAXDIM)
+ # ... and writes
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = impnld (out, obuf, ovec)
+ ptr = obuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ junk = imgnld (in[amp], ibuf, ivec[1, amp])
+ call amovd (Memd[ibuf], Memd[ptr], QG_NX(qg, amp))
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qspliti.x b/noao/imred/quadred/src/quad/qspliti.x
new file mode 100644
index 00000000..84aa5fc7
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qspliti.x
@@ -0,0 +1,97 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QSPLITx -- Split multi-readout image into separate images one for each
+# readout.
+
+procedure qspliti (in, out, qg)
+
+pointer in #I Image pointer for input image
+pointer out[ARB] #I Image pointer for output images
+pointer qg #I pointer to quadgeom structure
+
+long ivec[IM_MAXDIM], ovec[IM_MAXDIM, QG_MAXAMPS]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+bool all_phantom
+
+int imgnli(), impnli()
+
+begin
+ # Setup start vectors for sequential reads ...
+ call amovkl (long(1), ivec, IM_MAXDIM)
+ # ... and writes
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ovec[1, amp], IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+
+ # Check to see if there are any non phantom regions in this tier
+ all_phantom = true
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ all_phantom = false
+ break
+ }
+ }
+
+ if (all_phantom) {
+
+ # Reset start vector for reads to skip phantom data
+ ivec[2] = ivec[2] + long (QG_NY (qg, amp2))
+
+ } else {
+
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnli (in, ibuf, ivec)
+ ptr = ibuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ junk = impnli (out[amp], obuf, ovec[1, amp])
+ call amovi (Memi[ptr], Memi[obuf], QG_NX(qg, amp))
+ }
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+ }
+end
+
+# QJOINx -- Join multi-readout sub-images into a single image.
+
+procedure qjoini (in, out, qg)
+
+pointer in[ARB] #I Image pointer for input images.
+pointer out #I Image pointer for output image.
+pointer qg #I pointer to quadgeom structure.
+
+long ivec[IM_MAXDIM, QG_MAXAMPS], ovec[IM_MAXDIM]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+
+int imgnli(), impnli()
+
+begin
+ # Setup start vectors for sequential reads ...
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ivec[1, amp], IM_MAXDIM)
+ # ... and writes
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = impnli (out, obuf, ovec)
+ ptr = obuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ junk = imgnli (in[amp], ibuf, ivec[1, amp])
+ call amovi (Memi[ibuf], Memi[ptr], QG_NX(qg, amp))
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qsplitl.x b/noao/imred/quadred/src/quad/qsplitl.x
new file mode 100644
index 00000000..5e1d0e7e
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qsplitl.x
@@ -0,0 +1,97 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QSPLITx -- Split multi-readout image into separate images one for each
+# readout.
+
+procedure qsplitl (in, out, qg)
+
+pointer in #I Image pointer for input image
+pointer out[ARB] #I Image pointer for output images
+pointer qg #I pointer to quadgeom structure
+
+long ivec[IM_MAXDIM], ovec[IM_MAXDIM, QG_MAXAMPS]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+bool all_phantom
+
+int imgnll(), impnll()
+
+begin
+ # Setup start vectors for sequential reads ...
+ call amovkl (long(1), ivec, IM_MAXDIM)
+ # ... and writes
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ovec[1, amp], IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+
+ # Check to see if there are any non phantom regions in this tier
+ all_phantom = true
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ all_phantom = false
+ break
+ }
+ }
+
+ if (all_phantom) {
+
+ # Reset start vector for reads to skip phantom data
+ ivec[2] = ivec[2] + long (QG_NY (qg, amp2))
+
+ } else {
+
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnll (in, ibuf, ivec)
+ ptr = ibuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ junk = impnll (out[amp], obuf, ovec[1, amp])
+ call amovl (Meml[ptr], Meml[obuf], QG_NX(qg, amp))
+ }
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+ }
+end
+
+# QJOINx -- Join multi-readout sub-images into a single image.
+
+procedure qjoinl (in, out, qg)
+
+pointer in[ARB] #I Image pointer for input images.
+pointer out #I Image pointer for output image.
+pointer qg #I pointer to quadgeom structure.
+
+long ivec[IM_MAXDIM, QG_MAXAMPS], ovec[IM_MAXDIM]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+
+int imgnll(), impnll()
+
+begin
+ # Setup start vectors for sequential reads ...
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ivec[1, amp], IM_MAXDIM)
+ # ... and writes
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = impnll (out, obuf, ovec)
+ ptr = obuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ junk = imgnll (in[amp], ibuf, ivec[1, amp])
+ call amovl (Meml[ibuf], Meml[ptr], QG_NX(qg, amp))
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qsplitr.x b/noao/imred/quadred/src/quad/qsplitr.x
new file mode 100644
index 00000000..adba483d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qsplitr.x
@@ -0,0 +1,97 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QSPLITx -- Split multi-readout image into separate images one for each
+# readout.
+
+procedure qsplitr (in, out, qg)
+
+pointer in #I Image pointer for input image
+pointer out[ARB] #I Image pointer for output images
+pointer qg #I pointer to quadgeom structure
+
+long ivec[IM_MAXDIM], ovec[IM_MAXDIM, QG_MAXAMPS]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+bool all_phantom
+
+int imgnlr(), impnlr()
+
+begin
+ # Setup start vectors for sequential reads ...
+ call amovkl (long(1), ivec, IM_MAXDIM)
+ # ... and writes
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ovec[1, amp], IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+
+ # Check to see if there are any non phantom regions in this tier
+ all_phantom = true
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ all_phantom = false
+ break
+ }
+ }
+
+ if (all_phantom) {
+
+ # Reset start vector for reads to skip phantom data
+ ivec[2] = ivec[2] + long (QG_NY (qg, amp2))
+
+ } else {
+
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnlr (in, ibuf, ivec)
+ ptr = ibuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ junk = impnlr (out[amp], obuf, ovec[1, amp])
+ call amovr (Memr[ptr], Memr[obuf], QG_NX(qg, amp))
+ }
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+ }
+end
+
+# QJOINx -- Join multi-readout sub-images into a single image.
+
+procedure qjoinr (in, out, qg)
+
+pointer in[ARB] #I Image pointer for input images.
+pointer out #I Image pointer for output image.
+pointer qg #I pointer to quadgeom structure.
+
+long ivec[IM_MAXDIM, QG_MAXAMPS], ovec[IM_MAXDIM]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+
+int imgnlr(), impnlr()
+
+begin
+ # Setup start vectors for sequential reads ...
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ivec[1, amp], IM_MAXDIM)
+ # ... and writes
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = impnlr (out, obuf, ovec)
+ ptr = obuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ junk = imgnlr (in[amp], ibuf, ivec[1, amp])
+ call amovr (Memr[ibuf], Memr[ptr], QG_NX(qg, amp))
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qsplits.x b/noao/imred/quadred/src/quad/qsplits.x
new file mode 100644
index 00000000..b4eaba80
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qsplits.x
@@ -0,0 +1,97 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QSPLITx -- Split multi-readout image into separate images one for each
+# readout.
+
+procedure qsplits (in, out, qg)
+
+pointer in #I Image pointer for input image
+pointer out[ARB] #I Image pointer for output images
+pointer qg #I pointer to quadgeom structure
+
+long ivec[IM_MAXDIM], ovec[IM_MAXDIM, QG_MAXAMPS]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+bool all_phantom
+
+int imgnls(), impnls()
+
+begin
+ # Setup start vectors for sequential reads ...
+ call amovkl (long(1), ivec, IM_MAXDIM)
+ # ... and writes
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ovec[1, amp], IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+
+ # Check to see if there are any non phantom regions in this tier
+ all_phantom = true
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ all_phantom = false
+ break
+ }
+ }
+
+ if (all_phantom) {
+
+ # Reset start vector for reads to skip phantom data
+ ivec[2] = ivec[2] + long (QG_NY (qg, amp2))
+
+ } else {
+
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnls (in, ibuf, ivec)
+ ptr = ibuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ if (QG_PHANTOM (qg, amp) == NO) {
+ junk = impnls (out[amp], obuf, ovec[1, amp])
+ call amovs (Mems[ptr], Mems[obuf], QG_NX(qg, amp))
+ }
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+ }
+end
+
+# QJOINx -- Join multi-readout sub-images into a single image.
+
+procedure qjoins (in, out, qg)
+
+pointer in[ARB] #I Image pointer for input images.
+pointer out #I Image pointer for output image.
+pointer qg #I pointer to quadgeom structure.
+
+long ivec[IM_MAXDIM, QG_MAXAMPS], ovec[IM_MAXDIM]
+int amp, amp2, x, y, line, junk
+pointer ibuf, obuf, ptr
+
+int imgnls(), impnls()
+
+begin
+ # Setup start vectors for sequential reads ...
+ do amp = 1, QG_NAMPS (qg)
+ call amovkl (long(1), ivec[1, amp], IM_MAXDIM)
+ # ... and writes
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPSY(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = impnls (out, obuf, ovec)
+ ptr = obuf
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ junk = imgnls (in[amp], ibuf, ivec[1, amp])
+ call amovs (Mems[ibuf], Mems[ptr], QG_NX(qg, amp))
+ ptr = ptr + QG_NX(qg, amp)
+ }
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/qstatistics.cl b/noao/imred/quadred/src/quad/qstatistics.cl
new file mode 100644
index 00000000..a20f373f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qstatistics.cl
@@ -0,0 +1,19 @@
+procedure qstatistics (images)
+
+begin
+ string tmp
+
+ tmp = mktemp ("uparm$tmp")
+
+ #quadsections (image, window=window, section="", template="",
+ #xskip1=INDEF, xskip2=INDEF, xtrim1=INDEF, xtrim2=INDEF, ytrim1=INDEF,
+ #ytrim2=INDEF, >> tmp)
+ quadsections (image, window=window, section="", template="", >> tmp)
+
+ # Calculate image statistics
+ imstatistics ("@"//tmp, fields=fields, lower=lower, upper=upper,
+ binwidth=binwidth, format=format)
+
+
+ delete (tmp, ver-)
+end
diff --git a/noao/imred/quadred/src/quad/qstatistics.par b/noao/imred/quadred/src/quad/qstatistics.par
new file mode 100644
index 00000000..92a32f66
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qstatistics.par
@@ -0,0 +1,7 @@
+images,s,a,,,,Images
+window,s,h,"datasec","|datasec|trimsec|biassec|reflect|duplicate|",,Window to apply to image
+fields,s,h,"image,npix,mean,stddev,min,max",,,Fields to be printed
+lower,r,h,INDEF,,,Lower cutoff for pixel values
+upper,r,h,INDEF,,,Upper cutoff for pixel values
+binwidth,r,h,0.1,,,Bin width of histogram in sigma
+format,b,h,yes,,,Format output and print column labels?
diff --git a/noao/imred/quadred/src/quad/quad.cl b/noao/imred/quadred/src/quad/quad.cl
new file mode 100644
index 00000000..b08434c0
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quad.cl
@@ -0,0 +1,64 @@
+#{ QUAD -- Quad CCD reduction package
+
+noao
+imred
+
+set ccddb = "quad$ccddb/"
+set quadtest = "quad$quadtest/"
+
+package quad
+
+task quadtest.pkg = "quadtest$quadtest.cl"
+
+task quadsplit,
+ quadjoin,
+ quadscale,
+ quadsections,
+ ccddelete,
+ ccdprcselect,
+ ccdssselect,
+ ccdsection,
+ qpcalimage,
+ qpselect,
+ irlincor,
+ gainmeasure,
+# ccdgetparam = "quad$xx_quad.e"
+ ccdgetparam = "quad$x_quad.e"
+
+task quadproc = "quad$quadproc.cl"
+task qproc = "quad$qproc.cl"
+task qnoproc = "quad$qnoproc.cl"
+task qstatistics = "quad$qstatistics.cl"
+task qhistogram = "quad$qhistogram.cl"
+
+hidetask ccdgetparam, ccddelete, ccdprcselect, ccdssselect, ccdsection
+hidetask qpcalimage, qpselect, qproc, qnoproc, quadsplit, quadjoin, quadsections
+
+# CCDRED tasks.
+task badpiximage,
+ ccdgroups,
+ ccdhedit,
+ ccdinstrument,
+ ccdlist,
+ combine,
+ cosmicrays = ccdred$x_ccdred.e
+# cosmicrays,
+# mkfringecor,
+# mkillumcor,
+# mkillumflat,
+# mkskycor,
+# mkskyflat = ccdred$x_ccdred.e
+
+task setinstrument = quad$setinstrument.cl
+
+# Different default parameters
+task qccdproc = quad$x_ccdred.e
+
+# Special versions which run quadproc rather than ccdproc
+task darkcombine = quad$darkcombine.cl
+task flatcombine = quad$flatcombine.cl
+task zerocombine = quad$zerocombine.cl
+
+hidetask ccdproc
+
+clbye()
diff --git a/noao/imred/quadred/src/quad/quad.hd b/noao/imred/quadred/src/quad/quad.hd
new file mode 100644
index 00000000..b8526c66
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quad.hd
@@ -0,0 +1,33 @@
+# Help directory for the QUAD package.
+
+$defdir = "quad$"
+$doc = "quad$doc/"
+
+badpiximage hlp=doc$badpiximage.hlp
+ccdgroups hlp=doc$ccdgroups.hlp
+ccdhedit hlp=doc$ccdhedit.hlp
+ccdlist hlp=doc$ccdlist.hlp
+combine hlp=doc$combine.hlp
+cosmicrays hlp=doc$cosmicrays.hlp
+darkcombine hlp=doc$darkcombine.hlp
+flatcombine hlp=doc$flatcombine.hlp
+mkfringecor hlp=doc$mkfringecor.hlp
+mkillumcor hlp=doc$mkillumcor.hlp
+mkillumflat hlp=doc$mkillumflat.hlp
+mkskycor hlp=doc$mkskycor.hlp
+mkskyflat hlp=doc$mkskyflat.hlp
+quadproc hlp=doc$quadproc.hlp
+quadscale hlp=doc$quadscale.hlp
+qhistogram hlp=doc$qhistogram.hlp
+qstatistics hlp=doc$qstatistics.hlp
+setinstrument hlp=doc$setinstrument.hlp
+zerocombine hlp=doc$zerocombine.hlp
+
+ccdgeometry hlp=doc$ccdgeometry.hlp
+ccdinstrument hlp=doc$ccdinst.hlp
+ccdtypes hlp=doc$ccdtypes.hlp
+flatfields hlp=doc$flatfields.hlp
+guide hlp=doc$guide.hlp
+instruments hlp=doc$instruments.hlp
+package hlp=doc$quad.hlp
+subsets hlp=doc$subsets.hlp
diff --git a/noao/imred/quadred/src/quad/quad.men b/noao/imred/quadred/src/quad/quad.men
new file mode 100644
index 00000000..6b323daf
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quad.men
@@ -0,0 +1,36 @@
+ SPECIAL TASKS FOR MULTI-READOUT CCD IMAGES
+
+ quadproc - Process multi-readout CCD images
+ quadscale -
+ qstatistics - Calculate image statistics for multi-readout CCD images
+ qhistogram - Make histogram of multi-readout CCD image
+ darkcombine - Combine and process dark count images
+ flatcombine - Combine and process flat field images
+ zerocombine - Combine and process zero level images
+
+
+ STANDARD CCDRED TASKS
+
+ badpiximage - Create a bad pixel mask image from a bad pixel file
+ ccdgroups - Group CCD images into image lists
+ ccdhedit - CCD image header editor
+ ccdinstrument - Review and edit instrument translation files
+ ccdlist - List CCD processing information
+ combine - Combine CCD images
+ cosmicrays - Detect and replace cosmic rays
+ mkfringecor - Make fringe correction images from sky images
+ mkillumcor - Make flat field illumination correction images
+ mkillumflat - Make illumination corrected flat fields
+ mkskycor - Make sky illumination correction images
+ mkskyflat - Make sky corrected flat field images
+ setinstrument - Set instrument parameters
+
+ ADDITIONAL HELP TOPICS
+
+ ccdgeometry - Discussion of CCD coordinate/geometry keywords
+ ccdtypes - Description of the CCD image types
+ flatfields - Discussion of CCD flat field calibrations
+ guide - Introductory guide to using the CCDRED package
+ instruments - Instrument specific data files
+ package - CCD image reduction package
+ subsets - Description of CCD subsets
diff --git a/noao/imred/quadred/src/quad/quad.par b/noao/imred/quadred/src/quad/quad.par
new file mode 100644
index 00000000..74267f31
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quad.par
@@ -0,0 +1,12 @@
+# QUAD package parameter file
+
+pixeltype,s,h,"real real",,,Output and calculation pixel datatypes
+verbose,b,h,no,,,Print log information to the standard output?
+logfile,f,h,"logfile",,,Text log file
+plotfile,f,h,"",,,Log metacode plot file
+backup,s,h,"",,,Backup directory or prefix
+instrument,s,h,"",,,CCD instrument file
+ssfile,s,h,"subsets",,,Subset translation file
+graphics,s,h,"stdgraph",,,Interactive graphics output device
+cursor,*gcur,h,"",,,Graphics cursor input
+version,s,h,"Version 2.0 - Mar 94","Version 2.0 - Mar 94"
diff --git a/noao/imred/quadred/src/quad/quadalloc.x b/noao/imred/quadred/src/quad/quadalloc.x
new file mode 100644
index 00000000..9373340a
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadalloc.x
@@ -0,0 +1,165 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QUADOPEN -- Allocate space for quadgeom structure
+# Note: The various arrays are dimensioned as QG_MAXAMPS+1 and are ZERO indexed.
+
+procedure quadalloc (qg)
+
+pointer qg #O Pointer to opened quadgeom structure
+
+begin
+
+ call malloc (qg, QG_LENSTRUCT, TY_STRUCT)
+
+ # Zero readout counters
+ QG_NAMPS(qg) = 0
+ QG_NAMPSX(qg) = 0
+ QG_NAMPSY(qg) = 0
+
+ # Allocate and zero arrays.
+ call calloc (QG_AMPIDPTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_AMPTYPTR(qg), QG_MAXAMPS+1, TY_INT)
+
+ call calloc (QG_NXPTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_NYPTR(qg), QG_MAXAMPS+1, TY_INT)
+
+ call calloc (QG_DX1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_DX2PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_DY1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_DY2PTR(qg), QG_MAXAMPS+1, TY_INT)
+
+ call calloc (QG_TX1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_TX2PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_TY1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_TY2PTR(qg), QG_MAXAMPS+1, TY_INT)
+
+ call calloc (QG_BX1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_BX2PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_BY1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_BY2PTR(qg), QG_MAXAMPS+1, TY_INT)
+
+ call calloc (QG_CX1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_CX2PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_CY1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_CY2PTR(qg), QG_MAXAMPS+1, TY_INT)
+
+ call calloc (QG_AX1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_AX2PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_AY1PTR(qg), QG_MAXAMPS+1, TY_INT)
+ call calloc (QG_AY2PTR(qg), QG_MAXAMPS+1, TY_INT)
+
+ call calloc (QG_PHPTR(qg), QG_MAXAMPS+1, TY_INT)
+
+end
+
+# QUADFREE -- Free quadgeom structure
+
+procedure quadfree (qg)
+
+pointer qg #O Pointer to open quadgeom structure
+
+begin
+
+ if (qg != NULL) {
+
+ call mfree (QG_AMPIDPTR(qg), TY_INT)
+ call mfree (QG_AMPTYPTR(qg), TY_INT)
+
+ call mfree (QG_NXPTR(qg), TY_INT)
+ call mfree (QG_NYPTR(qg), TY_INT)
+
+ call mfree (QG_DX1PTR(qg), TY_INT)
+ call mfree (QG_DX2PTR(qg), TY_INT)
+ call mfree (QG_DY1PTR(qg), TY_INT)
+ call mfree (QG_DY2PTR(qg), TY_INT)
+
+ call mfree (QG_TX1PTR(qg), TY_INT)
+ call mfree (QG_TX2PTR(qg), TY_INT)
+ call mfree (QG_TY1PTR(qg), TY_INT)
+ call mfree (QG_TY2PTR(qg), TY_INT)
+
+ call mfree (QG_BX1PTR(qg), TY_INT)
+ call mfree (QG_BX2PTR(qg), TY_INT)
+ call mfree (QG_BY1PTR(qg), TY_INT)
+ call mfree (QG_BY2PTR(qg), TY_INT)
+
+ call mfree (QG_CX1PTR(qg), TY_INT)
+ call mfree (QG_CX2PTR(qg), TY_INT)
+ call mfree (QG_CY1PTR(qg), TY_INT)
+ call mfree (QG_CY2PTR(qg), TY_INT)
+
+ call mfree (QG_AX1PTR(qg), TY_INT)
+ call mfree (QG_AX2PTR(qg), TY_INT)
+ call mfree (QG_AY1PTR(qg), TY_INT)
+ call mfree (QG_AY2PTR(qg), TY_INT)
+
+ call mfree (QG_PHPTR(qg), TY_INT)
+
+ call mfree (qg, TY_STRUCT)
+ }
+end
+
+# QUADDUMP -- Print contents of quadgeom structure on STDERR
+procedure quaddump (qg)
+
+pointer qg #O Pointer to open quadgeom structure
+
+int amp
+
+begin
+
+ call eprintf ("Active amps: %d (%d in x, %d in y)\n")
+ call pargi (QG_NAMPS(qg))
+ call pargi (QG_NAMPSX(qg))
+ call pargi (QG_NAMPSY(qg))
+
+ do amp = 0, QG_NAMPS(qg) {
+ switch (amp) {
+ case 0:
+ call eprintf ("Entire image\n")
+ default:
+ call eprintf ("Amp %s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ if (QG_PHANTOM (qg, amp) == YES)
+ call eprintf (" [Phantom]")
+
+ call eprintf ("\n")
+ }
+
+ call eprintf ("\tnx = %d \tny = %d \n")
+ call pargi (QG_NX(qg, amp))
+ call pargi (QG_NY(qg, amp))
+
+ call eprintf ("\tdx1 = %d \tdx2 = %d \tdy1 = %d \tdy2 = %d\n")
+ call pargi (QG_DX1(qg, amp))
+ call pargi (QG_DX2(qg, amp))
+ call pargi (QG_DY1(qg, amp))
+ call pargi (QG_DY2(qg, amp))
+
+ call eprintf ("\ttx1 = %d \ttx2 = %d \tty1 = %d \tty2 = %d\n")
+ call pargi (QG_TX1(qg, amp))
+ call pargi (QG_TX2(qg, amp))
+ call pargi (QG_TY1(qg, amp))
+ call pargi (QG_TY2(qg, amp))
+
+ call eprintf ("\tbx1 = %d \tbx2 = %d \tby1 = %d \tby2 = %d\n")
+ call pargi (QG_BX1(qg, amp))
+ call pargi (QG_BX2(qg, amp))
+ call pargi (QG_BY1(qg, amp))
+ call pargi (QG_BY2(qg, amp))
+
+ call eprintf ("\tcx1 = %d \tcx2 = %d \tcy1 = %d \tcy2 = %d\n")
+ call pargi (QG_CX1(qg, amp))
+ call pargi (QG_CX2(qg, amp))
+ call pargi (QG_CY1(qg, amp))
+ call pargi (QG_CY2(qg, amp))
+
+ call eprintf ("\tax1 = %d \tax2 = %d \tay1 = %d \tay2 = %d\n")
+ call pargi (QG_AX1(qg, amp))
+ call pargi (QG_AX2(qg, amp))
+ call pargi (QG_AY1(qg, amp))
+ call pargi (QG_AY2(qg, amp))
+ }
+end
diff --git a/noao/imred/quadred/src/quad/quaddelete.x b/noao/imred/quadred/src/quad/quaddelete.x
new file mode 100644
index 00000000..bdee65b2
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quaddelete.x
@@ -0,0 +1,39 @@
+include "quadgeom.h"
+
+# QUADDELETE -- Delete subimages, one for each readout.
+
+procedure quaddelete (qg, rootname)
+
+pointer qg #I Pointer to open quadgeom structure
+char rootname[ARB] #I Root name for subimages.
+
+int amp
+pointer fullname
+
+pointer sp
+int imaccess()
+
+begin
+ call smark (sp)
+ call salloc (fullname, SZ_LINE, TY_CHAR)
+
+ # Loop over active readouts
+ do amp = 1, QG_NAMPS(qg) {
+
+ # The sub-section image will only exist if this is not a phantom
+ if (QG_PHANTOM (qg, amp) == NO) {
+
+ # Make sub-image name
+ call sprintf (Memc[fullname], SZ_LINE, "%s.%s")
+ call pargstr (rootname)
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ # Delete the sub-image (if it exists)
+ if (imaccess (Memc[fullname], READ_ONLY) == YES) {
+ call imdelete (Memc[fullname])
+ }
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/quad/quadgeom.h b/noao/imred/quadred/src/quad/quadgeom.h
new file mode 100644
index 00000000..090b4bf2
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadgeom.h
@@ -0,0 +1,99 @@
+# QUADGEOM - Structure definitions and macros for quadgeom structure.
+
+define QG_LENSTRUCT 28 # Length of structure.
+define QG_MAXAMPS 4 # Maximum possible number of readouts.
+# The various arrays are dimensioned as QG_MAXAMPS+1.
+# QG_AAAA(0) contains quantities refering to the entire image
+# QG_AAAA(z) contains quantities refering to the zth sub-image
+
+define QG_NAMPS Memi[$1] # Total number of active readouts.
+define QG_NAMPSX Memi[$1+1] # Number of active readouts in X.
+define QG_NAMPSY Memi[$1+2] # Number of active readouts in Y.
+
+# Array of pointers to names of active readouts.
+define QG_AMPIDPTR Memi[$1+3] # --> ampid array.
+define QG_AMPID Memi[QG_AMPIDPTR($1)+$2] # ampid array.
+
+# Array of pointers to names of active readouts.
+define QG_AMPTYPTR Memi[$1+4] # --> amptype array.
+define QG_AMPTYPE Memi[QG_AMPTYPTR($1)+$2] # amptype array.
+
+# Dimensions of image from each readout.
+define QG_NXPTR Memi[$1+5] # --> X dimension array.
+define QG_NX Memi[QG_NXPTR($1)+$2] # X dimension.
+define QG_NYPTR Memi[$1+6] # --> Y dimension array.
+define QG_NY Memi[QG_NYPTR($1)+$2] # Y dimension.
+
+# datasec = "[dx1:dx2,dy1:dy2]"
+define QG_DOFF 7
+define QG_DX1PTR Memi[$1+QG_DOFF] # --> dx1 array.
+define QG_DX2PTR Memi[$1+QG_DOFF+1] # --> dx2 array.
+define QG_DY1PTR Memi[$1+QG_DOFF+2] # --> dy1 array.
+define QG_DY2PTR Memi[$1+QG_DOFF+3] # --> dy2 array.
+define QG_DX1 Memi[QG_DX1PTR($1)+$2] # dx1.
+define QG_DX2 Memi[QG_DX2PTR($1)+$2] # dx2.
+define QG_DY1 Memi[QG_DY1PTR($1)+$2] # dy1..
+define QG_DY2 Memi[QG_DY2PTR($1)+$2] # dy2.
+
+# trimsec = "[tx1:tx2,ty1:ty2]"
+define QG_TOFF 11 # QG_DOFF+4.
+define QG_TX1PTR Memi[$1+QG_TOFF] # --> tx1 array.
+define QG_TX2PTR Memi[$1+QG_TOFF+1] # --> tx2 array.
+define QG_TY1PTR Memi[$1+QG_TOFF+2] # --> ty1 array.
+define QG_TY2PTR Memi[$1+QG_TOFF+3] # --> ty2 array.
+define QG_TX1 Memi[QG_TX1PTR($1)+$2] # tx1.
+define QG_TX2 Memi[QG_TX2PTR($1)+$2] # tx2.
+define QG_TY1 Memi[QG_TY1PTR($1)+$2] # ty1.
+define QG_TY2 Memi[QG_TY2PTR($1)+$2] # ty2.
+
+# biassec = "[bx1:bx2,by1:by2]"
+define QG_BOFF 15 # QG_TOFF+4.
+define QG_BX1PTR Memi[$1+QG_BOFF] # --> bx1 array.
+define QG_BX2PTR Memi[$1+QG_BOFF+1] # --> bx2 array.
+define QG_BY1PTR Memi[$1+QG_BOFF+2] # --> by1 array.
+define QG_BY2PTR Memi[$1+QG_BOFF+3] # --> by2 array.
+define QG_BX1 Memi[QG_BX1PTR($1)+$2] # bx1.
+define QG_BX2 Memi[QG_BX2PTR($1)+$2] # bx2.
+define QG_BY1 Memi[QG_BY1PTR($1)+$2] # by1.
+define QG_BY2 Memi[QG_BY2PTR($1)+$2] # by2.
+
+# ccdsec = "[cx1:cx2,cy1:cy2]"
+define QG_COFF 19 # QG_BOFF+4.
+define QG_CX1PTR Memi[$1+QG_COFF] # --> cx1 array.
+define QG_CX2PTR Memi[$1+QG_COFF+1] # --> cx2 array.
+define QG_CY1PTR Memi[$1+QG_COFF+2] # --> cy1 array.
+define QG_CY2PTR Memi[$1+QG_COFF+3] # --> cy2 array.
+define QG_CX1 Memi[QG_CX1PTR($1)+$2] # cx1.
+define QG_CX2 Memi[QG_CX2PTR($1)+$2] # cx2.
+define QG_CY1 Memi[QG_CY1PTR($1)+$2] # cy1.
+define QG_CY2 Memi[QG_CY2PTR($1)+$2] # cy2.
+
+# ampsec = "[ax1:ax2,ay1:ay2]"
+define QG_AOFF 23 # QG_COFF+4.
+define QG_AX1PTR Memi[$1+QG_AOFF] # --> ax1 array.
+define QG_AX2PTR Memi[$1+QG_AOFF+1] # --> ax2 array.
+define QG_AY1PTR Memi[$1+QG_AOFF+2] # --> ay1 array.
+define QG_AY2PTR Memi[$1+QG_AOFF+3] # --> ay2 array.
+define QG_AX1 Memi[QG_AX1PTR($1)+$2] # ax1.
+define QG_AX2 Memi[QG_AX2PTR($1)+$2] # ax2.
+define QG_AY1 Memi[QG_AY1PTR($1)+$2] # ay1.
+define QG_AY2 Memi[QG_AY2PTR($1)+$2] # ay2.
+
+# Phantom markers
+define QG_PHOFF 27 # QG_AOFF+4
+define QG_PHPTR Memi[$1+QG_PHOFF] # --> Phantom array
+define QG_PHANTOM Memi[QG_PHPTR($1)+$2] # Phantom value
+
+# Macros to convert between array offset and grid position
+define QG_GRIDX ($2 - (($2-1)/QG_NAMPSX($1))*QG_NAMPSX($1))
+define QG_GRIDY (($2-1)/QG_NAMPSX($1)+1)
+define QG_AMP ($2 + ($3-1) * QG_NAMPSX($1))
+
+# Symbolic values for AMPTYPE codes
+define AMPDICT "|11|12|21|22|"
+define AMP11 1 # BLHC
+define AMP12 2 # BRHC
+define AMP21 3 # TLHC
+define AMP22 4 # TRHC
+
+define SZ_AMPID 2
diff --git a/noao/imred/quadred/src/quad/quadgeom.x b/noao/imred/quadred/src/quad/quadgeom.x
new file mode 100644
index 00000000..3ce173ff
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadgeom.x
@@ -0,0 +1,304 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QUADGEOM -- Set up section information in quadgeom structure based on
+# information in the image header. The sections given in the image header are
+# "whole image" sections (i.e. those that would be appropriate for single
+# readout. From these we must calculate the sections to apply to the data
+# read through each readout. The values of datasec and ccdsec are taken from
+# the header. The values of trimsec and biassec can be supplied explicitly
+# via the corresponding arguments. If these are given as "image" or "" then the
+# image header values are used.
+
+procedure quadgeom (im, qg, trimsec, biassec)
+
+pointer im #I Pointer to input image.
+pointer qg #IO Pointer to open quadgeom structure.
+char trimsec[SZ_LINE] #I Trimsec may be used to overide header value.
+char biassec[SZ_LINE] #I Biassec may be used to overide header value.
+
+char section[SZ_LINE], nampsyx[SZ_LINE]
+int nx, ny, xdata, ydata, xover, yover, amp, xamp, yamp, pre
+int dx1, dx2, dxs, dy1, dy2, dys
+int ddx1, ddx2, ddy1, ddy2
+int cx1, cx2, cxs, cy1, cy2, cys
+int ccx1, ccx2, ccy1, ccy2
+int tx1, tx2, txs, txskip1, txskip2
+int ty1, ty2, tys, tyskip1, tyskip2
+int ttx1, ttx2, tty1, tty2
+int bx1, bx2, bxs, bxskip1, bxskip2
+int by1, by2, bys, byskip1, byskip2
+int bbx1, bbx2, bby1, bby2
+
+bool streq()
+
+begin
+
+ # Get input image dimensions.
+ nx = IM_LEN(im, 1)
+ ny = IM_LEN(im, 2)
+
+ # Get number of active amplifiers in Y and X.
+ call hdmgstr (im, "nampsyx", nampsyx, SZ_LINE)
+ call sscan (nampsyx)
+ call gargi (QG_NAMPSY(qg))
+ call gargi (QG_NAMPSX(qg))
+
+ QG_NAMPS(qg) = QG_NAMPSY(qg) * QG_NAMPSX(qg)
+ if (QG_NAMPS(qg) > QG_MAXAMPS)
+ call error (0, "CCD has two many read-outs for this program")
+
+ # Get list of active amplifiers.
+ # Presently the header doesn't contain this information so we fake it
+ # since we know all the posibilities.
+ do amp = 1, QG_NAMPS(qg)
+ call malloc (QG_AMPID(qg, amp), SZ_AMPID, TY_CHAR)
+
+ switch (QG_NAMPSX(qg)) {
+ case 1:
+ switch (QG_NAMPSY(qg)) {
+ case 1: # Mono
+ QG_AMPTYPE (qg, 1) = AMP11
+ call strcpy ("11", Memc[QG_AMPID(qg, 1)], SZ_AMPID)
+
+ case 2: # Split parallels
+ call error (0, "Unsuported read-out configuration")
+ }
+
+ case 2:
+
+ switch (QG_NAMPSY(qg)) {
+ case 1: # Split serials
+ QG_AMPTYPE (qg, 1) = AMP11
+ call strcpy ("11", Memc[QG_AMPID(qg, 1)], SZ_AMPID)
+ QG_AMPTYPE (qg, 2) = AMP12
+ call strcpy ("12", Memc[QG_AMPID(qg, 2)], SZ_AMPID)
+
+ case 2: # Quad
+ QG_AMPTYPE (qg, 1) = AMP11
+ call strcpy ("11", Memc[QG_AMPID(qg, 1)], SZ_AMPID)
+ QG_AMPTYPE (qg, 2) = AMP12
+ call strcpy ("12", Memc[QG_AMPID(qg, 2)], SZ_AMPID)
+ QG_AMPTYPE (qg, 3) = AMP21
+ call strcpy ("21", Memc[QG_AMPID(qg, 3)], SZ_AMPID)
+ QG_AMPTYPE (qg, 4) = AMP22
+ call strcpy ("22", Memc[QG_AMPID(qg, 4)], SZ_AMPID)
+ }
+ }
+
+ # Set X and Y dimensions of subimage read out by each amplifier
+ QG_NX (qg, 0) = nx
+ QG_NY (qg, 0) = ny
+ do amp = 1, QG_NAMPS (qg) {
+ QG_NX(qg, amp) = nx / QG_NAMPSX (qg)
+ QG_NY(qg, amp) = ny / QG_NAMPSY (qg)
+ }
+
+ # Get datasec, trimsec and biassec parameters from image header.
+ # trimsec and biassec may be overidden by supplying an explicit
+ # section in the biassec and trimsec arguments.
+ call hdmgstr (im, "datasec", section, SZ_LINE)
+ dx1 = 1
+ dx2 = nx
+ dxs = 1
+ dy1 = 1
+ dy2 = ny
+ dys = 1
+ call ccd_section (section, dx1, dx2, dxs, dy1, dy2, dys)
+ QG_DX1(qg, 0) = dx1
+ QG_DX2(qg, 0) = dx2
+ QG_DY1(qg, 0) = dy1
+ QG_DY2(qg, 0) = dy2
+
+ if (streq (trimsec, "image") || streq (trimsec, "")) {
+ call hdmgstr (im, "trimsec", section, SZ_LINE)
+ } else {
+ call strcpy (trimsec, section, SZ_LINE)
+ }
+ tx1 = dx1
+ tx2 = dx2
+ txs = 1
+ ty1 = dy1
+ ty2 = dy2
+ tys = 1
+ call ccd_section (section, tx1, tx2, txs, ty1, ty2, tys)
+ QG_TX1(qg, 0) = tx1
+ QG_TX2(qg, 0) = tx2
+ QG_TY1(qg, 0) = ty1
+ QG_TY2(qg, 0) = ty2
+
+ if (streq (biassec, "image") || streq (biassec, "")) {
+ call hdmgstr (im, "biassec", section, SZ_LINE)
+ } else {
+ call strcpy (biassec, section, SZ_LINE)
+ }
+ bx1 = dx2 + 1
+ bx2 = nx
+ bxs = 1
+ by1 = 1
+ by2 = ny
+ bys = 1
+ call ccd_section (section, bx1, bx2, bxs, by1, by2, bys)
+ QG_BX1(qg, 0) = bx1
+ QG_BX2(qg, 0) = bx2
+ QG_BY1(qg, 0) = by1
+ QG_BY2(qg, 0) = by2
+
+ call hdmgstr (im, "ccdsec", section, SZ_LINE)
+ cx1 = dx1
+ cx2 = dx2
+ cxs = 1
+ cy1 = dy1
+ cy2 = dy2
+ cys = 1
+ call ccd_section (section, cx1, cx2, cxs, cy1, cy2, cys)
+ QG_CX1(qg, 0) = cx1
+ QG_CX2(qg, 0) = cx2
+ QG_CY1(qg, 0) = cy1
+ QG_CY2(qg, 0) = cy2
+
+ # Calculate number of data pixels and margins to leave around
+ # trimsection.
+ xdata = dx2 - dx1 + 1
+ ydata = dy2 - dy1 + 1
+ txskip1 = tx1 - dx1
+ # ************* KLUDGE! *********************
+ # The datasec is the whole image. We have no way of knowing where the
+ # division between data and overscan is supposed to be so we assume
+ # that trimsec leaves an equal margin on both sides of the true datasec.
+ if ((dx1 == 1 ) && (dx2 == nx)) {
+ dx2 = tx2 + txskip1
+ xdata = dx2 - dx1 + 1
+ cx2 = cx1 + xdata - 1
+ QG_DX2(qg, 0) = dx2
+ QG_CX2(qg, 0) = cx2
+ }
+ txskip2 = dx2 - tx2
+ tyskip1 = ty1 - dy1
+ tyskip2 = dy2 - ty2
+
+ # Calculate number of overscan pixels and margins to leave around
+ # biassec.
+ xover = nx - xdata
+ yover = ny
+ bxskip1 = bx1 - dx2 - 1
+ bxskip2 = nx - bx2
+ byskip1 = by1 - dy1
+ byskip2 = ny - by2
+
+ # Calculate number of data and overscan pixels in subimages
+ xdata = xdata / QG_NAMPSX(qg)
+ ydata = ydata / QG_NAMPSY(qg)
+ xover = xover / QG_NAMPSX(qg)
+ yover = yover / QG_NAMPSY(qg)
+
+ # Calculate datasec, trimsec, etc. for each amplifier
+ do amp = 1, QG_NAMPS(qg) {
+
+ # Assume there are no phantoms
+ QG_PHANTOM (qg, amp) = NO
+
+ # X coordinates
+ switch (QG_AMPTYPE(qg, amp)) {
+ case AMP11, AMP21: # Left hand side
+ ddx1 = dx1
+ ddx2 = ddx1 + xdata - 1
+ ttx1 = ddx1 + txskip1
+ ttx2 = ddx2
+ bbx1 = ddx2 + bxskip1 + 1
+ bbx2 = ddx2 + xover - bxskip2
+ ccx1 = cx1
+ ccx2 = cx1 + xdata - 1
+
+ case AMP12, AMP22: # Right hand side
+ bbx1 = bxskip2 + 1
+ bbx2 = xover - bxskip1
+ ddx1 = xover + 1
+ ddx2 = ddx1 + xdata - 1
+ ttx1 = ddx1
+ ttx2 = ddx2 - txskip2
+ ccx1 = cx1 + xdata
+ ccx2 = cx2
+ }
+
+ # Y Coordinates
+ switch (QG_AMPTYPE(qg, amp)) {
+ case AMP11, AMP12: # Lower row
+ ddy1 = dy1
+ ddy2 = ddy1 + ydata - 1
+ tty1 = ddy1 + tyskip1
+ bby1 = ddy1 + byskip1
+ if (QG_NAMPSY(qg) == 1) {
+ tty2 = ddy2 - tyskip2
+ bby2 = ddy2 - byskip2
+ } else {
+ tty2 = ddy2
+ bby2 = ddy2
+ }
+ ccy1 = cy1
+ ccy2 = cy1 + ydata - 1
+
+ case AMP21, AMP22: # Upper row
+ ddy1 = 1
+ ddy2 = ddy1 + ydata - 1
+ if (QG_NAMPSY(qg) == 1) {
+ tty1 = ddy1 + tyskip1
+ bby1 = ddy1 + byskip1
+ } else {
+ tty1 = 1
+ bby1 = 1
+ }
+ tty2 = ddy2 - tyskip2
+ bby2 = ddy2 - byskip2
+ ccy1 = cy1 + ydata
+ ccy2 = cy2
+ }
+
+
+ QG_DX1(qg, amp) = ddx1
+ QG_DX2(qg, amp) = ddx2
+ QG_DY1(qg, amp) = ddy1
+ QG_DY2(qg, amp) = ddy2
+
+ QG_TX1(qg, amp) = ttx1
+ QG_TX2(qg, amp) = ttx2
+ QG_TY1(qg, amp) = tty1
+ QG_TY2(qg, amp) = tty2
+
+ QG_BX1(qg, amp) = bbx1
+ QG_BX2(qg, amp) = bbx2
+ QG_BY1(qg, amp) = bby1
+ QG_BY2(qg, amp) = bby2
+
+ QG_CX1(qg, amp) = ccx1
+ QG_CX2(qg, amp) = ccx2
+ QG_CY1(qg, amp) = ccy1
+ QG_CY2(qg, amp) = ccy2
+ }
+
+ # Set up "ampsec" - the section of the composite image derived from
+ # each sub-image.
+ do yamp = 1, QG_NAMPSY(qg) {
+ amp = QG_AMP (qg, 1, yamp)
+ QG_AX1(qg, amp) = 1
+ QG_AX2(qg, amp) = QG_NX(qg, amp)
+ do xamp = 2, QG_NAMPSX(qg) {
+ amp = QG_AMP (qg, xamp, yamp)
+ pre = QG_AMP (qg, xamp-1, yamp)
+ QG_AX1(qg, amp) = QG_AX2(qg, pre) + 1
+ QG_AX2(qg, amp) = QG_AX1(qg, amp) + QG_NX(qg, amp) - 1
+ }
+ }
+ do xamp = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP (qg, xamp, 1)
+ QG_AY1(qg, amp) = 1
+ QG_AY2(qg, amp) = QG_NY(qg, amp)
+ do yamp = 2, QG_NAMPSY(qg) {
+ amp = QG_AMP (qg, xamp, yamp)
+ pre = QG_AMP (qg, xamp, yamp-1)
+ QG_AY1(qg, amp) = QG_AY2(qg, pre) + 1
+ QG_AY2(qg, amp) = QG_AY1(qg, amp) + QG_NY(qg, amp) - 1
+ }
+ }
+
+end
diff --git a/noao/imred/quadred/src/quad/quadgeomred.x b/noao/imred/quadred/src/quad/quadgeomred.x
new file mode 100644
index 00000000..ff5d043c
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadgeomred.x
@@ -0,0 +1,165 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QUADGEOMRED -- Set up section information in quadgeom structure based on
+# information in the image header for a reduced image. The sections given in the
+# image header are "whole image" sections (i.e. those that would be appropriate
+# for single readout. From these we must calculate the sections to apply to
+# the data read through each readout.
+
+procedure quadgeomred (im, qg)
+
+pointer im #I Pointer to input image.
+pointer qg #IO Pointer to open quadgeom structure.
+
+char section[SZ_LINE], keyword[SZ_LINE], nampsyx[SZ_LINE]
+int nx, ny, x, y, amp, pre
+int dx1, dx2, dxs, dy1, dy2, dys
+int cx1, cx2, cxs, cy1, cy2, cys
+int ax1, ax2, axs, ay1, ay2, ays
+
+begin
+
+ # Get input image dimensions.
+ nx = IM_LEN(im, 1)
+ ny = IM_LEN(im, 2)
+ QG_NX (qg, 0) = nx
+ QG_NY (qg, 0) = ny
+
+ # Get number of active amplifiers in Y and X.
+ call hdmgstr (im, "nampsyx", nampsyx, SZ_LINE)
+ call sscan (nampsyx)
+ call gargi (QG_NAMPSY(qg))
+ call gargi (QG_NAMPSX(qg))
+
+ QG_NAMPS(qg) = QG_NAMPSY(qg) * QG_NAMPSX(qg)
+ if (QG_NAMPS(qg) > QG_MAXAMPS)
+ call error (0, "CCD has two many read-outs for this program")
+
+ # Get list of active amplifiers.
+ # Presently the header doesn't contain this information so we fake it
+ # since we know all the posibilities.
+ do amp = 1, QG_NAMPS(qg)
+ call malloc (QG_AMPID(qg, amp), SZ_AMPID, TY_CHAR)
+
+ switch (QG_NAMPSX(qg)) {
+ case 1:
+ switch (QG_NAMPSY(qg)) {
+ case 1: # Mono
+ QG_AMPTYPE (qg, 1) = AMP11
+ call strcpy ("11", Memc[QG_AMPID(qg, 1)], SZ_AMPID)
+
+ case 2: # Split parallels
+ call error (0, "Unsuported read-out configuration")
+ }
+
+ case 2:
+
+ switch (QG_NAMPSY(qg)) {
+ case 1: # Split serials
+ QG_AMPTYPE (qg, 1) = AMP11
+ call strcpy ("11", Memc[QG_AMPID(qg, 1)], SZ_AMPID)
+ QG_AMPTYPE (qg, 2) = AMP12
+ call strcpy ("12", Memc[QG_AMPID(qg, 2)], SZ_AMPID)
+
+ case 2: # Quad
+ QG_AMPTYPE (qg, 1) = AMP11
+ call strcpy ("11", Memc[QG_AMPID(qg, 1)], SZ_AMPID)
+ QG_AMPTYPE (qg, 2) = AMP12
+ call strcpy ("12", Memc[QG_AMPID(qg, 2)], SZ_AMPID)
+ QG_AMPTYPE (qg, 3) = AMP21
+ call strcpy ("21", Memc[QG_AMPID(qg, 3)], SZ_AMPID)
+ QG_AMPTYPE (qg, 4) = AMP22
+ call strcpy ("22", Memc[QG_AMPID(qg, 4)], SZ_AMPID)
+ }
+ }
+
+
+ # Get datasec.
+ call hdmgstr (im, "datasec", section, SZ_LINE)
+ dx1 = 1
+ dx2 = nx
+ dxs = 1
+ dy1 = 1
+ dy2 = ny
+ dys = 1
+ call ccd_section (section, dx1, dx2, dxs, dy1, dy2, dys)
+ QG_DX1(qg, 0) = dx1
+ QG_DX2(qg, 0) = dx2
+ QG_DY1(qg, 0) = dy1
+ QG_DY2(qg, 0) = dy2
+
+ # Get ccdsec.
+ call hdmgstr (im, "ccdsec", section, SZ_LINE)
+ cx1 = dx1
+ cx2 = dx2
+ cxs = 1
+ cy1 = dy1
+ cy2 = dy2
+ cys = 1
+ call ccd_section (section, cx1, cx2, cxs, cy1, cy2, cys)
+ QG_CX1(qg, 0) = cx1
+ QG_CX2(qg, 0) = cx2
+ QG_CY1(qg, 0) = cy1
+ QG_CY2(qg, 0) = cy2
+
+
+ do amp = 1, QG_NAMPS (qg) {
+
+ # Get AMPSECmn for each readout
+ call sprintf (keyword, SZ_LINE, "AMPSEC%s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ call hdmgstr (im, keyword, section, SZ_LINE)
+ ax1 = 1
+ ax2 = nx
+ axs = 1
+ ay1 = 1
+ ay2 = ny
+ ays = 1
+ call ccd_section (section, ax1, ax2, axs, ay1, ay2, ays)
+ QG_AX1(qg, amp) = ax1
+ QG_AX2(qg, amp) = ax2
+ QG_AY1(qg, amp) = ay1
+ QG_AY2(qg, amp) = ay2
+
+
+ # Set X and Y dimensions of subimage read out by each amplifier
+ QG_NX(qg, amp) = ax2 - ax1 + 1
+ QG_NY(qg, amp) = ay2 - ay1 + 1
+
+ # Set datsec and trimsec for each sub image
+ QG_DX1(qg, amp) = 1
+ QG_DX2(qg, amp) = QG_NX(qg, amp)
+ QG_DY1(qg, amp) = 1
+ QG_DY2(qg, amp) = QG_NY(qg, amp)
+
+ QG_TX1(qg, amp) = 1
+ QG_TX2(qg, amp) = QG_NX(qg, amp)
+ QG_TY1(qg, amp) = 1
+ QG_TY2(qg, amp) = QG_NY(qg, amp)
+ }
+
+ # Determine ccdsec for each each sub-image.
+ do y = 1, QG_NAMPSY(qg) {
+ amp = QG_AMP (qg, 1, y)
+ QG_CX1(qg, amp) = QG_CX1(qg, 0)
+ QG_CX2(qg, amp) = QG_CX1(qg, amp) + QG_NX(qg, amp) - 1
+ do x = 2, QG_NAMPSX(qg) {
+ amp = QG_AMP (qg, x, y)
+ pre = QG_AMP (qg, x-1, y)
+ QG_CX1(qg, amp) = QG_CX2(qg, pre) + 1
+ QG_CX2(qg, amp) = QG_CX1(qg, amp) + QG_NX(qg, amp) - 1
+ }
+ }
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP (qg, x, 1)
+ QG_CY1(qg, amp) = QG_CY1(qg, 0)
+ QG_CY2(qg, amp) = QG_CY1(qg, amp) + QG_NY(qg, amp) - 1
+ do y = 2, QG_NAMPSY(qg) {
+ amp = QG_AMP (qg, x, y)
+ pre = QG_AMP (qg, x, y-1)
+ QG_CY1(qg, amp) = QG_CY2(qg, pre) + 1
+ QG_CY2(qg, amp) = QG_CY1(qg, amp) + QG_NY(qg, amp) - 1
+ }
+ }
+end
diff --git a/noao/imred/quadred/src/quad/quadjoin.par b/noao/imred/quadred/src/quad/quadjoin.par
new file mode 100644
index 00000000..8ebf6582
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadjoin.par
@@ -0,0 +1,4 @@
+input,s,a,"",,,Input root name
+output,s,h,"",,,"Output image name
+"
+delete,b,h,yes,,,"Delete sub-images on completion"
diff --git a/noao/imred/quadred/src/quad/quadjoin.x b/noao/imred/quadred/src/quad/quadjoin.x
new file mode 100644
index 00000000..0ef94394
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadjoin.x
@@ -0,0 +1,638 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+procedure t_quadjoin ()
+
+char input[SZ_FNAME] #TI Input image root name.
+char output[SZ_FNAME] #TI Output image name.
+char instrument[SZ_FNAME] #TI Instrument translation file.
+bool delete #TI delete sub-images when done.
+
+int namps, amp
+pointer in[QG_MAXAMPS], out, qg
+char logstr[SZ_LINE]
+bool inplace
+
+pointer immap()
+int quadmap(), imaccess()
+bool streq(), clgetb()
+
+errchk ccddelete()
+
+begin
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Get input image name and output image names.
+ call clgstr ("input", input, SZ_FNAME)
+ call xt_imroot (input, input, SZ_FNAME)
+ call clgstr ("output", output, SZ_FNAME)
+
+ # If the output name is null the opperation is "done in place one
+ # removed". That is:
+ # the sub-images are combined to form a temporary image
+ # the ORIGINAL PARENT IMAGE is deleted or copied to a backup image
+ # the temporary image is renamed to the original parent image
+ #
+ if (streq (output, "")) {
+ call mktemp ("tmp", output, SZ_FNAME)
+ inplace = true
+ } else {
+ inplace = false
+ }
+
+ # Get delete sub-image flag
+ delete = clgetb ("delete")
+
+ # Allocate quadgeom structure
+ call quadalloc (qg)
+
+ # Open input sub-images
+ namps = quadmap (input, READ_ONLY, false, 0, qg, in)
+
+# call quaddump (qg)
+
+ # Open output image
+ out = immap (output, NEW_COPY, in[1])
+
+ # Merge header information to form header for composite image.
+# call quadjoinhdr (in, out, qg)
+ call quadjoinhdr2 (in, out, qg)
+
+ switch (IM_PIXTYPE(out)) {
+ case TY_USHORT, TY_SHORT:
+ call qjoins (in, out, qg)
+
+ case TY_INT:
+ call qjoini (in, out, qg)
+
+ case TY_LONG:
+ call qjoinl (in, out, qg)
+
+ case TY_REAL:
+ call qjoinr (in, out, qg)
+
+ case TY_DOUBLE:
+ call qjoind (in, out, qg)
+
+ default:
+ call error (1, "unsupported pixel datatype")
+ }
+
+ # Log opperation
+ if (QG_NAMPSX(qg) == 2 && QG_NAMPSY(qg) == 2) {
+ call sprintf (logstr, SZ_LINE, "Quad-readout image")
+ } else if (QG_NAMPSX(qg) == 2 || QG_NAMPSY(qg) == 2) {
+ call sprintf (logstr, SZ_LINE, "Dual-readout image: nampsx=%d nampsy=%d")
+ call pargi (QG_NAMPSX(qg))
+ call pargi (QG_NAMPSY(qg))
+ } else {
+ call sprintf (logstr, SZ_LINE, "Single-readout image")
+ }
+ call timelog (logstr, SZ_LINE)
+ call ccdlog (input, logstr)
+
+ # Tidy up
+ call imunmap (out)
+ do amp = 1, namps
+ call imunmap (in[amp])
+
+ # Delete sub-images
+ if (delete)
+ call quaddelete (qg, input)
+
+ if (inplace) {
+ # Replace the input by the output image.
+ if (imaccess (input, READ_ONLY) == YES) {
+ iferr (call ccddelete (input)) {
+ call imdelete (output)
+ call error (0, "Can't delete or make backup of original image")
+ }
+ }
+ call imrename (output, input)
+ }
+
+ call quadfree (qg)
+ call hdmclose ()
+end
+
+# Merge header information and write to header of output image.
+
+procedure quadjoinhdr (in, out, qg)
+
+pointer in[ARB] #I Pointer to input sub-images.
+pointer out #I Pointer to output image.
+pointer qg #I Pointer to quadgeom structure.
+
+char keyword[SZ_LINE], section[SZ_LINE], buffer[SZ_LINE]
+real rval, ccdmean
+int amp, brk
+
+int hdmaccf(), strsearch()
+real hdmgetr()
+
+begin
+ # Set image dimensions
+ IM_LEN (out, 1) = QG_NX(qg, 0)
+ IM_LEN (out, 2) = QG_NY(qg, 0)
+
+ # Add defined sections to output image header.
+ if ((QG_DX1 (qg, 0) != 0) && (hdmaccf (out, "trim") == NO)) {
+ call sprintf (section, SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_DX1(qg, 0))
+ call pargi (QG_DX2(qg, 0))
+ call pargi (QG_DY1(qg, 0))
+ call pargi (QG_DY2(qg, 0))
+ call hdmpstr (out, "datasec", section)
+
+ call sprintf (section, SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_TX1(qg, 0))
+ call pargi (QG_TX2(qg, 0))
+ call pargi (QG_TY1(qg, 0))
+ call pargi (QG_TY2(qg, 0))
+ call hdmpstr (out, "trimsec", section)
+
+ call sprintf (section, SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_BX1(qg, 0))
+ call pargi (QG_BX2(qg, 0))
+ call pargi (QG_BY1(qg, 0))
+ call pargi (QG_BY2(qg, 0))
+ call hdmpstr (out, "biassec", section)
+ }
+
+ if (QG_CX1 (qg, 0) != 0) {
+ call sprintf (section, SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_CX1(qg, 0))
+ call pargi (QG_CX2(qg, 0))
+ call pargi (QG_CY1(qg, 0))
+ call pargi (QG_CY2(qg, 0))
+ call hdmpstr (out, "ccdsec", section)
+ }
+
+ # Set AMPSECnm
+ do amp = 1, QG_NAMPS(qg) {
+ call sprintf (keyword, SZ_LINE, "ampsec%s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ call sprintf (section, SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_AX1(qg, amp))
+ call pargi (QG_AX2(qg, amp))
+ call pargi (QG_AY1(qg, amp))
+ call pargi (QG_AY2(qg, amp))
+
+ call hdmpstr (out, keyword, section)
+ }
+
+ # Tidy up processing history
+ if (hdmaccf (out, "trim") == YES) {
+ do amp = 1, QG_NAMPS(qg)
+ call mergehist (in[amp], out, "trim", Memc[QG_AMPID(qg, amp)])
+ call hdmdelf (out, "trim")
+ call strcpy ("Trimmed", buffer, SZ_LINE)
+ call timelog (buffer, SZ_LINE)
+ call hdmpstr (out, "trim", buffer)
+ }
+
+ if (hdmaccf (out, "overscan") == YES) {
+ do amp = 1, QG_NAMPS(qg)
+ call mergehist (in[amp], out, "overscan", Memc[QG_AMPID(qg, amp)])
+ call hdmdelf (out, "overscan")
+ call strcpy ("Overscan corrected", buffer, SZ_LINE)
+ call timelog (buffer, SZ_LINE)
+ call hdmpstr (out, "overscan", buffer)
+ }
+
+ if (hdmaccf (out, "ccdmean") == YES) {
+ ccdmean = 0.0
+ do amp = 1, QG_NAMPS(qg) {
+ rval = hdmgetr (in[amp], "ccdmean")
+ ccdmean = ccdmean + rval
+ call sprintf (keyword, SZ_LINE, "ccdmea%s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ call hdmputr (out, keyword, rval)
+ }
+ ccdmean = ccdmean / QG_NAMPS(qg)
+ call hdmdelf (out, "ccdmean")
+ call hdmputr (out, "ccdmean", ccdmean)
+ }
+
+ # Move CCDPROC keyword to end of header
+ if (hdmaccf (out, "ccdproc") == YES) {
+ call hdmgstr (in, "ccdproc", buffer, SZ_LINE)
+ call hdmdelf (out, "ccdproc")
+ brk = strsearch (buffer, "CCD")
+ if (brk !=0)
+ call strcpy (buffer[brk-3], buffer, SZ_LINE)
+ call timelog (buffer, SZ_LINE)
+ call hdmpstr (out, "ccdproc", buffer)
+ }
+end
+
+define SZ_KEYWRD 8 # Number of chars in FITS keyword
+
+define REVSTRING "1.000 09Mar94 (Included amplifier geometry keywords)"
+
+# Merge header information and write to header of output image.
+
+procedure quadjoinhdr2 (in, out, qg)
+
+pointer in[ARB] #I Pointer to input sub-images.
+pointer out #I Pointer to output image.
+pointer qg #I Pointer to quadgeom structure.
+
+pointer sp, keyword, section, buffer
+real rval, ccdmean
+int amp, brk, ch
+
+int ax1, ax2, ay1, ay2
+int bx1, bx2, by1, by2
+int dx1, dx2, dy1, dy2
+int tx1, tx2, ty1, ty2
+
+int hdmaccf(), strsearch()
+real hdmgetr()
+
+begin
+ call smark (sp)
+ call salloc (keyword, SZ_KEYWRD, TY_CHAR)
+ call salloc (section, SZ_LINE, TY_CHAR)
+ call salloc (buffer, SZ_LINE, TY_CHAR)
+
+ # Set image dimensions
+ IM_LEN (out, 1) = QG_NX(qg, 0)
+ IM_LEN (out, 2) = QG_NY(qg, 0)
+
+ # Set the header revision level if not already set.
+ if (hdmaccf (out, "HDR_REV") == NO) {
+ call hdmpstr (out, "HDR_REV", REVSTRING)
+ }
+
+ # Update nampsyx and amplist
+ call sprintf (Memc[buffer], SZ_LINE, "%d %d")
+ call pargi (QG_NAMPSY(qg))
+ call pargi (QG_NAMPSX(qg))
+ call hdmpstr (out, "nampsyx", Memc[buffer])
+
+ ch = 1
+ do amp = 1, QG_NAMPS(qg) {
+ call sprintf (Memc[buffer+ch-1], 3, "%2s ")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ ch = ch + 3
+ }
+ call hdmpstr (out, "amplist", Memc[buffer])
+
+ # Update geometry keywords for each amplifier in the header.
+ # If the corresponding section is undefined any old keywords are deleted
+ # The TSECyx, DSECyx and BSECyx keywords are only retained if the image
+ # has not been trimmed.
+ do amp = 1, QG_NAMPS (qg) {
+
+ # Ampsec (ASECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_LINE, "ASEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ ax1 = QG_AX1 (qg, amp)
+ ax2 = QG_AX2 (qg, amp)
+ ay1 = QG_AY1 (qg, amp)
+ ay2 = QG_AY2 (qg, amp)
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (ax1)
+ call pargi (ax2)
+ call pargi (ay1)
+ call pargi (ay2)
+
+ call hdmpstr (out, Memc[keyword], Memc[section])
+
+ # Biassec (BSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_LINE, "BSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ if ((hdmaccf (out, "trim") == NO) && (QG_BX1 (qg, amp) != 0)) {
+
+
+ bx1 = QG_BX1 (qg, amp) + ax1 - 1
+ bx2 = QG_BX2 (qg, amp) + ax1 - 1
+ by1 = QG_BY1 (qg, amp) + ay1 - 1
+ by2 = QG_BY2 (qg, amp) + ay1 - 1
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (bx1)
+ call pargi (bx2)
+ call pargi (by1)
+ call pargi (by2)
+
+ call hdmpstr (out, Memc[keyword], Memc[section])
+
+ } else if (hdmaccf (out, Memc[keyword]) == YES) {
+
+ call hdmdelf (out, Memc[keyword])
+
+ }
+
+ # CCDsec (CSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_LINE, "CSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ if ((hdmaccf (out, "trim") == NO) && (QG_CX1 (qg, amp) != 0)) {
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_CX1(qg, amp))
+ call pargi (QG_CX2(qg, amp))
+ call pargi (QG_CY1(qg, amp))
+ call pargi (QG_CY2(qg, amp))
+
+ call hdmpstr (out, Memc[keyword], Memc[section])
+
+ } else if (hdmaccf (out, Memc[keyword]) == YES) {
+
+ call hdmdelf (out, Memc[keyword])
+
+ }
+
+ # Datasec (DSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_LINE, "DSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ if ((hdmaccf (out, "trim") == NO) && (QG_DX1 (qg, amp) != 0)) {
+
+ dx1 = QG_DX1 (qg, amp) + ax1 - 1
+ dx2 = QG_DX2 (qg, amp) + ax1 - 1
+ dy1 = QG_DY1 (qg, amp) + ay1 - 1
+ dy2 = QG_DY2 (qg, amp) + ay1 - 1
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (dx1)
+ call pargi (dx2)
+ call pargi (dy1)
+ call pargi (dy2)
+ call hdmpstr (out, Memc[keyword], Memc[section])
+
+ } else if (hdmaccf (out, Memc[keyword]) == YES) {
+
+ call hdmdelf (out, Memc[keyword])
+
+ }
+
+ # Trimsec (TSECyx keyword)
+ #
+ call sprintf (Memc[keyword], SZ_LINE, "TSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+
+ if ((hdmaccf (out, "trim") == NO) && (QG_TX1 (qg, amp) != 0)) {
+
+
+ tx1 = QG_TX1 (qg, amp) + ax1 - 1
+ tx2 = QG_TX2 (qg, amp) + ax1 - 1
+ ty1 = QG_TY1 (qg, amp) + ay1 - 1
+ ty2 = QG_TY2 (qg, amp) + ay1 - 1
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (tx1)
+ call pargi (tx2)
+ call pargi (ty1)
+ call pargi (ty2)
+ call hdmpstr (out, Memc[keyword], Memc[section])
+
+ } else if (hdmaccf (out, Memc[keyword]) == YES) {
+
+ call hdmdelf (out, Memc[keyword])
+
+ }
+
+ }
+
+ # Delete biassec, ccdsec, datasec and trimsec if present.
+ if (hdmaccf (out, "biassec") == YES) {
+ call hdmdelf (out, "biassec")
+ }
+
+ if (hdmaccf (out, "datasec") == YES) {
+ call hdmdelf (out, "datasec")
+ }
+
+ if (hdmaccf (out, "trimsec") == YES) {
+ call hdmdelf (out, "trimsec")
+ }
+
+ if (hdmaccf (out, "ccdsec") == YES) {
+ call hdmdelf (out, "ccdsec")
+ }
+
+ # If image has been trimmed insert CCDSEC for entire image. This is
+ # derived from the CCDSEC's for the sub-images in the BLH and TRH
+ # corners.
+ if (hdmaccf (out, "trim") == YES) {
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_CX1(qg, 1))
+ call pargi (QG_CX2(qg, QG_NAMPS(qg)))
+ call pargi (QG_CY1(qg, 1))
+ call pargi (QG_CY2(qg, QG_NAMPS(qg)))
+
+ call hdmpstr (out, "CCDSEC", Memc[section])
+ }
+
+ # Tidy up processing history as appropriate
+
+ # Overscan Subtraction
+ if (hdmaccf (out, "overscan") == YES) {
+ do amp = 1, QG_NAMPS(qg)
+ call merge_overscan (in[amp], out, Memc[QG_AMPID(qg, amp)])
+
+ call hdmdelf (out, "overscan")
+ call strcpy ("Overscan corrected", Memc[buffer], SZ_LINE)
+ call timelog (Memc[buffer], SZ_LINE)
+ call hdmpstr (out, "overscan", Memc[buffer])
+ }
+
+ # Triming.
+ if (hdmaccf (out, "trim") == YES) {
+
+ do amp = 1, QG_NAMPS(qg)
+ call merge_trim (in[amp], out, Memc[QG_AMPID(qg, amp)])
+
+ call hdmdelf (out, "trim")
+ call strcpy ("Trimmed", Memc[buffer], SZ_LINE)
+ call timelog (Memc[buffer], SZ_LINE)
+ call hdmpstr (out, "trim", Memc[buffer])
+
+ }
+
+ # CCDMEAN
+ if (hdmaccf (out, "ccdmean") == YES) {
+ ccdmean = 0.0
+ do amp = 1, QG_NAMPS(qg) {
+ rval = hdmgetr (in[amp], "ccdmean")
+ ccdmean = ccdmean + rval
+ call sprintf (Memc[keyword], SZ_LINE, "ccdmea%s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ call hdmputr (out, Memc[keyword], rval)
+ }
+ ccdmean = ccdmean / QG_NAMPS(qg)
+ call hdmdelf (out, "ccdmean")
+ call hdmputr (out, "ccdmean", ccdmean)
+ }
+
+ # Move CCDPROC keyword to end of header
+ if (hdmaccf (out, "ccdproc") == YES) {
+ call hdmgstr (in, "ccdproc", Memc[buffer], SZ_LINE)
+ call hdmdelf (out, "ccdproc")
+ brk = strsearch (Memc[buffer], "CCD")
+ if (brk !=0)
+ call strcpy (Memc[buffer+brk-4], Memc[buffer], SZ_LINE)
+ call timelog (Memc[buffer], SZ_LINE)
+ call hdmpstr (out, "ccdproc", Memc[buffer])
+ }
+
+ call sfree (sp)
+end
+
+define OVSC_FMT1 "Overscan section is %s with mean=%g"
+define OVSC_FMT2 "Overscan section is %s"
+define OVSC_FMT3 "Overscan section is %s with function=%s"
+
+procedure merge_overscan (in, out, ampid)
+
+pointer in # Input quadrant image
+pointer out # Output image
+char ampid[2] # Label for readout
+
+pointer sp, buffer, amplifier, biassec, func, rootname, fullname
+real mean
+int idx
+
+int hdmaccf(), stridx(), nscan()
+
+
+begin
+ call smark (sp)
+ call salloc (buffer, SZ_LINE, TY_CHAR)
+ call salloc (amplifier, SZ_LINE, TY_CHAR)
+ call salloc (biassec, SZ_LINE, TY_CHAR)
+ call salloc (func, SZ_LINE, TY_CHAR)
+ call salloc (rootname, SZ_KEYWRD, TY_CHAR)
+ call salloc (fullname, SZ_KEYWRD, TY_CHAR)
+
+ if (hdmaccf (out, "overscan") == YES) {
+
+ # Get BSECyx
+ call sprintf (Memc[fullname], SZ_LINE, "BSEC%2s")
+ call pargstr (ampid)
+ call hdmgstr (in, Memc[fullname], Memc[biassec], SZ_LINE)
+
+ # Get overscan flag and retrieve the mean value if present
+ call hdmgstr (in, "overscan", Memc[buffer], SZ_LINE)
+ idx = stridx ("=", Memc[buffer])
+ if (idx == 0) {
+ call sprintf (Memc[buffer], SZ_LINE, OVSC_FMT2)
+ call pargstr (Memc[biassec])
+
+ } else {
+ call sscan (Memc[buffer+idx])
+ call gargr (mean)
+ if (nscan() == 1) {
+ call sprintf (Memc[buffer], SZ_LINE, OVSC_FMT1)
+ call pargstr (Memc[biassec])
+ call pargr (mean)
+ } else {
+ call strcpy (Memc[buffer+idx], Memc[func], SZ_LINE)
+ call sprintf (Memc[buffer], SZ_LINE, OVSC_FMT3)
+ call pargstr (Memc[biassec])
+ call pargstr (Memc[func])
+ }
+ }
+
+ # Get overscan keyword name and append AMP_ID
+ call hdmname ("overscan", Memc[rootname], 6)
+ call strcpy (Memc[rootname], Memc[fullname], 6)
+ call strcat (ampid, Memc[fullname], SZ_KEYWRD)
+
+ # Write new overscan keyword.
+ call timelog (Memc[buffer], SZ_LINE)
+ call hdmpstr (out, Memc[fullname], Memc[buffer])
+
+ # And record opperation in logfile
+ call sprintf (Memc[amplifier], SZ_LINE, " AMP%s")
+ call pargstr (ampid)
+ call ccdlog (Memc[amplifier], Memc[buffer])
+
+ }
+
+ call sfree (sp)
+end
+
+define TRIM_FMT "Trim data section is %s"
+
+procedure merge_trim (in, out, ampid)
+
+pointer in # Input quadrant image
+pointer out # Output image
+char ampid[2] # Label for readout
+
+pointer sp, buffer, amplifier, trimsec, rootname, fullname
+
+int hdmaccf()
+
+
+begin
+ call smark (sp)
+ call salloc (buffer, SZ_LINE, TY_CHAR)
+ call salloc (amplifier, SZ_LINE, TY_CHAR)
+ call salloc (trimsec, SZ_LINE, TY_CHAR)
+ call salloc (rootname, SZ_KEYWRD, TY_CHAR)
+ call salloc (fullname, SZ_KEYWRD, TY_CHAR)
+
+ if (hdmaccf (out, "trim") == YES) {
+
+ # Get BSECyx
+ call sprintf (Memc[fullname], SZ_LINE, "TSEC%2s")
+ call pargstr (ampid)
+ call hdmgstr (in, Memc[fullname], Memc[trimsec], SZ_LINE)
+
+ call sprintf (Memc[buffer], SZ_LINE, TRIM_FMT)
+ call pargstr (Memc[trimsec])
+
+ # Get overscan keyword name and append AMP_ID
+ call hdmname ("trim", Memc[rootname], 6)
+ call strcpy (Memc[rootname], Memc[fullname], 6)
+ call strcat (ampid, Memc[fullname], SZ_KEYWRD)
+
+ # Write new overscan keyword.
+ call timelog (Memc[buffer], SZ_LINE)
+ call hdmpstr (out, Memc[fullname], Memc[buffer])
+
+ # And record opperation in logfile
+ call sprintf (Memc[amplifier], SZ_LINE, " AMP%s")
+ call pargstr (ampid)
+ call ccdlog (Memc[amplifier], Memc[buffer])
+ }
+
+ call sfree (sp)
+end
+
+procedure mergehist (in, out, keyword, ampid)
+
+pointer in # Input quadrant image
+pointer out # Output image
+char keyword[ARB] # Header keyword to modify
+char ampid[2] # Label for readout
+
+char rootname[6], fullname[8]
+char buffer[SZ_LINE]
+
+int hdmaccf()
+
+begin
+ if (hdmaccf (out, keyword) == YES) {
+ call hdmgstr (in, keyword, buffer, SZ_LINE)
+ call hdmname (keyword, rootname, 6)
+ call strcpy (rootname, fullname, 6)
+ call strcat (ampid, fullname, 8)
+ call hdmpstr (out, fullname, buffer)
+ }
+end
diff --git a/noao/imred/quadred/src/quad/quadmap.x b/noao/imred/quadred/src/quad/quadmap.x
new file mode 100644
index 00000000..db0a052b
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadmap.x
@@ -0,0 +1,297 @@
+include <imhdr.h>
+include <error.h>
+include "quadgeom.h"
+
+# QUADMAP -- Map subimages, one for each readout, for input or output
+
+int procedure quadmap (rootname, mode, clobber, in, qg, out)
+
+char rootname[SZ_FNAME] #I Root name for output images.
+int mode #I Access mode.
+bool clobber #I Clobber existing output images.
+pointer in #I Input image pointer (for NEW_COPY).
+pointer qg #I Pointer to quadgeom structure.
+pointer out[ARB] #O Array of imio pointers for sub-images.
+
+int nopen #O Number of subimages mapped.
+
+int i, j, x, y, nx[QG_MAXAMPS], nampsx, nampsy
+char fullname[SZ_LINE], id[SZ_AMPID]
+
+pointer immap()
+int ahivi(), imaccess()
+
+begin
+ switch (mode) {
+ case NEW_COPY, NEW_IMAGE:
+
+ # Loop over active readouts
+ nopen = 0
+ do i = 1, QG_NAMPS(qg) {
+
+ nopen = nopen + 1
+
+ # The sub-section image need only be written if this is not a
+ # phantom
+ if (QG_PHANTOM (qg, i) == NO) {
+
+ # Make sub-image name
+ call sprintf (fullname, SZ_LINE, "%s.%s")
+ call pargstr (rootname)
+ call pargstr (Memc[QG_AMPID(qg, nopen)])
+
+ # If clobber is set then we can delete any pre-existing
+ # sub-images. Otherwise it is an error if the sub-image already
+ # exists. However we leave it to the immap call to find out.
+ if (clobber) {
+ if (imaccess (fullname, READ_ONLY) == YES)
+ call imdelete (fullname)
+ }
+
+ iferr (out[nopen] = immap (fullname, mode, in)) {
+ nopen = nopen - 1
+ do j = 1, nopen
+ call imunmap (out[j])
+ call erract (EA_ERROR)
+ }
+
+ call quadwritehdr (qg, out[nopen], i)
+
+ } else {
+ out[nopen] = NULL
+ }
+ }
+
+
+ case READ_ONLY, READ_WRITE:
+
+ # Loop over full grid of possible readout positions.
+ nopen = 0
+ do y = 1, QG_MAXAMPS {
+ nx[y] = 0
+ do x = 1, QG_MAXAMPS {
+
+ # Make readout id string
+ call sprintf (id, SZ_AMPID, "%1d%1d")
+ call pargi (y)
+ call pargi (x)
+
+ # Make sub-image name
+ call sprintf (fullname, SZ_LINE, "%s.%s")
+ call pargstr (rootname)
+ call pargstr (id)
+
+ # Attempt to map it.
+ nopen = nopen + 1
+ if (nopen > QG_MAXAMPS) {
+ nopen = nopen - 1
+ next
+ }
+
+ # Skip to next grid position if sub-image does not exist.
+ iferr (out[nopen] = immap (fullname, mode, in)) {
+ nopen = nopen - 1
+ next
+ }
+ nx[y] = nx[y] + 1
+ call quadreadhdr (qg, out[nopen], nopen, id)
+ }
+ }
+
+ nampsx = ahivi (nx, QG_MAXAMPS)
+ nampsy = nopen / nampsx
+ QG_NAMPS(qg) = nopen
+ QG_NAMPSX(qg) = nampsx
+ QG_NAMPSY(qg) = nampsy
+
+ # Consolidate quadgeom structure and perform consistancy checks
+# call quaddump (qg)
+ call quadmerge (qg)
+
+ }
+
+ return (nopen)
+end
+
+# QUADWRITEHDR -- Add dimensions and section information to image header.
+
+procedure quadwritehdr (qg, im, readout)
+
+pointer im #I Pointer to output sub-image image.
+pointer qg #I Pointer to open quadgeom structure.
+int readout #I readout number.
+
+int amp
+pointer sp, section, keyword
+
+int hdmaccf()
+
+begin
+ call smark (sp)
+ call salloc (section, SZ_LINE, TY_CHAR)
+ call salloc (keyword, SZ_LINE, TY_CHAR)
+
+ IM_LEN (im, 1) = QG_NX(qg, readout)
+ IM_LEN (im, 2) = QG_NY(qg, readout)
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_DX1(qg, readout))
+ call pargi (QG_DX2(qg, readout))
+ call pargi (QG_DY1(qg, readout))
+ call pargi (QG_DY2(qg, readout))
+ call hdmpstr (im, "datasec", Memc[section])
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_TX1(qg, readout))
+ call pargi (QG_TX2(qg, readout))
+ call pargi (QG_TY1(qg, readout))
+ call pargi (QG_TY2(qg, readout))
+ call hdmpstr (im, "trimsec", Memc[section])
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_BX1(qg, readout))
+ call pargi (QG_BX2(qg, readout))
+ call pargi (QG_BY1(qg, readout))
+ call pargi (QG_BY2(qg, readout))
+ call hdmpstr (im, "biassec", Memc[section])
+
+ call sprintf (Memc[section], SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (QG_CX1(qg, readout))
+ call pargi (QG_CX2(qg, readout))
+ call pargi (QG_CY1(qg, readout))
+ call pargi (QG_CY2(qg, readout))
+ call hdmpstr (im, "ccdsec", Memc[section])
+
+ # Delete zSECyx keywords for all other amps from header
+ do amp = 1, QG_NAMPS(qg) {
+ if (amp != readout) {
+ call sprintf (Memc[keyword], SZ_LINE, "ASEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ if (hdmaccf (im, Memc[keyword]) == YES)
+ call hdmdelf (im, Memc[keyword])
+
+ call sprintf (Memc[keyword], SZ_LINE, "BSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ if (hdmaccf (im, Memc[keyword]) == YES)
+ call hdmdelf (im, Memc[keyword])
+
+ call sprintf (Memc[keyword], SZ_LINE, "CSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ if (hdmaccf (im, Memc[keyword]) == YES)
+ call hdmdelf (im, Memc[keyword])
+
+ call sprintf (Memc[keyword], SZ_LINE, "DSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ if (hdmaccf (im, Memc[keyword]) == YES)
+ call hdmdelf (im, Memc[keyword])
+
+ call sprintf (Memc[keyword], SZ_LINE, "TSEC%2s")
+ call pargstr (Memc[QG_AMPID(qg, amp)])
+ if (hdmaccf (im, Memc[keyword]) == YES)
+ call hdmdelf (im, Memc[keyword])
+ }
+ }
+
+ call sfree (sp)
+
+end
+
+# QUADREADHDR -- Get dimensions and section information from image header.
+
+procedure quadreadhdr (qg, im, readout, id)
+
+pointer qg #I Pointer to open quadgeom structure.
+pointer im #I Pointer to input sub-image image.
+int readout #I Readout number.
+char id[SZ_AMPID] #I Readout identifier.
+
+int nx, ny
+int dx1, dx2, dxs, dy1, dy2, dys
+int tx1, tx2, txs, ty1, ty2, tys
+int bx1, bx2, bxs, by1, by2, bys
+int cx1, cx2, cxs, cy1, cy2, cys
+pointer sp, section
+
+int hdmaccf(), strdic()
+
+begin
+ call smark (sp)
+ call salloc (section, SZ_LINE, TY_CHAR)
+
+ # Store QG_AMPID and set QG_AMPTYPE
+ call malloc (QG_AMPID(qg, readout), SZ_AMPID, TY_CHAR)
+
+ call strcpy (id, Memc[QG_AMPID(qg, readout)], SZ_AMPID)
+
+ QG_AMPTYPE (qg, readout) = strdic (id, id, SZ_AMPID, AMPDICT)
+
+ # Get input image dimensions.
+ nx = IM_LEN (im, 1)
+ ny = IM_LEN (im, 2)
+ QG_NX(qg, readout) = nx
+ QG_NY(qg, readout) = ny
+
+ # Get datasec, trimsec etc. from image header, setting a null value
+ # for any missing sections.
+ if (hdmaccf (im, "datasec") == YES) {
+ call hdmgstr (im, "datasec", Memc[section], SZ_LINE)
+ dx1 = 1
+ dx2 = nx
+ dxs = 1
+ dy1 = 1
+ dy2 = ny
+ dys = 1
+ call ccd_section (Memc[section], dx1, dx2, dxs, dy1, dy2, dys)
+ }
+ QG_DX1(qg, readout) = dx1
+ QG_DX2(qg, readout) = dx2
+ QG_DY1(qg, readout) = dy1
+ QG_DY2(qg, readout) = dy2
+
+ if (hdmaccf (im, "trimsec") == YES) {
+ call hdmgstr (im, "trimsec", Memc[section], SZ_LINE)
+ tx1 = dx1
+ tx2 = dx2
+ txs = 1
+ ty1 = dy1
+ ty2 = dy2
+ tys = 1
+ call ccd_section (Memc[section], tx1, tx2, txs, ty1, ty2, tys)
+ }
+ QG_TX1(qg, readout) = tx1
+ QG_TX2(qg, readout) = tx2
+ QG_TY1(qg, readout) = ty1
+ QG_TY2(qg, readout) = ty2
+
+ if (hdmaccf (im, "biassec") == YES) {
+ call hdmgstr (im, "biassec", Memc[section], SZ_LINE)
+ bx1 = dx2 + 1
+ bx2 = nx
+ bxs = 1
+ by1 = 1
+ by2 = ny
+ bys = 1
+ call ccd_section (Memc[section], bx1, bx2, bxs, by1, by2, bys)
+ }
+ QG_BX1(qg, readout) = bx1
+ QG_BX2(qg, readout) = bx2
+ QG_BY1(qg, readout) = by1
+ QG_BY2(qg, readout) = by2
+
+ if (hdmaccf (im, "ccdsec") == YES) {
+ call hdmgstr (im, "ccdsec", Memc[section], SZ_LINE)
+ cx1 = dx1
+ cx2 = dx2
+ cxs = 1
+ cy1 = dy1
+ cy2 = dy2
+ cys = 1
+ call ccd_section (Memc[section], cx1, cx2, cxs, cy1, cy2, cys)
+ }
+ QG_CX1(qg, readout) = cx1
+ QG_CX2(qg, readout) = cx2
+ QG_CY1(qg, readout) = cy1
+ QG_CY2(qg, readout) = cy2
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/quad/quadmerge.x b/noao/imred/quadred/src/quad/quadmerge.x
new file mode 100644
index 00000000..ec75d286
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadmerge.x
@@ -0,0 +1,122 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+procedure quadmerge (qg)
+
+pointer qg #I Pointer to quadgeom structure.
+
+int nx, ny, xdata, ydata, txskip1, txskip2, tyskip1, tyskip2
+int bxskip1, bxskip2, byskip1, byskip2
+int x, y, amp, pre, namps, nampsx, nampsy
+
+begin
+ namps = QG_NAMPS(qg)
+ nampsx = QG_NAMPSX(qg)
+ nampsy = QG_NAMPSY(qg)
+
+ # Check consistancy of number of active readouts.
+ if (namps == 0)
+ call error (0, "No input images")
+ if (namps != nampsx * nampsy)
+ call error (0, "Incomplete or inconsistant set of sub-images")
+
+ # Determine dimensions of the composite image.
+ # We just sum the dimensions of the first row and column of sub-images
+ # We should realy check that the sub-images do form a regular grid.
+ nx = 0
+ do x = 1, nampsx {
+ nx = nx + QG_NX(qg, QG_AMP(qg, x, 1))
+ }
+ ny = 0
+ do y = 1, nampsy {
+ ny = ny + QG_NY(qg, QG_AMP(qg, 1, y))
+ }
+ QG_NX(qg, 0) = nx
+ QG_NY(qg, 0) = ny
+
+ # Calculate datasec, trimsec, and biassec, ccdsec for composite image.
+ # The required sections are those for the equivalent mono-readout image.
+ # If datasec is uninitialised assume all these sections are absent as
+ # will be the case for processed [OT] images.
+ if (QG_DX1 (qg, 1) != 0) {
+ # Calculate number of data pixels.
+ xdata = 0
+ do x = 1, nampsx {
+ amp = QG_AMP(qg, x, 1)
+ xdata = xdata + QG_DX2(qg, amp) - QG_DX1(qg, amp) + 1
+ }
+ ydata = 0
+ do y = 1, nampsy {
+ amp = QG_AMP(qg, 1, y)
+ ydata = ydata + QG_DY2(qg, amp) - QG_DY1(qg, amp) + 1
+ }
+ txskip1 = QG_TX1(qg, 1) - QG_DX1(qg, 1)
+ txskip2 = QG_DX2(qg, namps) - QG_TX2(qg, namps)
+ tyskip1 = QG_TY1(qg, 1) - QG_DY1(qg, 1)
+ tyskip2 = QG_DY2(qg, namps) - QG_TY2(qg, namps)
+
+ # Calculate width of bias strip margins.
+ switch (QG_AMPTYPE(qg, 1)) {
+ case AMP11, AMP21: # "Left amp"
+ bxskip1 = QG_BX1(qg, 1) - QG_DX2(qg, 1) - 1
+ bxskip2 = QG_NX(qg, 1) - QG_BX2(qg, 1)
+
+ case AMP12, AMP22: # "Right amp"
+ bxskip1 = QG_DX1(qg, 1) - QG_BX2(qg, 1) - 1
+ bxskip2 = QG_BX1(qg, 1) - 1
+ }
+
+ byskip1 = QG_BY1(qg, 1) - 1
+ byskip2 = QG_NY(qg, namps) - QG_BY2(qg, namps)
+
+ QG_DX1(qg, 0) = QG_DX1(qg, 1)
+ QG_DX2(qg, 0) = QG_DX1(qg, 0) + xdata - 1
+ QG_DY1(qg, 0) = QG_DY1(qg, 1)
+ QG_DY2(qg, 0) = QG_DY1(qg, 0) + ydata - 1
+
+ QG_TX1(qg, 0) = QG_DX1(qg, 0) + txskip1
+ QG_TX2(qg, 0) = QG_DX2(qg, 0) - txskip2
+ QG_TY1(qg, 0) = QG_DY1(qg, 0) + tyskip1
+ QG_TY2(qg, 0) = QG_DY2(qg, 0) - tyskip2
+
+ QG_BX1(qg, 0) = QG_DX2(qg, 0) + bxskip1 + 1
+ QG_BX2(qg, 0) = nx - bxskip2
+ QG_BY1(qg, 0) = 1 + byskip1
+ QG_BY2(qg, 0) = ny - byskip2
+ }
+
+ # Calculate ccdsec for composite image using sub-images in BLH and TRH
+ # corners.
+ if (QG_CX1 (qg, 1) != 0) {
+ QG_CX1(qg, 0) = QG_CX1(qg, 1)
+ QG_CX2(qg, 0) = QG_CX2(qg, nampsx)
+ QG_CY1(qg, 0) = QG_CY1(qg, 1)
+ QG_CY2(qg, 0) = QG_CY2(qg, namps)
+ }
+
+ # Set up "ampsec" - the section of the composite image derived from
+ # each sub-image.
+ do y = 1, nampsy {
+ amp = QG_AMP (qg, 1, y)
+ QG_AX1(qg, amp) = 1
+ QG_AX2(qg, amp) = QG_NX(qg, amp)
+ do x = 2, nampsx {
+ amp = QG_AMP (qg, x, y)
+ pre = QG_AMP (qg, x-1, y)
+ QG_AX1(qg, amp) = QG_AX2(qg, pre) + 1
+ QG_AX2(qg, amp) = QG_AX1(qg, amp) + QG_NX(qg, amp) - 1
+ }
+ }
+ do x = 1, nampsx {
+ amp = QG_AMP (qg, x, 1)
+ QG_AY1(qg, amp) = 1
+ QG_AY2(qg, amp) = QG_NY(qg, amp)
+ do y = 2, nampsy {
+ amp = QG_AMP (qg, x, y)
+ pre = QG_AMP (qg, x, y-1)
+ QG_AY1(qg, amp) = QG_AY2(qg, pre) + 1
+ QG_AY2(qg, amp) = QG_AY1(qg, amp) + QG_NY(qg, amp) - 1
+ }
+ }
+
+end
diff --git a/noao/imred/quadred/src/quad/quadproc.cl b/noao/imred/quadred/src/quad/quadproc.cl
new file mode 100644
index 00000000..3a881cd7
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadproc.cl
@@ -0,0 +1,173 @@
+procedure quadproc (images)
+
+begin
+ string ims, in_list, cal_list, qp_list
+ int nims
+ struct buffer
+
+ # Freeze input image list
+ in_list = mktemp ("uparm$tmp")
+ ccdlist (images, ccdtype="", names+, > in_list)
+ ims = "@"//in_list
+
+ # Check that the input list contains some images of the specified type.
+ ccdssselect (ims, ccdtype=ccdtype, subset="") | count | scan (nims)
+ if (nims == 0) { # Nothing to do !
+ delete (in_list, ver-)
+ return
+ }
+
+ # Set initial values for the ccdproc parameters used for fitting the
+ # overscan. These parameters may be modified during the interactive
+ # fitting process, the new values being used for all subsequent fits.
+ qccdproc.function = function
+ qccdproc.order = order
+ qccdproc.sample = sample
+ qccdproc.naverage = naverage
+ qccdproc.niterate = niterate
+ qccdproc.low_reject = low_reject
+ qccdproc.high_reject = high_reject
+ qccdproc.grow = grow
+ qccdproc.interactive = interactive
+
+ if (overscan || trim || fixpix) {
+ # Only those images which must be treated specialy are processed
+ # with qproc:
+ # 1) Multiple readout
+ # 2) Not already trimmed
+
+ # First process [OT] any calibration images which WILL BE USED so
+ # that we can be sure they will be reduced explicitly by qproc
+ # rather than automaticaly within ccdproc.
+ qp_list = mktemp ("uparm$tmp")
+
+ if (noproc) {
+
+ cal_list = mktemp ("uparm$tmp")
+ qpcalimage (images=ims, only_param=yes, check=no, > cal_list)
+ qpselect ("@"//cal_list, ccdtype="", stop=no, > qp_list)
+ delete (cal_list, ver-)
+ count (qp_list) | scan (nims)
+ if (nims > 0) {
+ printf ("Calibration images which will be processed:\n")
+ qnoproc (qp_list, fixpix=fixpix, overscan=overscan,
+ trim=trim, fixfile=fixfile, xskip1=xskip1, xskip2=xskip2,
+ xtrim1=xtrim1, xtrim2=xtrim2, ytrim1=ytrim1, ytrim2=ytrim2)
+
+ printf ("\nImages from the input list:\n")
+ }
+
+ } else {
+
+ cal_list = mktemp ("uparm$tmp")
+ qpcalimage (images=ims, only_param=no, check=no, > cal_list)
+ qpselect ("@"//cal_list, ccdtype="", stop=no, > qp_list)
+ delete (cal_list, ver-)
+ count (qp_list) | scan (nims)
+ if (nims > 0) {
+ qproc (qp_list, fixpix=fixpix, overscan=overscan, trim=trim,
+ readaxis=readaxis, fixfile=fixfile, xskip1=xskip1,
+ xskip2=xskip2, xtrim1=xtrim1, xtrim2=xtrim2, ytrim1=ytrim1,
+ ytrim2=ytrim2)
+
+ }
+ }
+
+ delete (qp_list, ver-)
+
+ # Now process all the remaining images.
+ qpselect (ims, ccdtype=ccdtype, stop=no, >> qp_list)
+
+ if (noproc) {
+ qnoproc (qp_list, fixpix=fixpix, overscan=overscan,
+ trim=trim, fixfile=fixfile, xskip1=xskip1, xskip2=xskip2,
+ xtrim1=xtrim1, xtrim2=xtrim2, ytrim1=ytrim1, ytrim2=ytrim2)
+ } else {
+ qproc (qp_list, fixpix=fixpix, overscan=overscan, trim=trim,
+ readaxis=readaxis, fixfile=fixfile, xskip1=xskip1,
+ xskip2=xskip2, xtrim1=xtrim1, xtrim2=xtrim2, ytrim1=ytrim1,
+ ytrim2=ytrim2)
+ }
+
+ delete (qp_list, ver-)
+
+ }
+
+ # Do all other operations with the standard ccdproc.
+
+ if (noproc) {
+
+ # Handle those images that will be processed with qproc ....
+ qpselect (ims, ccdtype=ccdtype, stop=no, >> qp_list)
+
+ # We must also include the calibration images or ccdproc will
+ # complain about missing calibrations.
+ qpcalimage (images=ims, only_param=no, check=no, > cal_list)
+ qpselect ("@"//cal_list, ccdtype="", stop=yes, >> qp_list)
+
+ if (zerocor || darkcor || flatcor || illumcor || fringecor ||
+ readcor || scancor) {
+ qccdproc ("@"//qp_list, noproc=yes,
+ fixpix=no, overscan=no, trim=no, zerocor=zerocor,
+ darkcor=darkcor, flatcor=flatcor, illumcor=illumcor,
+ fringecor=fringecor, readcor=readcor, scancor=scancor,
+ ccdtype=ccdtype, max_cache=max_cache, readaxis=readaxis,
+ fixfile=fixfile, biassec="image", trimsec="image", zero=zero,
+ dark=dark, flat=flat, illum=illum, fringe=fringe,
+ minreplace=minreplace, scantype=scantype, nscan=nscan)
+ }
+
+ printf ("\n")
+ delete (qp_list, ver-)
+
+ # ..... and those that won't
+ qpselect (ims, ccdtype=ccdtype, stop=yes, >> qp_list)
+
+ qccdproc ("@"//qp_list, noproc=yes,
+ fixpix=fixpix, overscan=overscan, trim=trim, zerocor=zerocor,
+ darkcor=darkcor, flatcor=flatcor, illumcor=illumcor,
+ fringecor=fringecor, readcor=readcor, scancor=scancor,
+ ccdtype=ccdtype, max_cache=max_cache, readaxis=readaxis,
+ fixfile=fixfile, biassec="image", trimsec="image", zero=zero,
+ dark=dark, flat=flat, illum=illum, fringe=fringe,
+ minreplace=minreplace, scantype=scantype, nscan=nscan)
+
+ delete (qp_list, ver-)
+
+ } else {
+
+ # Validate fixfile
+ if (fixpix) {
+ match ("single_readout", fixfile) | scan (buffer)
+ if (stridx ("#", buffer) == 0) {
+ buffer = "fixfile " // fixfile //
+ " cannot be used with multi-readout images"
+ error (0, buffer)
+ }
+ }
+
+ qccdproc (ims, ccdtype=ccdtype, max_cache=max_cache, noproc=no,
+ fixpix=fixpix, overscan=overscan, trim=trim, zerocor=zerocor,
+ darkcor=darkcor, flatcor=flatcor, illumcor=illumcor,
+ fringecor=fringecor, readcor=readcor, scancor=scancor,
+ readaxis=readaxis, fixfile=fixfile, biassec="image",
+ trimsec="image", zero=zero, dark=dark, flat=flat, illum=illum,
+ fringe=fringe, minreplace=minreplace, scantype=scantype,
+ nscan=nscan, backup=backup, interactive=interactive,
+ verbose=verbose, logfile=logfile)
+
+ # Set task parameters used for overscan fitting to the ccdproc
+ # values which may have been adjusted interactively
+ function.p_value = qccdproc.function
+ order.p_value = qccdproc.order
+ sample.p_value = qccdproc.sample
+ naverage.p_value = qccdproc.naverage
+ niterate.p_value = qccdproc.niterate
+ low_reject.p_value = qccdproc.low_reject
+ high_reject.p_value = qccdproc.high_reject
+ grow.p_value = qccdproc.grow
+
+ }
+
+ delete (in_list, ver-)
+end
diff --git a/noao/imred/quadred/src/quad/quadproc.par b/noao/imred/quadred/src/quad/quadproc.par
new file mode 100644
index 00000000..edc70514
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadproc.par
@@ -0,0 +1,42 @@
+images,s,a,"",,,List of CCD images to correct
+ccdtype,s,h,"",,,CCD image type to correct
+max_cache,i,h,0,0,,Maximum image caching memory (in Mbytes)
+noproc,b,h,no,,,"List processing steps only?
+"
+fixpix,b,h,yes,,,Fix bad CCD lines and columns?
+overscan,b,h,yes,,,Apply overscan strip correction?
+trim,b,h,yes,,,Trim the image?
+zerocor,b,h,yes,,,Apply zero level correction?
+darkcor,b,h,yes,,,Apply dark count correction?
+flatcor,b,h,yes,,,Apply flat field correction?
+illumcor,b,h,no,,,Apply illumination correction?
+fringecor,b,h,no,,,Apply fringe correction?
+readcor,b,h,no,,,Convert zero level image to readout correction?
+scancor,b,h,no,,,"Convert flat field image to scan correction?
+"
+readaxis,s,h,"line","column|line",, Read out axis (column|line)
+fixfile,s,h,"",,,File describing the bad lines and columns
+xskip1,i,h,INDEF,0,,X pixels to skip at start of overscan
+xskip2,i,h,INDEF,0,,X pixels to skip at end of overscan
+xtrim1,i,h,INDEF,0,,X pixels to trim at start of data
+xtrim2,i,h,INDEF,0,,X pixels to trim at end of data
+ytrim1,i,h,INDEF,0,,Y pixels to trim at start of data
+ytrim2,i,h,INDEF,0,,Y pixels to trim at end of data
+zero,s,h,"",,,Zero level calibration image
+dark,s,h,"",,,Dark count calibration image
+flat,s,h,"",,,Flat field images
+illum,s,h,"",,,Illumination correction images
+fringe,s,h,"",,,Fringe correction images
+minreplace,r,h,1.,,,Minimum flat field value
+scantype,s,h,"shortscan","shortscan|longscan",,Scan type (shortscan|longscan)
+nscan,i,h,1,1,,"Number of short scan lines
+"
+interactive,b,h,no,,,Fit overscan interactively?
+function,s,h,"legendre",,,Fitting function
+order,i,h,1,1,,Number of polynomial terms or spline pieces
+sample,s,h,"*",,,Sample points to fit
+naverage,i,h,1,,,Number of sample points to combine
+niterate,i,h,1,0,,Number of rejection iterations
+low_reject,r,h,3.,0.,,Low sigma rejection factor
+high_reject,r,h,3.,0.,,High sigma rejection factor
+grow,r,h,0.,0.,,Rejection growing radius
diff --git a/noao/imred/quadred/src/quad/quadscale.par b/noao/imred/quadred/src/quad/quadscale.par
new file mode 100644
index 00000000..9241c2b1
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadscale.par
@@ -0,0 +1,7 @@
+input,s,a,,,,Input image
+output,s,a,,,,Output image
+gain11,r,h,1,,,"Gain for quadrant y=1, x=1"
+gain12,r,h,1,,,"Gain for quadrant y=1, x=2"
+gain21,r,h,1,,,"Gain for quadrant y=2, x=1"
+gain22,r,h,1,,,"Gain for quadrant y=2, x=2"
+opperation,s,h,"multiply","multiply|divide",,Multiply or divide by gains
diff --git a/noao/imred/quadred/src/quad/quadscale.x b/noao/imred/quadred/src/quad/quadscale.x
new file mode 100644
index 00000000..5e594eb4
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadscale.x
@@ -0,0 +1,159 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+define OPPERATIONS "|multiply|divide|"
+define OPMULTIPLY 1
+define OPDIVIDE 2
+define TOL1 1.0e-7
+define TOL2 -1.0e-7
+
+procedure t_quadscale ()
+
+char input[SZ_FNAME] #TI Input image name.
+char output[SZ_FNAME] #TI Output image name.
+char instrument[SZ_FNAME] #TI Instrument translation file
+
+real gain[QG_MAXAMPS] #TI Gain factor for each quadrant
+int op #TI Multiply or divide by gain factors
+
+int i
+pointer in, out, qg
+char buffer[SZ_LINE]
+
+real clgetr()
+int clgwrd(), hdmaccf()
+pointer immap()
+
+begin
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Open input image
+ call clgstr ("input", input, SZ_FNAME)
+ in = immap (input, READ_ONLY, 0)
+
+ # Allocate quadgeom structure and initialise it from image header
+ call quadalloc (qg)
+
+
+ # Fill out quadgeom structure from header depending on revision level
+ if (hdmaccf (in, "HDR_REV") == NO) {
+
+ # Check to see if the image has been processed or not
+ if (hdmaccf (in, "ccdproc") == YES) {
+ call quadgeomred (in, qg)
+ } else {
+ call quadgeom (in, qg, "", "")
+ }
+
+ } else {
+ call qghdr2 (in, qg)
+ }
+
+ # Open output image
+ call clgstr ("output", output, SZ_FNAME)
+ out = immap (output, NEW_COPY, in)
+ IM_PIXTYPE(out) = TY_REAL
+
+ # Get gain factors
+ gain[1] = clgetr ("gain11")
+ gain[2] = clgetr ("gain12")
+ gain[3] = clgetr ("gain21")
+ gain[4] = clgetr ("gain22")
+
+ # Get direction of opperation
+ op = clgwrd ("opperation", buffer, SZ_LINE, OPPERATIONS)
+
+ switch (op) {
+ case OPMULTIPLY:
+ call quadmult (in, out, gain, qg)
+
+ case OPDIVIDE:
+ # Check for zero gain --> divide by zero
+ do i = 1, 4 {
+ if ((gain[i] < TOL1) && (gain[i] > TOL2)) {
+ call error (0, "Attempt to divide by gain value of zero")
+ }
+ }
+ call quaddiv (in, out, gain, qg)
+
+ }
+
+ call imunmap (in)
+ call imunmap (out)
+ call quadfree (qg)
+ call hdmclose ()
+end
+
+procedure quadmult (in, out, gain, qg)
+
+pointer in #I imio pointer for input image.
+pointer out #I imio pointer for output image.
+real gain[ARB] #I Array of gain factors.
+pointer qg #I Pointer to quadgeom structure.
+
+pointer inbuf, obuf
+int junk, nx, x, y, line, amp, amp2, off
+long invec[IM_MAXDIM], ovec[IM_MAXDIM]
+
+int imgnlr(), impnlr()
+
+begin
+
+ # Setup start vector for sequential reads
+ call amovkl (long(1), invec, IM_MAXDIM)
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPS(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnlr (in, inbuf, invec)
+ junk = impnlr (out, obuf, ovec)
+ off = 0
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ nx = QG_NX(qg, amp)
+ call amulkr (Memr[inbuf+off], gain[amp], Memr[obuf+off], nx)
+ off = off + nx
+ }
+ }
+ }
+
+end
+
+procedure quaddiv (in, out, gain, qg)
+
+pointer in #I imio pointer for input image.
+pointer out #I imio pointer for output image.
+real gain[ARB] #I Array of gain factors.
+pointer qg #I Pointer to quadgeom structure.
+
+pointer inbuf, obuf
+int junk, nx, x, y, line, amp, amp2, off
+long invec[IM_MAXDIM], ovec[IM_MAXDIM]
+
+int imgnlr(), impnlr()
+
+begin
+
+ # Setup start vector for sequential reads
+ call amovkl (long(1), invec, IM_MAXDIM)
+ call amovkl (long(1), ovec, IM_MAXDIM)
+
+ do y = 1, QG_NAMPS(qg) {
+ amp2 = QG_AMP(qg, 1, y)
+ do line = 1, QG_NY(qg, amp2) {
+ junk = imgnlr (in, inbuf, invec)
+ junk = impnlr (out, obuf, ovec)
+ off = 0
+ do x = 1, QG_NAMPSX(qg) {
+ amp = QG_AMP(qg, x, y)
+ nx = QG_NX(qg, amp)
+ call adivkr (Memr[inbuf+off], gain[amp], Memr[obuf+off], nx)
+ off = off + nx
+ }
+ }
+ }
+
+end
diff --git a/noao/imred/quadred/src/quad/quadsections.par b/noao/imred/quadred/src/quad/quadsections.par
new file mode 100644
index 00000000..aa6ae59d
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadsections.par
@@ -0,0 +1,14 @@
+images,s,a,"",,,Input image name
+window,s,h,"datasec","|datasec|trimsec|biassec|reflect|duplicate|",,Window to apply to section
+section,s,h,"",,,Default Image section
+template,s,h,"",,,Template for formating results
+#
+## TRIM AND OVERSCAN MARGINS (override header values)"
+#xskip1,i,h,INDEF,0,,X pixels to skip at start of overscan
+#xskip2,i,h,INDEF,0,,X pixels to skip at end of overscan
+#xtrim1,i,h,INDEF,0,,X pixels to trim at start of data
+#xtrim2,i,h,INDEF,0,,X pixels to trim at end of data
+#ytrim1,i,h,INDEF,0,,Y pixels to trim at start of data
+#ytrim2,i,h,INDEF,0,,"Y pixels to trim at end of data
+#"
+#mode,s,h,"ql"
diff --git a/noao/imred/quadred/src/quad/quadsections.x b/noao/imred/quadred/src/quad/quadsections.x
new file mode 100644
index 00000000..1d21d94c
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadsections.x
@@ -0,0 +1,447 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+# QUADSECTIONS.X -- File header comment.
+
+define OPTION_DICT "|biassec|datasec|trimsec|reflect|duplicate|"
+
+define OPT_BIASSEC 1
+define OPT_DATASEC 2
+define OPT_TRIMSEC 3
+define OPT_REFLECT 4
+define OPT_DUPLICATE 5
+
+define DEFAULT_MACRO "$I$S\\n"
+
+
+# QUADSECTIONS -- Quadsections task.
+
+procedure t_quadsections ()
+
+pointer inlist #TI List of input image name.
+char instrument[SZ_FNAME] #TI Instrument translation file
+char section[SZ_LINE] #TI Section of CCD required
+int option #TI Type of section required
+char format[SZ_LINE] #TI strmac macro string for building output
+int xtrim1 #TI X pixels to trim at start of data
+int xtrim2 #TI X pixels to trim at end of data
+int ytrim1 #TI Y pixels to trim at start of data
+int ytrim2 #TI Y pixels to trim at end of data
+int xskip1 #TI X pixels to skip at start of overscan
+int xskip2 #TI X pixels to skip at end of overscan
+
+char buffer[SZ_LINE], input[SZ_LINE]
+
+int clgwrd(), imtopenp(), imtgetim()
+
+begin
+ # Open input image
+ inlist = imtopenp ("images")
+
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Get option.
+ option = clgwrd ("window", buffer, SZ_LINE, OPTION_DICT)
+
+ # Get default section
+ call clgstr ("section", section, SZ_LINE)
+
+ # Get user defined trim and overscan margins
+ #xtrim1 = clgeti ("xtrim1")
+ #xtrim2 = clgeti ("xtrim2")
+ #ytrim1 = clgeti ("ytrim1")
+ #ytrim2 = clgeti ("ytrim2")
+ #xskip1 = clgeti ("xskip1")
+ #xskip2 = clgeti ("xskip2")
+ xtrim1 = INDEFI
+ xtrim2 = INDEFI
+ ytrim1 = INDEFI
+ ytrim2 = INDEFI
+ xskip1 = INDEFI
+ xskip2 = INDEFI
+
+ # Get format string and convert to a strmac macro string.
+ call clgstr ("template", format, SZ_LINE)
+ if (format[1] == EOS)
+ call sprintf (format, SZ_LINE, "%s")
+ call pargstr (DEFAULT_MACRO)
+ call qsmkmacro (format, format, SZ_LINE)
+
+ while (imtgetim (inlist, input, SZ_LINE) != EOF) {
+ call quadsections (input, section, xtrim1, xtrim2, ytrim1, ytrim2,
+ xskip1, xskip2, option, format)
+ }
+
+ # Tidy up
+ call hdmclose ()
+ call imtclose (inlist)
+end
+
+
+# QUADSECTIONS -- ???
+
+procedure quadsections (input, section, xtrim1, xtrim2, ytrim1, ytrim2,
+ xskip1, xskip2, option, format)
+
+char input[SZ_FNAME] #I Input image name.
+char section[SZ_LINE] #I Default section specification
+int xtrim1 #I X pixels to trim at start of data
+int xtrim2 #I X pixels to trim at end of data
+int ytrim1 #I Y pixels to trim at start of data
+int ytrim2 #I Y pixels to trim at end of data
+int xskip1 #I X pixels to skip at start of overscan
+int xskip2 #I X pixels to skip at end of overscan
+int option #I Type of section required
+char format[SZ_LINE] #I strmac macro string for building output
+
+char image[SZ_LINE], argstr[SZ_LINE], buffer[SZ_LINE]
+char insection[SZ_LINE], outsection[SZ_LINE]
+int amp, arg[9], len
+int i, x1, x2, y1, y2
+
+pointer in, qg
+bool reduced
+
+pointer immap()
+int hdmaccf(), gstrcpy(), strlen(), strmac()
+bool quadsect()
+
+begin
+ # Parse input into an image name and an image section.
+ call imgimage (input, image, SZ_LINE)
+ call imgsection (input, insection, SZ_LINE)
+ # if no section was supplied in the image name use the default section.
+ if (insection[1] == EOS) {
+ call strcpy (section, insection, SZ_LINE)
+ }
+
+ # Open input image
+ in = immap (image, READ_ONLY, 0)
+
+ # Determine if image has been trimmed or not
+ reduced = (hdmaccf (in, "trim") == YES)
+
+ if (reduced) {
+ # OPT_BIASSEC does not make sense for reduced images.
+ if (option == OPT_BIASSEC)
+ return
+ # Trimsec and datasec are identical for reduced images
+ if (option == OPT_TRIMSEC)
+ option = OPT_DATASEC
+ }
+
+ # Set-up quadgeom structure
+ call quadalloc (qg)
+ if (hdmaccf (in, "HDR_REV") == NO) {
+ if (reduced) {
+ call quadgeomred (in, qg)
+ } else {
+ call quadgeom (in, qg, "", "")
+ }
+ } else {
+ call qghdr2 (in, qg)
+ }
+
+# call quaddump (qg)
+
+ # Adjust quadgeom structure for user trim and overscan margins
+ if (! reduced) {
+ call qguser (qg, xtrim1, xtrim2, ytrim1, ytrim2, xskip1, xskip2)
+ }
+# call quaddump (qg)
+
+
+ # Store image name as first argument in macro argument string "argstr"
+ arg[1] = 1
+ arg[2] = 1 + arg[1] + gstrcpy (image, argstr, SZ_LINE)
+
+ # Blank output string
+ buffer[1] = EOS
+
+ # Determine the intersection of the specified section with the portion
+ # of the image read through each readout.
+ do amp = 1, QG_NAMPS (qg) {
+
+ # skip any phantoms in raw images
+ if (QG_PHANTOM (qg, amp) == NO) {
+
+ if (quadsect (qg, insection, option, amp, x1, x2, y1, y2)) {
+ # Build resulting section string ...
+ call sprintf (outsection, SZ_LINE, "[%d:%d,%d:%d]")
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+
+ # ... and save it as second argument
+ arg[3] = 1 + arg[2] + gstrcpy (outsection, argstr[arg[2]],
+ SZ_LINE-arg[2]+1)
+
+ # Save Ampid as third argument
+ call strcpy (Memc[QG_AMPID(qg, amp)], argstr[arg[3]],
+ SZ_LINE-arg[3]+1)
+
+ # Process macro string
+ i = strmac (format, argstr, buffer, SZ_LINE)
+ call printf (buffer)
+ }
+ }
+ }
+
+ # Output <lf> if format does not explicitly include one.
+ len = strlen (buffer)
+ if ((len > 2) && !(buffer[len-1]=='\\' && buffer[len]=='n')) {
+ call printf ("\n")
+ }
+
+ call flush (STDOUT)
+
+ # Tidy up
+ call quadfree (qg)
+ call imunmap (in)
+end
+
+
+# QSMKMACRO -- Perform the following substitutions on the given macro string
+#
+# $I --> $1
+# $S --> $2
+# $A --> $3
+# $? --> $?
+
+procedure qsmkmacro (instr, outstr, maxchars)
+
+char instr[ARB] #I Input macro string.
+char outstr[maxchars] #O Output macro string.
+int maxchars #I Maximum length of outstr
+
+char ch
+int ip, op
+
+begin
+
+ op = 1
+ for (ip=1; instr[ip] != EOS; ip=ip+1) {
+ ch = instr[ip]
+ outstr[op] = ch
+ op = op + 1
+ if (op > maxchars)
+ call error (0, "qsmkmacro: Output buffer overflow")
+
+ if (ch == '$') {
+ ip = ip + 1
+ ch = instr[ip]
+
+ if (ch == 'I') {
+ outstr (op) = '1'
+ op = op + 1
+ } else if (ch == 'S') {
+ outstr (op) = '2'
+ op = op + 1
+ } else if (ch == 'A') {
+ outstr (op) = '3'
+ op = op + 1
+ } else {
+ outstr (op) = ch
+ op = op + 1
+ }
+ if (op > maxchars)
+ call error (0, "qsmkmacro: Output buffer overflow")
+ }
+ }
+end
+
+
+# QUADSECT -- ??
+
+bool procedure quadsect (qg, section, option, amp, x1, x2, y1, y2)
+
+pointer qg #I Pointer to initialised quadgeom structure.
+char section[SZ_LINE] #I Default section specification.
+int option #I Type of section required.
+int amp #I Amplifier for which section is required.
+int x1, x2, y1, y2 #O Corners of specified section.
+bool overlap #O true if part of section read through amp.
+
+int xskip, xsize, yskip, ysize
+int sx1, sx2, sy1, sy2, sxs, sys
+int dx1, dx2, dy1, dy2
+int tx1, tx2, ty1, ty2
+int bx1, bx2, by1, by2
+
+begin
+
+ # Decode input section
+ x1 = 1
+ x2 = QG_NX(qg, 0)
+ sxs = 1
+ y1 = 1
+ y2 = QG_NY(qg, 0)
+ sys = 1
+ call ccd_section (section, x1, x2, sxs, y1, y2, sys)
+ sx1 = min (x1, x2)
+ sx2 = max (x1, x2)
+ sy1 = min (y1, y2)
+ sy2 = max (y1, y2)
+
+ # Set up null return (overlap) values in case no part of section was
+ # read with this amplifier.
+ overlap = false
+ x1 = 0
+ x2 = 0
+ y1 = 0
+ y2 = 0
+
+ # Calculate suplimentary quantitiies as required.
+ switch (option) {
+
+ case OPT_REFLECT, OPT_DUPLICATE:
+ xskip = sx1 - QG_DX1(qg, 0)
+ xsize = sx2 - sx1 + 1
+ yskip = sy1 - QG_DY1(qg, 0)
+ ysize = sy2 - sy1 + 1
+ }
+
+ # Determine the intersection of the specified section with the portion
+ # of the image read through the specified readout.
+ switch (option) {
+
+ case OPT_BIASSEC:
+ bx1 = QG_AX1(qg, amp) + QG_BX1(qg, amp) - 1
+ bx2 = QG_AX1(qg, amp) + QG_BX2(qg, amp) - 1
+ by1 = QG_AY1(qg, amp) + QG_BY1(qg, amp) - 1
+ by2 = QG_AY1(qg, amp) + QG_BY2(qg, amp) - 1
+
+ if (sx1 > bx2)
+ return (overlap)
+ if (sx2 < bx1)
+ return (overlap)
+ if (sy1 > by2)
+ return (overlap)
+ if (sy2 < by1)
+ return (overlap)
+
+ x1 = max (sx1, bx1)
+ x2 = min (sx2, bx2)
+ y1 = max (sy1, by1)
+ y2 = min (sy2, by2)
+
+ case OPT_DATASEC:
+ dx1 = QG_AX1(qg, amp) + QG_DX1(qg, amp) - 1
+ dx2 = QG_AX1(qg, amp) + QG_DX2(qg, amp) - 1
+ dy1 = QG_AY1(qg, amp) + QG_DY1(qg, amp) - 1
+ dy2 = QG_AY1(qg, amp) + QG_DY2(qg, amp) - 1
+
+ if (sx1 > dx2)
+ return (overlap)
+ if (sx2 < dx1)
+ return (overlap)
+ if (sy1 > dy2)
+ return (overlap)
+ if (sy2 < dy1)
+ return (overlap)
+
+ x1 = max (sx1, dx1)
+ x2 = min (sx2, dx2)
+ y1 = max (sy1, dy1)
+ y2 = min (sy2, dy2)
+
+ case OPT_TRIMSEC:
+ tx1 = QG_AX1(qg, amp) + QG_TX1(qg, amp) - 1
+ tx2 = QG_AX1(qg, amp) + QG_TX2(qg, amp) - 1
+ ty1 = QG_AY1(qg, amp) + QG_TY1(qg, amp) - 1
+ ty2 = QG_AY1(qg, amp) + QG_TY2(qg, amp) - 1
+
+ if (sx1 > tx2)
+ return (overlap)
+ if (sx2 < tx1)
+ return (overlap)
+ if (sy1 > ty2)
+ return (overlap)
+ if (sy2 < ty1)
+ return (overlap)
+
+ x1 = max (sx1, tx1)
+ x2 = min (sx2, tx2)
+ y1 = max (sy1, ty1)
+ y2 = min (sy2, ty2)
+
+ case OPT_REFLECT:
+ dx1 = QG_AX1(qg, amp) + QG_DX1(qg, amp) - 1
+ dx2 = QG_AX1(qg, amp) + QG_DX2(qg, amp) - 1
+ dy1 = QG_AY1(qg, amp) + QG_DY1(qg, amp) - 1
+ dy2 = QG_AY1(qg, amp) + QG_DY2(qg, amp) - 1
+
+ switch (QG_AMPTYPE(qg, amp)) {
+ case AMP11:
+ x1 = dx1 + xskip
+ x2 = x1 + xsize - 1
+ y1 = dy1 + yskip
+ y2 = y1 + ysize - 1
+
+ case AMP12:
+ x2 = dx2 - xskip
+ x1 = x2 - xsize + 1
+ y1 = dy1 + yskip
+ y2 = y1 + ysize - 1
+
+ case AMP21:
+ x1 = dx1 + xskip
+ x2 = x1 + xsize - 1
+ y2 = dy2 - yskip
+ y1 = y2 - ysize + 1
+
+ case AMP22:
+ x2 = dx2 - xskip
+ x1 = x2 - xsize + 1
+ y2 = dy2 - yskip
+ y1 = y2 - ysize + 1
+ }
+
+ if (x1 > dx2)
+ return (overlap)
+ if (x2 < dx1)
+ return (overlap)
+ if (y1 > dy2)
+ return (overlap)
+ if (y2 < dy1)
+ return (overlap)
+
+ x1 = max (x1, dx1)
+ x2 = min (x2, dx2)
+ y1 = max (y1, dy1)
+ y2 = min (y2, dy2)
+
+ case OPT_DUPLICATE:
+ dx1 = QG_AX1(qg, amp) + QG_DX1(qg, amp) - 1
+ dx2 = QG_AX1(qg, amp) + QG_DX2(qg, amp) - 1
+ dy1 = QG_AY1(qg, amp) + QG_DY1(qg, amp) - 1
+ dy2 = QG_AY1(qg, amp) + QG_DY2(qg, amp) - 1
+
+ x1 = dx1 + xskip
+ x2 = x1 + xsize - 1
+ y1 = dy1 + yskip
+ y2 = y1 + ysize - 1
+
+ if (x1 > dx2)
+ return (overlap)
+ if (x2 < dx1)
+ return (overlap)
+ if (y1 > dy2)
+ return (overlap)
+ if (y2 < dy1)
+ return (overlap)
+
+ x1 = max (x1, dx1)
+ x2 = min (x2, dx2)
+ y1 = max (y1, dy1)
+ y2 = min (y2, dy2)
+
+ }
+
+ overlap = true
+ return (overlap)
+
+end
diff --git a/noao/imred/quadred/src/quad/quadsplit.par b/noao/imred/quadred/src/quad/quadsplit.par
new file mode 100644
index 00000000..274018c0
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadsplit.par
@@ -0,0 +1,9 @@
+input,s,a,"",,,Input image name
+output,s,h,"",,,Output root name
+clobber,b,h,"yes",,,Clobber prexisting subimages
+#xskip1,i,h,INDEF,0,,X pixels to skip at start of overscan
+#xskip2,i,h,INDEF,0,,X pixels to skip at end of overscan
+#xtrim1,i,h,INDEF,0,,X pixels to trim at start of data
+#xtrim2,i,h,INDEF,0,,X pixels to trim at end of data
+#ytrim1,i,h,INDEF,0,,Y pixels to trim at start of data
+#ytrim2,i,h,INDEF,0,,Y pixels to trim at end of data
diff --git a/noao/imred/quadred/src/quad/quadsplit.x b/noao/imred/quadred/src/quad/quadsplit.x
new file mode 100644
index 00000000..a6ffc95f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadsplit.x
@@ -0,0 +1,115 @@
+include <imhdr.h>
+include "quadgeom.h"
+
+procedure t_quadsplit ()
+
+char input[SZ_FNAME] #TI Input image name.
+char output[SZ_FNAME] #TI Output image root name.
+char instrument[SZ_FNAME] #TI Instrument translation file.
+bool clobber #TI Clobber any existing sub-images.
+int xtrim1 #TI Number of pixels to trim at right.
+int xtrim2 #TI Number of pixels to trim at left.
+int ytrim1 #TI Number of pixels to trim at bottom.
+int ytrim2 #TI Number of pixels to trim at top.
+int xskip1 #TI Number of pixels to skip at start of overscan in X
+int xskip2 #TI Number of pixels to skip at end of overscan in X
+
+pointer in, qg, out[QG_MAXAMPS]
+int amp, namps
+char logstr[SZ_LINE]
+
+pointer immap()
+bool streq(), clgetb()
+int quadmap(), hdmaccf()
+
+begin
+
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Map input image
+ call clgstr ("input", input, SZ_FNAME)
+ in = immap (input, READ_ONLY, 0)
+
+ # Get root name for output image
+ call clgstr ("output", output, SZ_FNAME)
+ if (streq (output, ""))
+ call strcpy (input, output, SZ_FNAME)
+ call xt_imroot (output, output, SZ_FNAME)
+
+ # Set-up section translation
+ call quadalloc (qg)
+
+ if (hdmaccf (in, "HDR_REV") == NO) {
+ call quadgeom (in, qg, "", "")
+ } else {
+ call qghdr2 (in, qg)
+ }
+
+ # Adjust quadgeom structure for user trim and overscan margins
+ #xtrim1 = clgeti ("xtrim1")
+ #xtrim2 = clgeti ("xtrim2")
+ #ytrim1 = clgeti ("ytrim1")
+ #ytrim2 = clgeti ("ytrim2")
+ #xskip1 = clgeti ("xskip1")
+ #xskip2 = clgeti ("xskip2")
+ xtrim1 = INDEFI
+ xtrim2 = INDEFI
+ ytrim1 = INDEFI
+ ytrim2 = INDEFI
+ xskip1 = INDEFI
+ xskip2 = INDEFI
+ call qguser (qg, xtrim1, xtrim2, ytrim1, ytrim2, xskip1, xskip2)
+
+# call quaddump (qg)
+
+ # Map output images one for each readout
+ clobber = clgetb ("clobber")
+ namps = quadmap (output, NEW_COPY, clobber, in, qg, out)
+
+ # Split the image using the appropriately typed routine
+ switch (IM_PIXTYPE(in)) {
+ case TY_USHORT, TY_SHORT:
+ call qsplits (in, out, qg)
+
+ case TY_LONG:
+ call qsplitl (in, out, qg)
+
+ case TY_INT:
+ call qspliti (in, out, qg)
+
+ case TY_REAL:
+ call qsplitr (in, out, qg)
+
+ case TY_DOUBLE:
+ call qsplitd (in, out, qg)
+
+ default:
+ call error (1, "unsupported pixel datatype")
+ }
+
+ # Log opperation
+ if (QG_NAMPSX(qg) == 2 && QG_NAMPSY(qg) == 2) {
+ call sprintf (logstr, SZ_LINE, "Quad-readout image")
+ } else if (QG_NAMPSX(qg) == 2 || QG_NAMPSY(qg) == 2) {
+ call sprintf (logstr, SZ_LINE,
+ "Dual-readout image: nampsx=%d nampsy=%d")
+ call pargi (QG_NAMPSX(qg))
+ call pargi (QG_NAMPSY(qg))
+ } else {
+ call sprintf (logstr, SZ_LINE, "Single-readout image")
+ }
+ call timelog (logstr, SZ_LINE)
+ call ccdlog (input, logstr)
+
+ # Tidy up
+ call imunmap (in)
+ do amp = 1, namps {
+ if (out[amp] != NULL) {
+ call imunmap (out[amp])
+ }
+ }
+ call quadfree (qg)
+ call hdmclose ()
+end
diff --git a/noao/imred/quadred/src/quad/quadtest/artobs.cl b/noao/imred/quadred/src/quad/quadtest/artobs.cl
new file mode 100644
index 00000000..292ed8c6
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/artobs.cl
@@ -0,0 +1,68 @@
+# ARTOBS -- Simulate observe command using artificial data.
+
+procedure artobs ()
+
+begin
+ string image, oim, ccdt
+ int picnum, nexps, i
+ real exptime
+ string imtitle
+
+ # Get ccdtype
+ ccdt = obspars.ccdtype
+
+ # Get number of pictures to take
+ nexps = npics
+
+ # Get next picture number
+ if (obspars.autopicnum) {
+ picnum = obspars.picture.p_value
+ } else {
+ picnum = obspars.picture
+ }
+
+ # Get exposure time
+ if (ccdt != "zero") {
+ exptime = obspars.exposure
+ } else {
+ exptime = 0.0
+ }
+
+ # Set filter
+ if (obspars.setfilter != "none" && ccdt != "zero" && ccdt != "dark") {
+ if (instrpars.instrname != "")
+ mkquad.filter = instrpars.filter1
+ }
+
+ # Get imtitle. This MUST always be the last interactive prompt!
+ imtitle = title
+
+ for (i = picnum; i < picnum+nexps; i = i+1) {
+
+ # Make image name
+ if (ccdt == "object") {
+ printf ("obj%03d\n", i) | scan (image)
+ } else {
+ printf ("%s%03d\n", ccdt, i) | scan (image)
+ }
+ if (access (image//".imh")) {
+ oim = image
+ image = mktemp (image//".")
+ printf ("Output image %s already exists... %s used \n", oim,
+ image)
+ }
+
+ if (ccdt == "dflat" || ccdt == "pflat")
+ ccdt = "flat"
+
+ if (ccdt == "sflat" || ccdt == "comp" )
+ ccdt = "other"
+
+ # Call MKQUAD task
+ mkquad (image, exptime, ccdt)
+ hedit (image, "i_title", imtitle, add+, ver-, show-)
+ obspars.picture.p_value = i + 1
+ printf ("Image %s written to disk\n", image, > "STDERR")
+ }
+
+end
diff --git a/noao/imred/quadred/src/quad/quadtest/artobs.par b/noao/imred/quadred/src/quad/quadtest/artobs.par
new file mode 100644
index 00000000..d9611ef5
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/artobs.par
@@ -0,0 +1,5 @@
+# observe parameter file
+obspars,pset,h,,,,Observing parameters
+detpars,pset,h,,,,Detector parameters
+instrpars,pset,h,,,,Instrument parameters
+telpars,pset,h,,,,Telescope parameters
diff --git a/noao/imred/quadred/src/quad/quadtest/ccdpars.par b/noao/imred/quadred/src/quad/quadtest/ccdpars.par
new file mode 100644
index 00000000..b30fbb99
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/ccdpars.par
@@ -0,0 +1,29 @@
+ncols,i,h,1060,,,"Number of columns"
+nlines,i,h,1024,,,"Number of lines
+"
+datasec,s,h,"[1:1024,1:1024]",,,"Data section"
+trimsec,s,h,"[1:1024,1:1024]",,,"Trim section"
+biassec,s,h,"[1025:1060,1:1024]",,,"Bias section
+"
+amplifiers,s,h,"Quad","|Quad|UpperPair|LowerPair|LowerLeft|",,"Amplifiers to use
+"
+gain1,r,h,1.0,,,gain (e-/ADU) for Amp12
+ron1,r,h,4.0,,,readout noise for Amp11
+zero1,i,h,1000,,,"zero level for Amp11"
+nlin1,s,h,"",,,"Non-linearity coefficants
+"
+gain2,r,h,1.0,,,gain (e-/ADU) for Amp12
+ron2,r,h,4.0,,,readout noise for Amp12
+zero2,i,h,1000,,,"zero level for Amp12"
+nlin2,s,h,"",,,"Non-linearity coefficants
+"
+gain3,r,h,1.0,,,gain (e-/ADU) for Amp21
+ron3,r,h,4.0,,,readout noise for Amp21
+zero3,i,h,1000,,,"zero level for Amp21"
+nlin3,s,h,"",,,"Non-linearity coefficants
+"
+gain4,r,h,1.0,,,gain (e-/ADU) for Amp22
+ron4,r,h,4.0,,,readout noise for Amp22
+zero4,i,h,1000,,,"zero level for Amp22"
+nlin4,s,h,"",,,"Non-linearity coefficants
+"
diff --git a/noao/imred/quadred/src/quad/quadtest/logfile b/noao/imred/quadred/src/quad/quadtest/logfile
new file mode 100644
index 00000000..ddf97f0a
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/logfile
@@ -0,0 +1 @@
+obj99999: Dec 9 12:21 Quadjoin: nampsx=2 nampsy=2
diff --git a/noao/imred/quadred/src/quad/quadtest/mkamp.cl b/noao/imred/quadred/src/quad/quadtest/mkamp.cl
new file mode 100644
index 00000000..98cd8468
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/mkamp.cl
@@ -0,0 +1,166 @@
+# MKAMP -- Make a CCD observation
+
+procedure mkamp (image, exptime, ccdtype)
+
+string image {prompt="Image name"}
+real exptime {prompt="Exposure time"}
+string ccdtype {prompt="CCD type"}
+
+int ncols=132 {prompt="Number of columns"}
+int nlines=100 {prompt="Number of lines"}
+string filter="" {prompt="Filter"}
+string datasec="" {prompt="Data section"}
+string trimsec="" {prompt="Trim section"}
+string biassec="" {prompt="Bias section"}
+
+file imdata="" {prompt="Image data"}
+real skyrate=0. {prompt="Sky count rate"}
+real zeroval=0. {prompt="Zero level value"}
+real zeroslope=0. {prompt="Slope of zero level"}
+real flashval=0. {prompt="Preflash value"}
+real flashslope=0. {prompt="Slope of preflash value"}
+real darkrate=0. {prompt="Dark count rate"}
+real darkslope=0. {prompt="Slope of dark count rate"}
+real flatslope=0. {prompt="Flat field slope"}
+file badpix="" {prompt="Bad pixel regions"}
+real badval=0. {prompt="Bad pixel value"}
+real gain=1. {prompt="Gain (e-/adu)", min=1.0e-9}
+real ron=0. {prompt="Read out noise e-"}
+string nonlin {prompt="Non-linearity coefficiants"}
+bool poisson=yes {prompt="Add poisson noise?"}
+bool overwrite=no {prompt="Overwrite existing image?"}
+struct *fdnl {prompt="Internal use"}
+
+begin
+ int c1, c2, l1, l2, rseed, i, dummy
+ real exp, value, valslope, invgain, date, rval, coef[7]
+ string im, type, s, lincoefs, ampsec
+
+ im = image
+ exp = exptime
+ type = ccdtype
+
+ # Check for zero (or very small) gain
+ if (abs (gain) < 1.0e-9)
+ call error (0, "zero (or very small) gain specified")
+
+ invgain = 1.0 / gain
+
+ if (access (im//".imh") == yes)
+ im = im // ".imh"
+ if (access (im//".hhh") == yes)
+ im = im // ".hhh"
+ if (access (im) == yes) {
+ if (overwrite == yes)
+ imdelete (im, verify=no)
+ else
+ return
+ }
+
+ # Create the image.
+ s = str (ncols) // " " // str (nlines)
+ mkimage (im, "make", 0., 2, s, pixtype="real", slope=0., sigma=0.)
+
+ # Add a data image.
+ if (access (imdata//".imh") == yes)
+ imdata = imdata // ".imh"
+ if (access (imdata//".hhh") == yes)
+ imdata = imdata // ".hhh"
+ if (access (imdata) == yes)
+ imcopy (imdata//datasec, im//datasec, verbose=no)
+
+ # Add sky.
+ value = exp * skyrate
+ if (value != 0.)
+ mkimage (im//datasec, "add", value, slope=0., sigma=0.)
+
+ # Add flat field response.
+ if (flatslope != 0.)
+ mkimage (im//datasec, "mul", 1., slope=flatslope, sigma=0.)
+
+ # Add preflash level and dark count.
+ value = flashval + exp * darkrate
+ valslope = flashslope + exp * darkslope
+ if ((value != 0.) && (valslope != 0.))
+ mkimage (im//datasec, "add", value, slope=valslope, sigma=0.)
+
+ # Convert to ADU
+ mkimage (im//datasec, "mul", invgain, slope=0., sigma=0.)
+
+ # Add poisson and readout noise
+ # if seed is 0 pick a fairly arbitrary value
+ if (seed == 0) {
+ date | translit ("STDIN", from_string="a-zA-Z: ", delete+) |
+ scan (date)
+ rseed = abs (date / 10000)
+ } else {
+ rseed = seed
+ }
+
+ # Add non-linearity
+ if (nonlin != "") {
+ lincoefs = mktemp ("uparm$tmp")
+ files (nonlin, >> lincoefs)
+ fdnl = lincoefs
+ coef[1] = 1.0
+ for (i=2; i <= 7; i = i+1) {
+ dummy = fscan (fdnl, rval)
+ if (dummy == EOF) {
+ coef[i] = 0.0
+ } else {
+ coef[i] = rval
+ }
+ }
+
+ irlincor (im, im, section= "", coeff1=coef[1], coeff2=coef[2],
+ coeff3=coef[3], coeff4=coef[4], coeff5=coef[5], coeff6=coef[6],
+ coeff7=coef[7], maxadu=65535.0)
+ delete (lincoefs, ver-)
+ }
+
+ mknoise (im, background=0., gain=gain, rdnoise=ron, poisson=poisson,
+ seed=rseed, cosrays="", ncosrays=0, comments=no)
+
+ # decrement seed for next use
+ if (seed < 0)
+ seed.p_value = seed - 1
+
+ # Add zero level
+ # We add an extra 0.5 so that we nint rather than truncate when
+ # converting to short integer.
+ zeroval = zeroval + 0.5
+ mkimage (im, "add", zeroval, slope=zeroslope, sigma=0.)
+
+ # Set bad pixels.
+ if (access (badpix)) {
+ list = badpix
+ while (fscan (list, c1, c2, l1, l2) != EOF) {
+ if (nscan() != 4)
+ next
+ c1 = max (1, c1)
+ c2 = min (ncols, c2)
+ l1 = max (1, l1)
+ l2 = min (nlines, l2)
+ s = "["//c1//":"//c2//","//l1//":"//l2//"]"
+ mkimage (im//s, "replace", badval, slope=0., sigma=0.)
+ }
+ }
+
+ # Convert to ushort data type
+ chpixtype (im, im, "ushort", oldpixtype="all", ver-)
+
+ # Set image header
+ ccdhedit (im, "exptime", exp, type="real")
+ if (type != "")
+ ccdhedit (im, "imagetyp", type, type="string")
+
+ if (datasec != "") {
+ ccdhedit (im, "datasec", datasec, type="string")
+ }
+ if (trimsec != "")
+ ccdhedit (im, "trimsec", trimsec, type="string")
+ if (biassec != "")
+ ccdhedit (im, "biassec", biassec, type="string")
+ if (filter != "")
+ ccdhedit (im, "subset", filter, type="string")
+end
diff --git a/noao/imred/quadred/src/quad/quadtest/mkimage.par b/noao/imred/quadred/src/quad/quadtest/mkimage.par
new file mode 100644
index 00000000..148bf7ea
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/mkimage.par
@@ -0,0 +1,10 @@
+image,s,a,,,,Image to make or modify
+option,s,a,,"make|replace|add|multiply",,Editing option
+value,r,a,,,,Mean pixel value
+slope,r,h,0.,,,Slope of pixel values
+sigma,r,h,0.,0.,,Noise sigma
+seed,i,h,0,0,,Seed for noise generator
+
+ndim,i,a,,1,7,Number of dimensions
+dims,s,a,,,,Image dimensions
+pixtype,s,h,"real","short|real",,Pixel datatype
diff --git a/noao/imred/quadred/src/quad/quadtest/mkquad.cl b/noao/imred/quadred/src/quad/quadtest/mkquad.cl
new file mode 100644
index 00000000..391d1a61
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/mkquad.cl
@@ -0,0 +1,222 @@
+# MKQUAD -- Make an artifical multi-readout image
+
+procedure mkquad (image, exptime, ccdtype)
+
+begin
+ string im, ccdt
+ real exp, sky
+
+ string amps, as, bs, cs, ds, ts, nampsyx, amplist
+ int tx1, tx2, ty1, ty2
+ int bx1, bx2, by1, by2
+ int cx1, cx2, cy1, cy2
+ int dx1, dx2, dy1, dy2
+ int txs1, txs2, tys1, tys2
+ int bxs1, bxs2, bys1, bys2
+ int nx, ny, dnx, dny, onx, ony
+ int nampx, nampy
+ bool use_amp[4]
+
+ im = image
+ if (access (im//".imh"))
+ error (0, "Output image already exists")
+
+ exp = exptime
+ ccdt = ccdtype
+ sky = skyrate
+ amps = ccdpars.amplifiers
+
+ nx = ccdpars.ncols
+ ny = ccdpars.nlines
+
+ # Set number of amplifiers and use_amp. This is a bit kludgy
+ if (amps == "Quad") {
+ nampx = 2
+ nampy = 2
+ use_amp[1] = yes
+ use_amp[2] = yes
+ use_amp[3] = yes
+ use_amp[4] = yes
+ amplist = "11 12 21 22"
+ } else if (amps == "LowerPair") {
+ nampx = 2
+ nampy = 1
+ use_amp[1] = yes
+ use_amp[2] = yes
+ use_amp[3] = no
+ use_amp[4] = no
+ amplist = "11 12"
+ } else if (amps == "UpperPair") {
+ nampx = 2
+ nampy = 1
+ use_amp[1] = no
+ use_amp[2] = no
+ use_amp[3] = yes
+ use_amp[4] = yes
+ amplist = "21 22"
+ } else if (amps == "LowerLeft") {
+ nampx = 1
+ nampy = 1
+ use_amp[1] = yes
+ use_amp[2] = no
+ use_amp[3] = no
+ use_amp[4] = no
+ amplist = "11"
+ }
+
+ # Parse sections strings.
+ ccdsection (ccdpars.trimsec) | scan (tx1, tx2, ty1, ty2)
+ tx1 = max (1, tx1)
+ tx2 = min (nx, tx2)
+ ty1 = max (1, ty1)
+ ty2 = min (ny, ty2)
+
+ ccdsection (ccdpars.biassec) | scan (bx1, bx2, by1, by2)
+ bx1 = max (1, bx1)
+ bx2 = min (nx, bx2)
+ by1 = max (1, by1)
+ by2 = min (ny, by2)
+
+ ccdsection (ccdpars.datasec) | scan (dx1, dx2, dy1, dy2)
+ dx1 = max (1, dx1)
+ dx2 = min (nx, dx2)
+ dy1 = max (1, dy1)
+ dy2 = min (ny, dy2)
+
+ # Number of pixels to trim
+ txs1 = tx1 - 1
+ txs2 = dx2 - tx2
+ tys1 = ty1 - 1
+ tys2 = dy2 - ty2
+
+ # Number of pixels to skip before overscan strip
+ bxs1 = bx1 - dx2 - 1
+ bxs2 = nx - bx2
+ bys1 = by1 - 1
+ bys2 = ny - by2
+
+ # Number of pixels in subimages
+ nx = nx / nampx
+ ny = ny / nampy
+ dnx = (dx2 - dx1 + 1) / nampx
+ dny = (dy2 - dy1 + 1) / nampy
+ onx = nx - dnx
+ ony = ny
+
+ # Set ampsec for all amps
+ printf ("[1:%d,1:%d]\n", nx, ny) | scan (as)
+
+ # Set sections for Amp11 & Amp21
+ dx1 = 1
+ dx2 = dx1 + dnx - 1
+ dy1 = 1
+ dy2 = dy1 + dny - 1
+ printf ("[%d:%d,%d:%d]\n", dx1, dx2, dy1, dy2) | scan (ds)
+
+ tx1 = dx1 + txs1
+ tx2 = dx2
+ ty1 = dy1 + tys1
+ ty2 = dy2
+ printf ("[%d:%d,%d:%d]\n", tx1, tx2, ty1, ty2) | scan (ts)
+
+ bx1 = dx2 + bxs1 + 1
+ bx2 = nx - bxs2
+ by1 = 1 + bys1
+ by2 = ny
+ printf ("[%d:%d,%d:%d]\n", bx1, bx2, by1, by2) | scan (bs)
+
+ if (use_amp[1]) {
+ mkamp (im//".11", exp, ccdt, ncols=nx, nlines=ny,
+ filter=filter, datasec=ds, trimsec=ts, biassec=bs, imdata=imdata,
+ skyrate=sky, zeroval=ccdpars.zero1, zeroslope=zeroslope,
+ badpix=badpix, badval=badval, flashval=flashval,
+ flashslope=flashslope, darkrate=darkrate, darkslope=darkslope,
+ flatslope=flatslope, gain=ccdpars.gain1, ron=ccdpars.ron1,
+ nonlin=ccdpars.nlin1, poisson=poisson, overwrite=yes)
+ hedit (im//".11", "asec11", as, show-, ver-, add+)
+ cx1 = 1
+ cx2 = cx1 + dnx - 1
+ cy1 = 1
+ cy2 = cy1 + dny - 1
+ printf ("[%d:%d,%d:%d]\n", cx1, cx2, cy1, cy2) | scan (cs)
+ hedit (im//".11", "ccdsec", cs, show-, ver-, add+)
+ }
+
+ if (use_amp[3]) {
+ mkamp (im//".21", exp, ccdt, ncols=nx, nlines=ny,
+ filter=filter, datasec=ds, trimsec=ts, biassec=bs, imdata=imdata,
+ skyrate=sky, zeroval=ccdpars.zero3, zeroslope=zeroslope,
+ badpix=badpix, badval=badval, flashval=flashval,
+ flashslope=flashslope, darkrate=darkrate, darkslope=darkslope,
+ flatslope=flatslope, gain=ccdpars.gain3, ron=ccdpars.ron3,
+ nonlin=ccdpars.nlin3, poisson=poisson, overwrite=yes)
+ hedit (im//".21", "asec21", as, show-, ver-, add+)
+ cx1 = 1
+ cx2 = cx1 + dnx - 1
+ cy1 = dny + 1
+ cy2 = cy1 + dny - 1
+ printf ("[%d:%d,%d:%d]\n", cx1, cx2, cy1, cy2) | scan (cs)
+ hedit (im//".21", "ccdsec", cs, show-, ver-, add+)
+ }
+
+ # Set sections for Amp12 & Amp22
+ dx1 = onx + 1
+ dx2 = nx
+ dy1 = 1
+ dy2 = dy1 + dny - 1
+ printf ("[%d:%d,%d:%d]\n", dx1, dx2, dy1, dy2) | scan (ds)
+
+ tx1 = dx1 + txs1
+ tx2 = dx2
+ ty1 = dy1 + tys1
+ ty2 = dy2
+ printf ("[%d:%d,%d:%d]\n", tx1, tx2, ty1, ty2) | scan (ts)
+
+ bx1 = 1 + bxs1
+ bx2 = onx - bxs2
+ by1 = 1 + bys1
+ by2 = ny
+ printf ("[%d:%d,%d:%d]\n", bx1, bx2, by1, by2) | scan (bs)
+
+ if (use_amp[2]) {
+ mkamp (im//".12", exp, ccdt, ncols=nx, nlines=ny,
+ filter=filter, datasec=ds, trimsec=ts, biassec=bs, imdata=imdata,
+ skyrate=sky, zeroval=ccdpars.zero2, zeroslope=zeroslope,
+ badpix=badpix, badval=badval, flashval=flashval,
+ flashslope=flashslope, darkrate=darkrate, darkslope=darkslope,
+ flatslope=flatslope, gain=ccdpars.gain2, ron=ccdpars.ron2,
+ nonlin=ccdpars.nlin2, poisson=poisson, overwrite=yes)
+ hedit (im//".12", "asec12", as, show-, ver-, add+)
+ cx1 = dnx + 1
+ cx2 = cx1 + dnx - 1
+ cy1 = 1
+ cy2 = cy1 + dny - 1
+ printf ("[%d:%d,%d:%d]\n", cx1, cx2, cy1, cy2) | scan (cs)
+ hedit (im//".12", "ccdsec", cs, show-, ver-, add+)
+ }
+
+ if (use_amp[4]) {
+ mkamp (im//".22", exp, ccdt, ncols=nx, nlines=ny,
+ filter=filter, datasec=ds, trimsec=ts, biassec=bs, imdata=imdata,
+ skyrate=sky, zeroval=ccdpars.zero4, zeroslope=zeroslope,
+ badpix=badpix, badval=badval, flashval=flashval,
+ flashslope=flashslope, darkrate=darkrate, darkslope=darkslope,
+ flatslope=flatslope, gain=ccdpars.gain4, ron=ccdpars.ron4,
+ nonlin=ccdpars.nlin4, poisson=poisson, overwrite=yes)
+ hedit (im//".22", "asec22", as, show-, ver-, add+)
+ cx1 = dnx + 1
+ cx2 = cx1 + dnx - 1
+ cy1 = dny + 1
+ cy2 = cy1 + dny - 1
+ printf ("[%d:%d,%d:%d]\n", cx1, cx2, cy1, cy2) | scan (cs)
+ hedit (im//".22", "ccdsec", cs, show-, ver-, add+)
+ }
+
+ # Set NAMPSYX and amplistin header
+ nampsyx = str (nampy) // " " // str (nampx)
+ hedit (im//".??.imh", "nampsyx", nampsyx, show-, ver-, add+)
+ hedit (im//".??.imh", "amplist", amplist, show-, ver-, add+)
+
+ quadjoin (im, output="", delete=yes)
+
+end
diff --git a/noao/imred/quadred/src/quad/quadtest/mkquad.par b/noao/imred/quadred/src/quad/quadtest/mkquad.par
new file mode 100644
index 00000000..662f315f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/mkquad.par
@@ -0,0 +1,4 @@
+image,s,a,,,,"Image name"
+exptime,r,a,,,,"Exposure time"
+ccdtype,s,a,,,,"CCD type"
+filter,s,h,"",,,"Filter"
diff --git a/noao/imred/quadred/src/quad/quadtest/quadtest.cl b/noao/imred/quadred/src/quad/quadtest/quadtest.cl
new file mode 100644
index 00000000..3129f636
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/quadtest.cl
@@ -0,0 +1,14 @@
+# QUADTEST -- QUAD Test package
+
+# load artdata package (mknoise)
+artdata
+
+package quadtest
+
+task mkimage = quadtest$x_ccdred.e
+task mkamp = quadtest$mkamp.cl
+task mkquad = quadtest$mkquad.cl
+task artobs = quadtest$artobs.cl
+task ccdpars = quadtest$ccdpars.par
+
+clbye()
diff --git a/noao/imred/quadred/src/quad/quadtest/quadtest.par b/noao/imred/quadred/src/quad/quadtest/quadtest.par
new file mode 100644
index 00000000..efe72ef5
--- /dev/null
+++ b/noao/imred/quadred/src/quad/quadtest/quadtest.par
@@ -0,0 +1,20 @@
+# QUADTEST -- package parameter file
+imdata,f,h,"",,,"Image data"
+skyrate,r,h,0.,,,"Sky count rate
+"
+zeroslope,r,h,0.,,,"Slope of zero value"
+flatslope,r,h,0.,,,"Flat field slope
+"
+badpix,f,h,"",,,"Bad pixel regions"
+badval,r,h,0.,,,"Bad pixel value
+"
+flashval,r,h,0.,,,"Preflash level value"
+flashslope,r,h,0.,,,"Slope of preflash level
+"
+darkrate,r,h,0.,,,"Dark count rate"
+darkslope,r,h,0.,,,"Slope of dark count rate
+"
+poisson,b,h,yes,,,"Add Poisson noise"
+seed,i,h,0,,,"Random number seed
+"
+version,s,h,"Version 1.0 - Oct 93","Version 1.0 - Oct 93"
diff --git a/noao/imred/quadred/src/quad/qzerocombine.cl b/noao/imred/quadred/src/quad/qzerocombine.cl
new file mode 100644
index 00000000..b8d554ae
--- /dev/null
+++ b/noao/imred/quadred/src/quad/qzerocombine.cl
@@ -0,0 +1,48 @@
+# ZEROCOMBINE -- Process and combine zero level CCD images.
+
+procedure zerocombine (input)
+
+string input {prompt="List of zero level images to combine"}
+file output="Zero" {prompt="Output zero level name"}
+string combine="average" {prompt="Type of combine operation",
+ enum="average|median"}
+string reject="minmax" {prompt="Type of rejection",
+ enum="none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip"}
+string ccdtype="zero" {prompt="CCD image type to combine"}
+bool process=no {prompt="Process images before combining?"}
+bool delete=no {prompt="Delete input images after combining?"}
+bool clobber=no {prompt="Clobber existing output image?"}
+string scale="none" {prompt="Image scaling",
+ enum="none|mode|median|mean|exposure"}
+string statsec="" {prompt="Image section for computing statistics"}
+int nlow=0 {prompt="minmax: Number of low pixels to reject"}
+int nhigh=1 {prompt="minmax: Number of high pixels to reject"}
+int nkeep=1 {prompt="Minimum to keep (pos) or maximum to reject (neg)"}
+bool mclip=yes {prompt="Use median in sigma clipping algorithms?"}
+real lsigma=3. {prompt="Lower sigma clipping factor"}
+real hsigma=3. {prompt="Upper sigma clipping factor"}
+string rdnoise="0." {prompt="ccdclip: CCD readout noise (electrons)"}
+string gain="1." {prompt="ccdclip: CCD gain (electrons/DN)"}
+string snoise="0." {prompt="ccdclip: Sensitivity noise (fraction)"}
+real pclip=-0.5 {prompt="pclip: Percentile clipping parameter"}
+real blank=0. {prompt="Value if there are no pixels"}
+
+begin
+ string ims
+
+ ims = input
+
+ # Process images first if desired.
+ if (process == YES)
+ quadproc (ims, ccdtype=ccdtype)
+
+ # Combine the flat field images.
+ combine (ims, output=output, plfile="", sigma="", combine=combine,
+ reject=reject, ccdtype=ccdtype, subsets=no, delete=delete,
+ clobber=clobber, project=no, outtype="real", offsets="none",
+ masktype="none", blank=blank, scale=scale, zero="none", weight=no,
+ statsec=statsec, lthreshold=INDEF, hthreshold=INDEF, nlow=nlow,
+ nhigh=nhigh, nkeep=nkeep, mclip=mclip, lsigma=lsigma, hsigma=hsigma,
+ rdnoise=rdnoise, gain=gain, snoise=snoise, sigscale=0.1,
+ pclip=pclip, grow=0)
+end
diff --git a/noao/imred/quadred/src/quad/setinstrument.cl b/noao/imred/quadred/src/quad/setinstrument.cl
new file mode 100644
index 00000000..72361f89
--- /dev/null
+++ b/noao/imred/quadred/src/quad/setinstrument.cl
@@ -0,0 +1,58 @@
+# SETINSTRUMENT -- Set up instrument parameters for the CCD reduction tasks.
+#
+# This task sets default parameters based on an instrument ID.
+
+procedure setinstrument (instrument)
+
+char instrument {prompt="Instrument ID (type ? for a list)"}
+char site="ctio" {prompt="Site ID"}
+char directory="ccddb$" {prompt="Instrument directory"}
+bool review=yes {prompt="Review instrument parameters?"}
+char query {prompt="Instrument ID (type q to quit)",
+ mode="q"}
+
+begin
+ string inst, instdir, instmen, instfile
+
+ # Define instrument directory, menu, and file
+ instdir = directory
+ if (site != "")
+ instdir = instdir // site // "/"
+ instmen = instdir // "instruments.men"
+ inst = instrument
+ instfile = instdir // inst // ".dat"
+
+ # Loop until a valid instrument file is given.
+ while (inst != "" && !access (instfile)) {
+ if (access (instmen))
+ page (instmen)
+ else if (inst == "?")
+ print ("Instrument list ", instmen, " not found")
+ else
+ print ("Instrument file ", instfile, " not found")
+ print ("")
+ inst = query
+ if (inst == "q")
+ return
+ instrument = inst
+ instfile = instdir // inst // ".dat"
+ }
+
+ # Set instrument parameter.
+ if (access (instfile))
+ quadred.instrument = instfile
+ else
+ quadred.instrument = ""
+
+ # Run instrument setup script.
+ instfile = instdir // inst // ".cl"
+ if (access (instfile))
+ cl (< instfile)
+
+ # Review parameters if desired.
+ if (review) {
+ eparam ("quadred")
+ eparam ("qccdproc")
+ eparam ("quadproc")
+ }
+end
diff --git a/noao/imred/quadred/src/quad/test.x b/noao/imred/quadred/src/quad/test.x
new file mode 100644
index 00000000..3df5240a
--- /dev/null
+++ b/noao/imred/quadred/src/quad/test.x
@@ -0,0 +1,71 @@
+include "quadgeom.h"
+
+procedure new ()
+
+char input[SZ_FNAME] #TI Input image name.
+char instrument[SZ_FNAME] #TI Instrument translation file
+
+pointer in, qg
+int xtrim1, xtrim2, ytrim1, ytrim2, xskip1, xskip2
+
+int clgeti
+pointer immap()
+
+begin
+
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Open input image
+ call clgstr ("input", input, SZ_FNAME)
+ in = immap (input, READ_ONLY, 0)
+
+ xtrim1 = clgeti ("xtrim1")
+ xtrim2 = clgeti ("xtrim2")
+ ytrim1 = clgeti ("ytrim1")
+ ytrim2 = clgeti ("ytrim2")
+ xskip1 = clgeti ("xskip1")
+ xskip2 = clgeti ("xskip2")
+
+ # Set-up section translation
+ call quadalloc (qg)
+ call qghdr2 (in, qg)
+ call qguser (qg, xtrim1, xtrim2, ytrim1, ytrim2, xskip1, xskip2)
+ call quaddump (qg)
+
+ # Tidy up
+ call imunmap (in)
+ call quadfree (qg)
+ call hdmclose ()
+end
+
+procedure old ()
+
+char input[SZ_FNAME] #TI Input image name.
+char instrument[SZ_FNAME] #TI Instrument translation file
+
+pointer in, qg
+
+pointer immap()
+
+begin
+
+ # Open instrument file
+ call clgstr ("instrument", instrument, SZ_FNAME)
+ call hdmopen (instrument)
+
+ # Open input image
+ call clgstr ("input", input, SZ_FNAME)
+ in = immap (input, READ_ONLY, 0)
+
+ # Set-up section translation
+ call quadalloc (qg)
+ call quadgeom (in, qg, "", "")
+ call quaddump (qg)
+
+ # Tidy up
+ call imunmap (in)
+ call quadfree (qg)
+ call hdmclose ()
+end
diff --git a/noao/imred/quadred/src/quad/timelog.x b/noao/imred/quadred/src/quad/timelog.x
new file mode 100644
index 00000000..7a8d969f
--- /dev/null
+++ b/noao/imred/quadred/src/quad/timelog.x
@@ -0,0 +1,29 @@
+include <time.h>
+
+
+# TIMELOG -- Prepend a time stamp to the given string.
+#
+# For the purpose of a history logging prepend a short time stamp to the
+# given string. Note that the input string is modified.
+
+procedure timelog (str, max_char)
+
+char str[max_char] # String to be time stamped
+int max_char # Maximum characters in string
+
+pointer sp, time, temp
+long clktime()
+
+begin
+ call smark (sp)
+ call salloc (time, SZ_DATE, TY_CHAR)
+ call salloc (temp, max_char, TY_CHAR)
+
+ call cnvdate (clktime(0), Memc[time], SZ_DATE)
+ call sprintf (Memc[temp], max_char, "%s %s")
+ call pargstr (Memc[time])
+ call pargstr (str)
+ call strcpy (Memc[temp], str, max_char)
+
+ call sfree (sp)
+end
diff --git a/noao/imred/quadred/src/quad/x_quad.x b/noao/imred/quadred/src/quad/x_quad.x
new file mode 100644
index 00000000..8000dabf
--- /dev/null
+++ b/noao/imred/quadred/src/quad/x_quad.x
@@ -0,0 +1,14 @@
+task ccdsection = t_ccdsection,
+ quadsplit = t_quadsplit,
+ quadjoin = t_quadjoin,
+ ccddelete = t_ccddelete,
+ ccdgetparam = ccdgetparam,
+ ccdprcselect = t_ccdprcselect,
+ ccdssselect = t_ccdsubsetselect,
+ qpcalimage = t_qpcalimage,
+ qpselect = t_qpselect,
+ quadscale = t_quadscale,
+ quadsections = t_quadsections,
+ gainmeasure = t_gainmeasure,
+ new = new,
+ old = old