aboutsummaryrefslogtreecommitdiff
path: root/pkg/obsolete
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /pkg/obsolete
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/obsolete')
-rw-r--r--pkg/obsolete/Revisions120
-rw-r--r--pkg/obsolete/doc/imtitle.hlp26
-rw-r--r--pkg/obsolete/doc/mkhistogram.hlp61
-rw-r--r--pkg/obsolete/doc/ofixpix.hlp85
-rw-r--r--pkg/obsolete/doc/oimcombine.hlp1013
-rw-r--r--pkg/obsolete/doc/oimstat.hlp108
-rw-r--r--pkg/obsolete/doc/orfits.hlp164
-rw-r--r--pkg/obsolete/doc/owfits.hlp205
-rw-r--r--pkg/obsolete/doc/radplt.hlp57
-rw-r--r--pkg/obsolete/fits/README1
-rw-r--r--pkg/obsolete/fits/fits_cards.x250
-rw-r--r--pkg/obsolete/fits/fits_params.x234
-rw-r--r--pkg/obsolete/fits/fits_read.x173
-rw-r--r--pkg/obsolete/fits/fits_rheader.x575
-rw-r--r--pkg/obsolete/fits/fits_rimage.x605
-rw-r--r--pkg/obsolete/fits/fits_rpixels.x154
-rw-r--r--pkg/obsolete/fits/fits_wheader.x471
-rw-r--r--pkg/obsolete/fits/fits_wimage.x416
-rw-r--r--pkg/obsolete/fits/fits_wpixels.x162
-rw-r--r--pkg/obsolete/fits/fits_write.x156
-rw-r--r--pkg/obsolete/fits/mkpkg23
-rw-r--r--pkg/obsolete/fits/ranges.x234
-rw-r--r--pkg/obsolete/fits/rfits.com18
-rw-r--r--pkg/obsolete/fits/rfits.h80
-rw-r--r--pkg/obsolete/fits/structure.hlp363
-rw-r--r--pkg/obsolete/fits/t_rfits.x184
-rw-r--r--pkg/obsolete/fits/t_wfits.x216
-rw-r--r--pkg/obsolete/fits/wfits.com15
-rw-r--r--pkg/obsolete/fits/wfits.h113
-rw-r--r--pkg/obsolete/fixcol.gx45
-rw-r--r--pkg/obsolete/fixcol.x248
-rw-r--r--pkg/obsolete/fixline.gx50
-rw-r--r--pkg/obsolete/fixline.x242
-rw-r--r--pkg/obsolete/generic/fixcol.x250
-rw-r--r--pkg/obsolete/generic/fixline.x244
-rw-r--r--pkg/obsolete/generic/mkpkg11
-rw-r--r--pkg/obsolete/imcombine/generic/icaclip.x2198
-rw-r--r--pkg/obsolete/imcombine/generic/icaverage.x337
-rw-r--r--pkg/obsolete/imcombine/generic/iccclip.x1790
-rw-r--r--pkg/obsolete/imcombine/generic/icgdata.x918
-rw-r--r--pkg/obsolete/imcombine/generic/icgrow.x251
-rw-r--r--pkg/obsolete/imcombine/generic/icmedian.x556
-rw-r--r--pkg/obsolete/imcombine/generic/icmm.x612
-rw-r--r--pkg/obsolete/imcombine/generic/icombine.x1645
-rw-r--r--pkg/obsolete/imcombine/generic/icpclip.x878
-rw-r--r--pkg/obsolete/imcombine/generic/icsclip.x1922
-rw-r--r--pkg/obsolete/imcombine/generic/icsigma.x405
-rw-r--r--pkg/obsolete/imcombine/generic/icsort.x1096
-rw-r--r--pkg/obsolete/imcombine/generic/icstat.x880
-rw-r--r--pkg/obsolete/imcombine/generic/mkpkg23
-rw-r--r--pkg/obsolete/imcombine/icaclip.gx573
-rw-r--r--pkg/obsolete/imcombine/icaverage.gx97
-rw-r--r--pkg/obsolete/imcombine/iccclip.gx471
-rw-r--r--pkg/obsolete/imcombine/icgdata.gx235
-rw-r--r--pkg/obsolete/imcombine/icgrow.gx123
-rw-r--r--pkg/obsolete/imcombine/icimstack.x129
-rw-r--r--pkg/obsolete/imcombine/iclog.x384
-rw-r--r--pkg/obsolete/imcombine/icmask.com8
-rw-r--r--pkg/obsolete/imcombine/icmask.x314
-rw-r--r--pkg/obsolete/imcombine/icmedian.gx180
-rw-r--r--pkg/obsolete/imcombine/icmm.gx181
-rw-r--r--pkg/obsolete/imcombine/icombine.com38
-rw-r--r--pkg/obsolete/imcombine/icombine.gx580
-rw-r--r--pkg/obsolete/imcombine/icombine.h52
-rw-r--r--pkg/obsolete/imcombine/icpclip.gx233
-rw-r--r--pkg/obsolete/imcombine/icrmasks.x41
-rw-r--r--pkg/obsolete/imcombine/icscale.x358
-rw-r--r--pkg/obsolete/imcombine/icsclip.gx504
-rw-r--r--pkg/obsolete/imcombine/icsection.x94
-rw-r--r--pkg/obsolete/imcombine/icsetout.x273
-rw-r--r--pkg/obsolete/imcombine/icsigma.gx115
-rw-r--r--pkg/obsolete/imcombine/icsort.gx386
-rw-r--r--pkg/obsolete/imcombine/icstat.gx237
-rw-r--r--pkg/obsolete/imcombine/mkpkg54
-rw-r--r--pkg/obsolete/imcombine/t_imcombine.x501
-rw-r--r--pkg/obsolete/imtitle.par4
-rw-r--r--pkg/obsolete/mkhistogram.par7
-rw-r--r--pkg/obsolete/mkpkg41
-rw-r--r--pkg/obsolete/obsolete.cl14
-rw-r--r--pkg/obsolete/obsolete.hd15
-rw-r--r--pkg/obsolete/obsolete.men11
-rw-r--r--pkg/obsolete/obsolete.par3
-rw-r--r--pkg/obsolete/ofixpix.par5
-rw-r--r--pkg/obsolete/oimcombine.par38
-rw-r--r--pkg/obsolete/oimstat.h50
-rw-r--r--pkg/obsolete/oimstatistics.par6
-rw-r--r--pkg/obsolete/orfits.par13
-rw-r--r--pkg/obsolete/owfits.par14
-rw-r--r--pkg/obsolete/radplt.par5
-rw-r--r--pkg/obsolete/t_fixpix.x172
-rw-r--r--pkg/obsolete/t_imtitle.x21
-rw-r--r--pkg/obsolete/t_mkhgm.x137
-rw-r--r--pkg/obsolete/t_oimstat.x1014
-rw-r--r--pkg/obsolete/t_radplt.x305
-rw-r--r--pkg/obsolete/x_obsolete.x8
95 files changed, 28927 insertions, 0 deletions
diff --git a/pkg/obsolete/Revisions b/pkg/obsolete/Revisions
new file mode 100644
index 00000000..f4a00d74
--- /dev/null
+++ b/pkg/obsolete/Revisions
@@ -0,0 +1,120 @@
+.help revisions Jan92 pkg.obsolete
+.nf
+=====
+V2.12
+=====
+
+obsolete/obsolete.cl
+obsolete/obsolete.men
+obsolete/obsolete.hd
+obsolete/x_obsolete.x
+obsolete/mkpkg
+obsolete/oimstatistics.par
+obsolete/oimstat.h
+obsolete/t_oimstat
+obsolete/doc/oimstat.hlp
+ Added IMSTATISTICS from V2.11.3b. (8/30/01, Davis)
+
+obsolete/obsolete.cl
+obsolete/obsolete.men
+obsolete/obsolete.hd
+obsolete/x_obsolete.x
+obsolete/mkpkg
+obsolete/oimcombine.par +
+obsolete$doc/oimcombine.hlp +
+obsolete$imcombine/ +
+ Added IMCOMBINE from V2.11.3b. (8/17/01, Valdes)
+
+obsolete/obsolete.cl
+obsolete/obsolete.men
+obsolete/obsolete.hd
+obsolete/x_obsolete.x
+obsolete/mkpkg
+obsolete/odisplay.par -
+obsolete$doc/odisplay.hlp -
+obsolete$display/ -
+ Removed ODISPLAY task. (8/17/01, Valdes)
+
+=======
+V2.11.3
+=======
+
+obsolete/obsolete.cl
+obsolete/obsolete.men
+obsolete/obsolete.hd
+obsolete/x_obsolete.x
+obsolete/mkpkg
+obsolete/odisplay.par +
+obsolete$doc/odisplay.hlp +
+obsolete$display/ +
+ Moved the V2.10.4 versions of DISPLAY to OBSOLETE and renamed
+ it to ODISPLAY. (5/29/97, Valdes)
+
+obsolete/obsolete.cl
+obsolete/obsolete.men
+obsolete/obsolete.hd
+obsolete/x_obsolete.x
+obsolete/mkpkg
+obsolete/orfits.par
+obsolete/owfits.par
+obsolete$doc/orfits.par
+obsolete$doc/owfits.par
+obsolete$fits/README
+obsolete$fits/fits_cards.x
+obsolete$fits/fits_params.x
+obsolete$fits/fits_read.x
+obsolete$fits/fits_rheader.x
+obsolete$fits/fits_rimage.x
+obsolete$fits/fits_rpixels.x
+obsolete$fits/fits_wheader.x
+obsolete$fits/fits_wimage.x
+obsolete$fits/fits_wpixels.x
+obsolete$fits/fits_write.x
+obsolete$fits/mkpkg
+obsolete$fits/ranges.x
+obsolete$fits/rfits.com
+obsolete$fits/rfits.h
+obsolete$fits/structure.hlp
+obsolete$fits/t_rfits.x
+obsolete$fits/t_wfits.x
+obsolete$fits/wfits.com
+obsolete$fits/wfits.h
+ Moved the V2.10.4 versions of RFITS and WFITS to OBSOLETE and renamed
+ them to ORFITS and OWFITS. (5/29/97, Davis)
+
+obsolete$doc/ofixpix.hlp
+ Fixed errors in formating. (4/22/97, Valdes)
+
+obsolete$t_fixpix.x +
+obsolete$fixcol.gx +
+obsolete$t_fixline.gx +
+obsolete$ofixpix.par +
+obsolete$doc/ofixpix.hlp +
+obsolete$mkpkg
+obsolete$x_obsolete.x
+obsolete$obsolete.cl
+obsolete$obsolete.hd
+obsolete$obsolete.men
+ Moved the V2.10.4 version of FIXPIX and renamed to OFIXPIX.
+ (6/14/96, Valdes)
+
+obsolete$<imcombine> -
+ The old imcombine task was removed. (6/14/96, Valdes)
+
+=========
+V2.10.4p2
+=========
+
+obsolete$<imcombine>
+ The old imcombine task was added and renamed to oimcombine.
+ (1/30/92, Valdes)
+
+obsolete$* +
+ The obsolete package, PKG.OBSOLETE, was created.
+
+ The tasks MKHISTOGRAM, IMTITLE, and RADPLT were moved out of the old
+ NOAO.PROTO package into the OBSOLETE package as they have been
+ superseded by the PHISTOGRAM, HEDIT, and PRADPROF tasks respectively.
+
+ (1/23/92, Valdes Davis)
+.endhelp
diff --git a/pkg/obsolete/doc/imtitle.hlp b/pkg/obsolete/doc/imtitle.hlp
new file mode 100644
index 00000000..36a1b296
--- /dev/null
+++ b/pkg/obsolete/doc/imtitle.hlp
@@ -0,0 +1,26 @@
+.help imtitle Aug84 obsolete
+.ih
+NAME
+imtitle -- Change the title of an image
+.ih
+USAGE
+imtitle image title
+.ih
+PARAMETERS
+.ls image
+Image to be modified.
+.le
+.ls title
+New image title.
+.le
+.ih
+DESCRIPTION
+The title in \fIimage\fR is changed to \fItitle\fR.
+.ih
+EXAMPLES
+
+ cl> imtitle m1 "M1 U Band"
+.ih
+USE INSTEAD
+images.hedit
+.endhelp
diff --git a/pkg/obsolete/doc/mkhistogram.hlp b/pkg/obsolete/doc/mkhistogram.hlp
new file mode 100644
index 00000000..3bd5e6ca
--- /dev/null
+++ b/pkg/obsolete/doc/mkhistogram.hlp
@@ -0,0 +1,61 @@
+.help mkhistogram Feb88 obsolete
+.ih
+NAME
+mkhistogram -- print or plot the histogram of a data stream
+.ih
+USAGE
+mkhistogram file
+.ih
+PARAMETERS
+.ls file
+The name of the text file containing the data (may be STDIN).
+.le
+.ls nbins
+The number of bins in the histogram.
+.le
+.ls z1 = INDEF, z2 = INDEF
+The minimum and maximum histogram intensity. Z1 and z2 default to the data
+minimum and maximum.
+.le
+.ls listout = yes
+List instead of plot the histogram.
+.le
+.ls device = "stdgraph"
+The output graphics device.
+.le
+.ih
+DESCRIPTION
+MKHISTOGRAM calculates the histogram of the data in the text
+file \fIfile\fR using
+the parameters \fInbins\fR, \fIz1\fR and \fIz2\fR. If the z1 or z2 are
+undefined the image min or max is used. If \fIlistout\fR = no, the
+histogram is plotted on the graphics device specified by \fIdevice\fR.
+Otherwise the histogram is listed on the standard output.
+.ih
+EXAMPLES
+
+1. Output the histogram of data to a file.
+
+.nf
+ cl> mkhisto magsdata nbins=100 > magsdata.hst
+.fi
+
+2. Plot the histogram of data between the 12.0 and 26.0 with a binsize
+ if 0.5 on standard graph. Notice that the extra bin will contain
+ points for which z2 is exactly 26.
+
+.nf
+ cl> mkhist magsdat nbins=29 z1=12.0 z2=26.0 li-
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+USE INSTEAD
+plot.phistogram
+.ih
+SEE ALSO
+images.imhistogram, fields
+.endhelp
diff --git a/pkg/obsolete/doc/ofixpix.hlp b/pkg/obsolete/doc/ofixpix.hlp
new file mode 100644
index 00000000..506dcbe6
--- /dev/null
+++ b/pkg/obsolete/doc/ofixpix.hlp
@@ -0,0 +1,85 @@
+.help ofixpix Jan85 proto
+.ih
+NAME
+ofixpix -- fix bad pixels using a text file (from proto V2.10.4)
+.ih
+USAGE
+.nf
+ofixpix images badpixels
+.fi
+.ih
+PARAMETERS
+.ls image
+List of two dimensional images to be modified.
+.le
+.ls badpixels
+File containing the regions of bad pixels. A region is described by
+four whitespace separated numbers consisting of the first and last columns
+of the bad region and the first and last lines of the bad region.
+.le
+.ls verbose = no
+Print the image names and the bad pixel regions?
+.le
+.ih
+DESCRIPTION
+Bad pixel regions in the list of two dimensional images are replaced by
+linear interpolation using pixels bordering the bad pixel regions.
+The bad pixel regions are input in the specified file consisting of lines
+of coordinates (x1 x2 y1 y2) where x1 and x2 are the first and last columns
+of the bad region and y1 and y2 are the first and last lines of the
+bad region. The file may be STDIN to read from the standard input.
+The type of interpolation is determined as follows:
+
+.ls (1)
+If the bad region spans entire lines then the interpolation is from
+neighboring lines.
+.le
+.ls (2)
+If the bad region spans entire columns then the interpolation is from
+neighboring columns.
+.le
+.ls (3)
+If the bad region contains more lines than columns then the interpolation
+is from neighboring columns.
+.le
+.ls (4)
+If the bad region contains the same or more columns than lines then the
+interpolation is from neighboring lines.
+.le
+
+If the bad region borders the edge of the image then the interpolation
+is by replication of the first good pixel in the direction of interpolation
+and otherwise linear interpolation between the bordering lines or columns
+is used. The verbose parameter may be used to produce of log of the pixel
+modifications.
+.ih
+EXAMPLES
+A detector has bad lines 10 and 25 to 27 and a partial bad column
+at column 31 between lines 35 and 50. A bad region file is created containing
+the lines
+
+.nf
+1 100 10 10
+1 100 25 27
+31 31 35 50
+.fi
+
+The set of images "image*" are fixed by:
+
+ cl> ofixpix image* badpixfile
+.ih
+REVISIONS
+.ls OFIXPIX V2.11
+This is the V2.10.4 and earlier version of PROTO.FIXPIX.
+.le
+.ih
+BUGS
+This is a simple minded task which can be improved by using more sophisticated
+interpolation. The bad pixel file will eventually be replaced by image
+masks and bad pixel lists in the image. Be careful with image sections because
+the bad pixel regions are relative to the image section. Also if the image
+is trimmed or rotated then the bad pixel regions must be changed.
+.ih
+SEE ALSO
+epix, imedit, fixpix
+.endhelp
diff --git a/pkg/obsolete/doc/oimcombine.hlp b/pkg/obsolete/doc/oimcombine.hlp
new file mode 100644
index 00000000..adc95f83
--- /dev/null
+++ b/pkg/obsolete/doc/oimcombine.hlp
@@ -0,0 +1,1013 @@
+.help oimcombine May96 obsolete
+.ih
+NAME
+oimcombine -- Combine images using various algorithms
+.ih
+USAGE
+oimcombine input output
+.ih
+PARAMETERS
+.ls input
+List of input images to combine. All images must have the same dimensionality
+but they may be of different sizes.
+.le
+.ls output
+Output combined image or list of images. If the \fIproject\fR parameter is
+no then there will be one output image while if it is yes there will be one
+output image for each input image.
+.le
+.ls rejmask = "" (optional)
+Output mask file to contain identifications of which pixels in which input
+images were rejected or excluded. The pixel mask will be the size of the
+output image and identified pixels will be in the output image pixel
+coordinate system. There is on extra dimension with length equal to the
+number of input images. Each element of this dimension contains the mask
+of the input image. The order is the order of the input images.
+.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 logfile = "STDOUT" (optional)
+Output log file. If no file is specified then no log information is produced.
+The special filename "STDOUT" prints log information to the terminal.
+.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 described 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|ushort|integer|long|real|double)
+Output image pixel datatype. The pixel datatypes are "double", "real",
+"long", "integer", unsigned short "ushort", and "short" with highest
+precedence first. If none is specified then the highest precedence
+datatype of the input images is used. When there is a mixture of
+short and unsigned short images the highest precedence become integer.
+The datatypes may be abbreviated to
+a single character.
+.le
+.ls offsets = "none" (none|wcs|grid|<filename>)
+Integer offsets to add to each image axes. The options are:
+.ls "none"
+No offsets are applied.
+.le
+.ls "wcs"
+The world coordinate system (wcs) in the image is used to derive the
+offsets. The nearest integer offset that matches the world coordinate
+at the center of the first input image is used.
+.le
+.ls "grid"
+A uniform grid of offsets is specified by a string of the form
+
+.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 <filename>
+The offsets are given in the specified file. The file consists
+of one line per image with the offsets in each dimension forming the
+columns.
+.le
+.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. Note that when
+combining images by projection of the highest dimension only one
+pixel mask is applied to all the images. \fBNote\fR, if the number of
+input images becomes too large (currently about 250 .imh or 125 .hhh
+images) then the images are temporarily stacked and combined by projection
+which also means the bad pixel mask from the first image will be used
+for all images.
+.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, multiply
+by the reciprocal of the mode, median, or mean of the specified statistics
+section, multiply by the reciprocal of the exposure time in the image header,
+multiply by the values in a specified file, or multiply 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, add
+the negative of the mode, median, or mean of the specified statistics
+section, add the values given in a file, or add the 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. File or keyword zero offset
+values do not allow a correction to the weights.
+.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 and the only adjustment made by the task is for the number of
+images previously combined. In this case the weights should be those
+appropriate for the scaled images which would normally be the inverse
+of the variance in the scaled image.
+.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
+.ls expname = ""
+Image header keyword to be used with the exposure scaling and weighting
+options. Also if an exposure keyword is specified that keyword will be
+added to the output image using a weighted average of the input exposure
+values.
+.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. The latter is in addition to pixels
+missing due to non-overlapping offsets, bad pixel masks, or thresholds.
+.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. The noise model for a pixel is:
+
+.nf
+ variance in DN = (rdnoise/gain)^2 + DN/gain + (snoise*DN)^2
+ variance in e- = (rdnoise)^2 + (gain*DN) + (snoise*(gain*DN))^2
+ = rdnoise^2 + Ne + (snoise * Ne)^2
+.fi
+
+where DN is the data number and Ne is the number of electrons. Sensitivity
+noise typically comes from noise introduced during flat fielding.
+.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.
+Radius in pixels for additional pixel to be rejected in an image with a
+rejected pixel from one of the rejection algorithms. This applies only to
+pixels rejected by one of the rejection algorithms and not the masked or
+threshold rejected pixels.
+.le
+.ih
+DESCRIPTION
+A set of images or the highest dimension elements (for example the planes
+in an image cube) 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, possibly determined using the world coordinate system of the
+images, to produce an image bigger than any of the input images.
+
+The input images to be combined are specified by a list. 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. If
+\fBproject\fR is no then the entire input list is combined to form a single
+output image. 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, an image header keyword selected by the \fIexpname\fR parameters
+(which is usually an exposure time) is updated as the weighted average of
+the input header keywords, 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. If there is a mixture of short and unsigned short images then
+the highest precision is integer.
+
+In addition to one or more output combined images there are some optional
+output files which may be specified. A pixel mask identifying each pixel
+rejected or excluded may be created. This mask will match the output
+image in size except there is one extra dimension. The extra dimension
+indexes the input images in the order in which they are specified and
+combined. What this means is that each element of the extra dimension
+is a mask of the pixel rejected in a particular input image (or lower
+dimensional element in the case of projection) but in the offset and
+sized to the output image. For example, if the input consists of
+two dimensional images then the rejected pixel mask will be three
+dimensional and each plane will be for a particular input image.
+If one wants to separate this file the task \fBimslice\fR may be used.
+If there are no offsets then the masks will also be registered with the
+input image. If there are offsets then the masks will be offset
+also.
+
+Another pixel mask may be produced giving just the total number of pixels
+rejected at each output pixel. An image containing the sigmas of the
+pixels combined about the final output combined pixels may also be
+created. 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. Finally a log file may be produced.
+
+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 masks, 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 columns, the first two images in the next 10 columns and
+all three images starting in the 21st column. At the 21st output column
+the 21st column of the first image will be combined with the 11th 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 120
+columns corresponding to the 20 column offset in the third image.
+
+The input image offsets are set using the \fIoffset\fR parameter. There
+are four 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 "wcs" offsets are specified then the world coordinate systems (wcs)
+in the image headers are used to derived the offsets. The world coordinate
+at the center of the first input image is evaluated. Then integer pixel
+offsets are determined for each image to bring the same world coordinate
+to the same point. Note the following caveats. The world coordinate
+systems must be of the same type, orientation, and scale and only the
+nearest integer shift is used.
+
+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 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 needed 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 value of the
+image header keyword specified by the \fIexpname\fR keyword. As implied
+by the parameter name, this is typically the image exposure time since
+intensity levels are linear with the exposure time in CCD detectors.
+Note that the exposure keyword is also updated in the final image
+as the weighted average of the input values. Thus, if one wants to
+use a nonexposure time keyword and keep the exposure time updating
+feature the image header keyword syntax is available; i.e. !<keyword>.
+
+Scaling values may be defined as a list of values in a text file. The file
+name is specified by the standard @file syntax. The list consists of one
+value per line. The order of the list is assumed to be the same as the
+order of the input images. It is a fatal error if the list is incomplete
+and a warning if the list appears longer than the number of input images.
+Because the scale and zero levels are adjusted only the relative
+values are important.
+
+If both an intensity scaling and zero point shift are selected the
+zero point is added first and the scaling is done. This is
+important if the scale and offset values are specified by
+header keywords or from a file of values. However,
+in the log output the zero values are given as the scale times
+the offset hence those numbers would be interpreted as scaling
+first and zero offset second.
+
+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. When scale factors or
+zero point shifts are specified by the user in an @file or
+by an image header keyword no normalization is done.
+
+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. For weights in the case of no scaling or only multiplicative
+scaling the weights are used as given or determined so that images with
+lower signal levels will have lower weights. However, for cases in which
+zero level scaling is used and the zero levels are determined from image
+statistics (not from an input file or keyword) the weights are computed
+from the initial weights (the exposure time, image statistics, or input
+values) using the formula:
+
+.nf
+ weight_final = weight_initial / (scale * sky)
+.fi
+
+where the sky values are those from the image statistics before conversion
+to zero level shifts and adjustment to zero mean over all images. The
+reasoning is that if the zero level is high the sky brightness is high and
+so the S/N is lower and the weight should be lower. If any sky value
+determined from the image statistics comes out to be negative a warning is
+given and the none of the weight are adjusted for sky levels.
+
+The weights are not adjusted when the zero offsets are input from a file
+or keyword since these values do not imply the actual image sky value.
+In this case if one wants to account for different sky statistics
+in the weights the user must specify the weights in a file taking
+explicit account of changes in the weights due to different sky
+statistics.
+
+
+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 \fBoimcombine\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.
+
+In the case of combining the higher dimensions of an image into a
+lower dimensional image, the "project" option, the same pixel mask
+is applied to all of the data being combined; i.e. the same 2D
+pixel mask is applied to every plane of a 3D image. This is because
+a higher dimensional image is treated as a collection of lower
+dimensional images having the same header and hence the same
+bad pixel mask. It would be tempting to use a bad pixel mask with
+the same dimension as the image being projected but this is not
+currently how the task works.
+
+When the number of input images exceeds the maximum number of open files
+allowed by IRAF (currently about 250 or 125 .hhh images) the input images
+are stacked and combined with the \fIproject\fR option. \fBNote\fR that
+this means that the bad pixel mask from the first input image will be
+applied to all the images.
+
+
+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 offsetting, 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 offsetting, 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 nlow=0.1 and nhigh=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 0 0 0 0 0 1
+ nh 0 0 0 0 0 1 1 1 1 1 2
+.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 values (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. The sigma is then computed
+about this estimate (without excluding the low and high values). 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 multiplied 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
+offsetting, masking, or thresholding; for example, if the 3rd 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.
+
+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.
+
+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
+may also be rejected. The number of neighbors to be rejected
+is specified by the \fIgrow\fR parameter which is a radius in pixels.
+If too many pixels are rejected in one of the grown pixels positions
+(as defined by the \fInkeep\fR parameter) then the value of that pixel
+without growing will be used.
+
+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> oimcombine obj* avg combine=average reject=none
+ cl> oimcombine obj* med combine=median reject=none
+.fi
+
+2. To reject cosmic rays:
+
+.nf
+ cl> oimcombine 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> oimcombine @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> oimcombine 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> oimcombine obj* avsig combine=average reject=avsig \
+ >>> scale=exp zero=mode weight=exp expname=exptime
+.fi
+.ih
+REVISIONS
+.ls OIMCOMBINE V2.11.4
+The version of IMCOMBINE from V2.11-V2.11.3 was moved to OBSOLETE.
+.le
+.ih
+LIMITATIONS
+Though the previous limit on the number of images that can be combined
+was removed in V2.11 the method has the limitation that only a single
+bad pixel mask will be used for all images.
+.ih
+SEE ALSO
+immatch.imcombine ccdred.combine onedspec.scombine, wpfc.noisemodel
+.endhelp
diff --git a/pkg/obsolete/doc/oimstat.hlp b/pkg/obsolete/doc/oimstat.hlp
new file mode 100644
index 00000000..2dd23de2
--- /dev/null
+++ b/pkg/obsolete/doc/oimstat.hlp
@@ -0,0 +1,108 @@
+.help oimstatistics Jan90 images.imutil
+.ih
+NAME
+oimstatistics -- compute and print image pixel statistics
+.ih
+USAGE
+oimstatistics images
+.ih
+PARAMETERS
+.ls images
+Images for which pixel statistics are to be computed.
+.le
+.ls fields = "image,npix,mean,stddev,min,max"
+The statistical quantities to be computed and printed.
+.le
+.ls lower = INDEF
+Use only pixels with values greater than or equal to this limit.
+All pixels are above the default value of INDEF.
+.le
+.ls upper = INDEF
+Use only pixels with values less than or equal to this limit.
+All pixels are below the default value of INDEF.
+.le
+.ls binwidth = 0.1
+The width of the histogram bins used for computing the midpoint (estimate
+of the median) and the mode.
+The units are in sigma.
+.le
+.ls format = yes
+Label the output columns and print the result in fixed format. If format
+is "no" no column labels are printed and the output is in free format.
+.le
+.ih
+DESCRIPTION
+The statistical quantities specified by the parameter \fIfields\fR are
+computed and printed for each image in the list specified by \fIimages\fR.
+The results are printed in tabular form with the fields listed in the order
+they are specified in the fields parameter. The available fields are the
+following.
+
+.nf
+ image - the image name
+ npix - the number of pixels used to do the statistics
+ mean - the mean of the pixel distribution
+ midpt - estimate of the median of the pixel distribution
+ mode - the mode of the pixel distribution
+ stddev - the standard deviation of the pixel distribution
+ skew - the skew of the pixel distribution
+ kurtosis - the kurtosis of the pixel distribution
+ min - the minimum pixel value
+ max - the maximum pixel value
+.fi
+
+The mean, standard deviation, skew, kurtosis, min and max are computed in a
+single pass through the image using the expressions listed below.
+Only the quantities selected by the fields parameter are actually computed.
+
+.nf
+ mean = sum (x1,...,xN) / N
+ y = x - mean
+ variance = sum (y1 ** 2,...,yN ** 2) / (N-1)
+ stddev = sqrt (variance)
+ skew = sum ((y1 / stddev) ** 3,...,(yN / stddev) ** 3) / (N-1)
+ kurtosis = sum ((y1 / stddev) ** 4,...,(yN / stddev) ** 4) / (N-1) - 3
+.fi
+
+The midpoint and mode are computed in two passes through the image. In the
+first pass the standard deviation of the pixels is calculated and used
+with the \fIbinwidth\fR parameter to compute the resolution of the data
+histogram. The midpoint is estimated by integrating the histogram and
+computing by interpolation the data value at which exactly half the
+pixels are below that data value and half are above it. The mode is
+computed by locating the maximum of the data histogram and fitting the
+peak by parabolic interpolation.
+
+.ih
+EXAMPLES
+1. To find the number of pixels, mean, standard deviation and the minimum
+and maximum pixel value of a bias region in an image.
+
+.nf
+ cl> oimstat flat*[*,1]
+ # IMAGE NPIX MEAN STDDEV MIN MAX
+ flat1[*,1] 800 999.5 14.09 941. 1062.
+ flat2[*,1] 800 999.4 28.87 918. 1413.
+.fi
+
+The string "flat*" uses a wildcard to select all images beginning with the
+word flat. The string "[*,1]" is an image section selecting row 1.
+
+2. Compute the mean, midpoint, mode and standard deviation of a pixel
+distribution.
+
+.nf
+ cl> oimstat m51 fields="image,mean,midpt,mode,stddev"
+ # IMAGE PIXELS MEAN MIDPT MODE STDDEV
+ M51 262144 108.3 88.75 49.4 131.3
+.fi
+
+.ih
+BUGS
+When using a very large number of pixels the accumulation of the sums
+of the pixel values to the various powers may
+encounter roundoff error. This is significant when the true standard
+deviation is small compared to the mean.
+.ih
+SEE ALSO
+.endhelp
diff --git a/pkg/obsolete/doc/orfits.hlp b/pkg/obsolete/doc/orfits.hlp
new file mode 100644
index 00000000..b5993c73
--- /dev/null
+++ b/pkg/obsolete/doc/orfits.hlp
@@ -0,0 +1,164 @@
+.help orfits Jan90 dataio
+.ih
+NAME
+orfits -- convert FITS data files to IRAF image files
+.ih
+USAGE
+orfits fits_file file_list iraf_file
+.ih
+PARAMETERS
+.ls fits_file
+The FITS data source. This is either a template describing a list of disk files
+or a tape file
+specification of the form mt*[n], where mt indicates a mag tape device,
+* represents a density, and [n] is the tape file number.
+If the tape file number n is specified then only that file
+is converted. If the general tape device name is given, i.e. mta, mtb800, etc,
+then the files specified by the file_list parameter will be read from the tape.
+.le
+.ls file_list
+The files to be read from a tape are specified by the file_list string. The
+string can consist of any sequence of file numbers separated by
+at least one of comma, or dash.
+A dash specifies a range of files. For example the string
+
+ "1,2,3-5,8-6"
+
+will convert the files 1 through 8.
+.le
+.ls iraf_file
+The IRAF file which will receive the FITS data if the make_image parameter
+switch is set. Iraf_file can be a template of output image names or
+a root output image name. In the former case one output image name
+must be specified for every input file. In the latter case iraf_file is
+a root output image name to which the input file sequence number or tape
+file number is appended if the number of input files > 1. For example
+reading files 1 and 3 from a FITS tape with a value of iraf_file of "data"
+will produce the files data0001 and data0003, whereas reading the same
+two files with a value of iraf_file of "data1,data2" will produce the files
+data1 and data2.
+.le
+.ls make_image = yes
+This switch determines whether FITS image data is converted to an IRAF image
+file. This switch is set to no to obtain just header information with the
+long_header or short_header switches.
+.le
+.ls long_header = no
+If this switch is set the full FITS header is printed on the standard output.
+.le
+.ls short_header = yes
+If this switch is set only the output filename,
+the title string, and the image dimensions are printed.
+.le
+.ls datatype
+The IRAF image file may be of a different data type than the FITS image data.
+The data type may be specified as s for short, u for unsigned short,
+i for integer, l for long,
+r for real, and d for double. The user must beware of truncation problems if an
+inappropriate data type is specified. If an incorrect data_type or a
+null string is given for this parameter then a default data type is used
+which is the appropriate minimum size for the input pixel values.
+If the bscale and bzero parameters in the FITS header are undefined or equal to
+1.0 and 0.0 respectively, orfits
+selects datatype s or l depending on bitpix. If bscale and bzero are set to
+other than 1.0 and 0.0, orfits selects datatype r.
+.le
+.ls blank = 0.
+The IRAF image value of a blank pixel.
+.le
+.ls scale = yes
+If scale equals no the integers are read directly off the tape.
+Otherwise ORFITS checks the values of bscale and bzero. If these numbers
+are not 1. and 0. respectively, ORFITS scales the data before output.
+.le
+.ls oldirafname = no
+If the oldirafname switch is set ORFITS will attempt to restore the image to
+disk with the filename defined by the IRAFNAME parameter in the FITS header.
+.le
+.ls offset = 0
+Offset is an integer parameter specifying the offset to the current tape file
+number. For example if offset = 100, iraf_file = "fits" and file_list = "1-3"
+then the output file names will be "fits0101", "fits0102" and "fits0103"
+respectively rather than "fits0001", "fits0002" and "fits0003".
+.le
+.ih
+DESCRIPTION
+FITS data is read from the specified source; either disk or
+magnetic tape. The FITS header may optionally be printed on the standard
+output as either a full listing or a short description.
+The FITS long blocks option is supported.
+At present non-standard FITS files (SIMPLE = F) and files containing
+group data are skipped and a warning message is issued.
+A warning message will be issued if the default user area allocated in
+memory is too small
+to hold all the FITS parameter cards being read in by ORFITS.
+Since the default user area is 8000
+characters and a single card image is 81 characters long, the normal
+user area will hold 98 complete card images. ORFITS will not permit
+partial cards to be written. The user can override the default user area
+length by setting the environment variable min_lenuserarea (see example
+below).
+.ih
+EXAMPLES
+1. Convert a set of FITS files on tape to a set of IRAF image files, allowing
+orfits to select the output datatype. Blanks are set to zero.
+
+.nf
+ cl> orfits mtb1600 1-999 images
+.fi
+
+2. Convert a list of FITS files on disk to a set of IRAF images. In the first
+case the files specified by fits* are written to the images images0001,
+images0002, etc. In the second case the fits disk files listed one per
+line in the text file fitslist are written to the output images listed
+one per line in the file imlist.
+
+.nf
+ cl> orfits fits* * images
+
+ cl. orfits @fitslist * @imlist
+.fi
+
+3. List the contents of a FITS tape on the standard output without creating
+any image files.
+
+.nf
+ cl> orfits mtb1600 1-999 images ma-
+.fi
+
+4. Convert FITS files directly to IRAF images without scaling.
+
+.nf
+ cl> orfits mtb1600 1-999 images scal-
+.fi
+
+5. Convert the first three FITS files on tape to IRAF files setting blanks
+to -1.
+
+.nf
+ cl> orfits mta 1-3 images blan=-1
+.fi
+
+6. Read in a FITS file with a header roughly twice the usual IRAF length
+of 8000 characters.
+
+.nf
+ cl> set min_lenuserarea = 16300
+ cl> orfits mta 1 images
+.fi
+
+7. Read a FITS tape with 5 normal fits records (2880 bytes) to a tape record.
+Notice that no extra parameters are needed.
+
+.nf
+ cl> orfits mta 1-3 fits
+.fi
+
+.ih
+BUGS
+Blank pixels are counted and set to a user determined value, but not flagged
+in the image header.
+.ih
+SEE ALSO
+owfits, reblock, t2d
+.endhelp
diff --git a/pkg/obsolete/doc/owfits.hlp b/pkg/obsolete/doc/owfits.hlp
new file mode 100644
index 00000000..9496192f
--- /dev/null
+++ b/pkg/obsolete/doc/owfits.hlp
@@ -0,0 +1,205 @@
+.help owfits Jan90 dataio
+.ih
+NAME
+owfits -- convert IRAF image files to FITS image files
+.ih
+USAGE
+owfits iraf_files fits_files
+.ih
+PARAMETERS
+.ls iraf_files
+String parameter specifying the input file(s), e.g. "file1" or "file*".
+.le
+.ls fits_files
+String parameter specifying the output destination.
+Magnetic tape output is assumed if the first two characters of fits_files
+are "mt", otherwise the output destination defaults to disk.
+Tape output will begin at the file
+number specified in fits_files, e.g. file 5 if fits_files =
+"mtb1600[5]". Data in file 5 and succeeding files will be overwritten.
+If no tape file number is specified in fits_files, the newtape parameter
+is requested. Tape output will begin at BOT (beginning of tape) if
+newtape = yes, otherwise at EOT (after the double EOF).
+Requesting a tape write at EOT on a blank tape may cause severe problems
+like tape runaway.
+In the case of disk output fits_files may be either a file name template
+or a root filename. In the former case there must be an output fits file
+name for every image. In the latter case the image sequence number is
+appended to fits_files if the number of input images > 1.
+.le
+.ls newtape
+Boolean parameter specifying whether an output tape is blank or contains
+data. Newtape is requested only if no tape file number is specified in
+fits_files, e.g. fits_files = "mtb1600".
+.le
+.ls bscale
+The FITS bscale parameter, defined as p = i * bscale + bzero, where
+p and i are the physical and tape data values respectively.
+The bscale parameter is only requested if the scale switch is set
+and the autoscale switch is turned off.
+.le
+.ls bzero
+The FITS bzero parameter (see bscale for a definition).
+Bzero is only requested if the scale switch is set and the autoscale
+switch is turned off.
+.le
+.ls make_image = yes
+By default owfits writes the FITS image(s) to the output destination.
+If the make_image switch is turned off, owfits prints the FITS headers
+on the standard output and no output file is created. In this way the
+output FITS headers can be examined before actually writing a FITS tape.
+.le
+.ls long_header = no
+If this switch is set the full FITS header will be printed on the standard
+output for each IRAF image converted.
+.le
+.ls short_header = yes
+If this switch is set only a short header, listing files processed and
+their dimensions will be printed on the standard output.
+The long_header switch must be turned off.
+.le
+.ls bitpix = 0
+A bitpix of 8, 16, or 32 will produce either an unsigned byte,
+twos-complement 16 bit integer, or twos-complement 32 bit integer FITS
+image. If bitpix is -32 or
+-64 IEEE real or double precision floating point FITS images are produced.
+If bitpix is set to 0 (the default), owfits will choose one of 8,
+16, 32, -32 or -64 based on the data type of the IRAF image.
+For example a short integer and real image will default to bitpix 16 and
+-32 respectively.
+Users should be wary or overriding the default value of bitpix as loss
+of precision in their data may result. In this case owfits will issue a
+warning message and an estimate of the maximum loss of precision to be
+expected.
+.le
+.ls blocking_factor = 0
+The tape blocking factor for FITS.
+Wfits normally writes \fIblocking_factor\fR * 2880 byte records,
+where \fIblocking_factor\fR is an integer from 1 to 10.
+If \fIblocking_factor\fR = 0, owfits uses the default FITS blocking
+factor specified for the device by the "fb" parameter in the
+file dev$tapecap, or 1 if the "fb" parameter is not present. For
+devices which support variable block sizes, e.g. 9-track tapes, exabytes
+and dats, "fb" is normally set to 10.
+The user may override this value by setting \fIblocking_factor\fR
+>= 1 or <= 10. If the device does not support variable block sizes, e.g.
+various types of cartridge drives, blocks of the size defined for the
+device by the "bs" parameter in the dev$tapecap file are written
+and \fIblocking_factor\fR is ignored.
+.le
+.ls scale = yes
+If the scale switch is set, the IRAF image will be scaled before output.
+Two types of scaling are available. The scaling parameters bscale and
+bzero may be entered by the user (autoscale = no), or the program can
+calculate the appropriate bscale and bzero factors (autoscale = yes).
+If the scale switch is turned off, the IRAF image data is converted
+directly to integers of the specified bitpix with possible loss of
+precision.
+.le
+.ls autoscale = yes
+If the autoscale switch is set, owfits calculates the appropriate bscale and
+bzero factors
+based on the IRAF image data type, and the maximum and minimum
+values of the data.
+.le
+.ih
+DESCRIPTION
+IRAF data is read from disk and written to the specified destination,
+either disk or magnetic tape. The FITS header may optionally be printed
+on the standard output as either a full listing or a short description,
+with or without creating an output image file. If a the default value
+of bitpix (default = 0) is entered, owfits will select the appropriate
+bitpix value based on the precision of the IRAF data. Otherwise the
+user value is used with possible loss of precision. Two data scaling
+options are available. In autoscale mode owfits calculates the appropriate
+scaling factors based on the maximum and minimum data values in the
+IRAF image and the FITS bits per pixel. Alternatively the scaling factors
+can be entered directly. If no scaling is requested the IRAF data values
+will be converted directly to FITS integers or floating point values
+with possible loss of precision.
+.ih
+EXAMPLES
+1. Convert a series of IRAF image files to FITS image files on a blank
+magnetic tape, allowing owfits to select the appropriate bitpix
+and scaling parameters.
+
+.nf
+ cl> owfits iraf_file* mtb1600[1]
+.fi
+
+2. Convert a series of IRAF image files to FITS image files on disk,
+allowing owfits to select the appropriate bitpix and scaling parameters.
+In the first case the images specified by the template are written
+to fits001, fits002 etc. In the second case the list of input images
+specified one per line in the text file imlist are written to the
+files specified one per line in the text file fitslist.
+
+.nf
+ cl> owfits iraf_file* fits
+
+ cl> owfits @imlist @fitslist
+.fi
+
+3. Convert an IRAF image file to a 32 bits per pixel FITS file with no
+scaling and append to a tape already containing data.
+
+.nf
+ cl> owfits iraf_file mtb1600[EOT] bi=32 sc-
+.fi
+
+4. Convert an IRAF image to a 16 bit FITS image on disk, specifying
+bscale and bzero.
+
+.nf
+ cl> owfits iraf_file fits_file bi=16 au- bs=4.0 bz=0.0
+.fi
+
+5. Print the FITS headers on the standard output.
+
+.nf
+ cl> owfits iraf_file* ma-
+.fi
+
+6. Create a disk file called headers containing the FITS headers for a set
+of IRAF image files.
+
+.nf
+ cl> owfits iraf_file* ma- > headers
+.fi
+
+7. Write a FITS tape with 14400 bytes per record (5 2880 FITS records per
+tape block) on a 9-track tape.
+
+.nf
+ cl> owfits images* mtb[1] block=5
+.fi
+
+8. Write a FITS Exabyte tape with a blocking factor of 1 (1 2880 FITS record
+per block). Note that owfits will normally by default write a 28000 (
+10 2880 FITS logical records per block) byte record.
+
+.nf
+ cl> owfits images* mtb[1] block=1
+.fi
+.ih
+BUGS
+OWFITS does not attempt to recover from write errors. When an error is
+detected, OWFITS issues an error message and attempts to write a double
+EOF at the end of the last good record. In this case the last file on
+the tape will be a partial file. IF OWFITS is not successful in writing
+the double EOF, the message "Cannot close magtape file (name)" will be
+issued. Problems occur as some drives permit the double EOF to be
+written after the physical end of tape and some do not. Similarly
+some drives can read a double EOF after end of tape and some cannot. Depending
+on operating system and device driver, an attempt to read or write past
+end of tape may or may not be distinguishable from a normal write error.
+
+Blank pixel values are not correctly handled.
+
+Attempting to write at EOT on a blank tape will at best result in numerous
+error messages being issued and at worst result in tape runaway depending
+on the driver.
+.ih
+SEE ALSO
+orfits, reblock
+.endhelp
diff --git a/pkg/obsolete/doc/radplt.hlp b/pkg/obsolete/doc/radplt.hlp
new file mode 100644
index 00000000..eb98d038
--- /dev/null
+++ b/pkg/obsolete/doc/radplt.hlp
@@ -0,0 +1,57 @@
+.help radplt Dec85 obsolete
+.ih
+NAME
+radplt -- plot a radial profile of a stellar image
+.ih
+USAGE
+radplt input x_init y_init
+.ih
+PARAMETERS
+.ls input
+the list of images which contain the star whose profile is to be plotted
+.le
+.ls x_init
+the approximate column coordinate as a starting point for the centering
+.le
+.ls y_init
+the approximate line (row) coordinate as a starting point for the centering
+.le
+.ls cboxsize = 5
+the size of the extraction box to be used during the centering process
+.le
+.ls rboxsize = 21
+the size of the extraction box to be used for the radial profile. The
+profile will extend to sqrt(2) * rboxsize / 2. This is the length
+of the diagonal from the box center to a corner, and corresponds to about
+14 pixels for the default value.
+.le
+.ih
+DESCRIPTION
+Given the approximate coordinates of the center of a star, (x_init, y_init),
+RADPLT will compute a more accurate center using the algorithms described in
+the Kitt Peak publication "Stellar Magnitudes from Digital Images" under
+the Mountain Photometry Code section and then plot the intensity values
+in the profile extraction box as a function of distance from the center.
+This is effectively a radial profile.
+
+The values for both box sizes should be odd.
+.ih
+EXAMPLES
+The following example plots the profile of a star near (123, 234):
+.sp 1
+.nj
+.nf
+cl> radplt m92red 123 234
+.fi
+.ju
+.ih
+BUGS
+The routine will probably fail if the desired star is within 2 or 3 pixels
+of the image boundary.
+.ih
+USE INSTEAD
+plot.pradprof
+.ih
+SEE ALSO
+imcntr
+.endhelp
diff --git a/pkg/obsolete/fits/README b/pkg/obsolete/fits/README
new file mode 100644
index 00000000..b9c10c7b
--- /dev/null
+++ b/pkg/obsolete/fits/README
@@ -0,0 +1 @@
+The IRAF code for the FITS I/O package.
diff --git a/pkg/obsolete/fits/fits_cards.x b/pkg/obsolete/fits/fits_cards.x
new file mode 100644
index 00000000..fe4829c9
--- /dev/null
+++ b/pkg/obsolete/fits/fits_cards.x
@@ -0,0 +1,250 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "wfits.h"
+
+# WFT_STANDARD_CARD -- Procedure for fetching the minimum header
+# parameters required by fits. The end card is encoded separately.
+
+int procedure wft_standard_card (cardno, im, fits, axisno, card)
+
+int cardno # number of FITS standard card
+pointer im # pointer to the IRAF image
+pointer fits # pointer to the FITS structure
+int axisno # axis number
+char card[ARB] # FITS card image
+
+char keyword[LEN_KEYWORD]
+errchk wft_encodeb, wft_encodei, wft_encodel, wft_encode_axis
+include "wfits.com"
+
+begin
+ # Get mandatory keywords.
+ switch (cardno) {
+ case FIRST_CARD:
+ call wft_encodeb ("SIMPLE", YES, card, "FITS STANDARD")
+ case SECOND_CARD:
+ call wft_encodei ("BITPIX", FITS_BITPIX(fits), card,
+ "FITS BITS/PIXEL")
+ case THIRD_CARD:
+ call wft_encodei ("NAXIS", NAXIS(im), card, "NUMBER OF AXES")
+ default:
+ call wft_encode_axis ("NAXIS", keyword, axisno)
+ call wft_encodel (keyword, NAXISN(im, axisno), card, "")
+ axisno = axisno + 1
+ }
+
+ return (YES)
+end
+
+
+# WFT_OPTION_CARD -- Procedure for fetching optional FITS header parameters.
+# At present these are bscale, bzero, bunit, blank, object, origin, date,
+# irafmax, irafmin, iraf type and iraf bits per pixel. Blank is only encoded
+# if there are a nonzero number of blanks in the IRAF image. Bunit and object
+# are only encoded if the appropriate IRAF strings are defined. Bzero, bscale,
+# irafmax, irafmin, iraf type and iraf bits per pixel are only encoded if
+# there is a pixel file.
+
+int procedure wft_option_card (im, fits, optiono, card)
+
+pointer im # pointer to the IRAF image
+pointer fits # pointer to FITS structure
+int optiono # number of the option card
+char card[ARB] # FITS card image
+
+char datestr[LEN_STRING]
+int len_object, stat
+int strlen()
+errchk wft_encoded, wft_encodec, wft_encode_blank, wft_encoder, wft_encodei
+errchk wft_encode_date
+
+begin
+ stat = YES
+
+ # get optional keywords
+ switch (optiono) {
+ case KEY_BSCALE:
+ if ((NAXIS(im) <= 0) || (FITS_BITPIX(fits) < 0))
+ stat = NO
+ else {
+ call wft_encoded ("BSCALE", BSCALE(fits), card,
+ "REAL = TAPE*BSCALE + BZERO", NDEC_DOUBLE)
+ }
+ case KEY_BZERO:
+ if ((NAXIS(im) <= 0) || (FITS_BITPIX(fits) < 0))
+ stat = NO
+ else
+ call wft_encoded ("BZERO", BZERO(fits), card, "", NDEC_DOUBLE)
+ case KEY_BUNIT:
+ stat = NO
+ case KEY_BLANK:
+ stat = NO
+ #if (NBPIX(im) == 0)
+ #stat = NO
+ #else
+ #call wft_encode_blank ("BLANK", BLANK_STRING(fits), card,
+ #"TAPE VALUE OF BLANK PIXEL")
+ case KEY_OBJECT:
+ if (OBJECT(im) == EOS)
+ stat = NO
+ else {
+ len_object = max (min (LEN_OBJECT, strlen (OBJECT(im))),
+ LEN_STRING)
+ call wft_encodec ("OBJECT", OBJECT(im), len_object, card, "")
+ }
+ case KEY_ORIGIN:
+ call wft_encodec ("ORIGIN", "KPNO-IRAF", LEN_ORIGIN, card, "")
+ case KEY_DATE:
+ call wft_encode_date (datestr, LEN_STRING)
+ call wft_encodec ("DATE", datestr, LEN_STRING, card, "")
+ case KEY_IRAFNAME:
+ len_object = max (min (LEN_OBJECT, strlen (IRAFNAME(fits))),
+ LEN_STRING)
+ call wft_encodec ("IRAFNAME", IRAFNAME(fits), len_object, card,
+ "NAME OF IRAF IMAGE FILE")
+ case KEY_IRAFMAX:
+ if (NAXIS(im) <= 0)
+ stat = NO
+ else
+ call wft_encoder ("IRAF-MAX", IRAFMAX(fits), card, "DATA MAX",
+ NDEC_REAL)
+ case KEY_IRAFMIN:
+ if (NAXIS(im) <= 0)
+ stat = NO
+ else
+ call wft_encoder ("IRAF-MIN", IRAFMIN(fits), card, "DATA MIN",
+ NDEC_REAL)
+ case KEY_IRAFBP:
+ if (NAXIS(im) <= 0)
+ stat = NO
+ else
+ call wft_encodei ("IRAF-BPX", DATA_BITPIX(fits), card,
+ "DATA BITS/PIXEL")
+ case KEY_IRAFTYPE:
+ if (NAXIS(im) <= 0)
+ stat = NO
+ else
+ call wft_encodec ("IRAFTYPE", TYPE_STRING(fits), LEN_STRING,
+ card, "PIXEL TYPE")
+ default:
+ stat = NO
+ }
+
+ optiono = optiono + 1
+
+ return (stat)
+end
+
+
+# WFT_HISTORY_CARD -- Procedure to fetch a single history line, trim newlines
+# and pad with blanks to size LEN_CARD in order to create a FITS HISTORY card.
+
+int procedure wft_history_card (im, hp, card)
+
+pointer im # pointer to the IRAF image
+int hp # pointer to first character to extract from string
+char card[ARB] # FITS card image
+
+char cval
+char chfetch()
+
+begin
+ if (chfetch (HISTORY(im), hp, cval) == EOS)
+ return (NO)
+ else {
+ hp = hp - 1
+ call strcpy ("HISTORY ", card, LEN_KEYWORD)
+ call wft_fits_card (HISTORY(im), hp, card, COL_VALUE - 2, LEN_CARD,
+ '\n')
+ return (YES)
+ }
+end
+
+
+# WFT_UNKNOWN_CARD -- Procedure to fetch a single unknown
+# "line", trim newlines and pad blanks to size LEN_CARD in order to
+# create an unknown keyword card. At present user area information is
+# assumed to be in the form of FITS card images, less then or equal to
+# 80 characters and delimited by a newline.
+
+int procedure wft_unknown_card (im, up, card)
+
+pointer im # pointer to the IRAF image
+int up # pointer to next character in the unknown string
+char card[ARB] # FITS card image
+
+char cval
+int stat, axis, index
+char chfetch()
+int strmatch(), ctoi()
+
+begin
+ if (chfetch (UNKNOWN(im), up, cval) == EOS)
+ return (NO)
+ else {
+ up = up - 1
+ stat = NO
+ while (stat == NO) {
+ call wft_fits_card (UNKNOWN(im), up, card, 1, LEN_CARD, '\n')
+ if (card[1] == EOS)
+ break
+ if (strmatch (card, "^GROUPS ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^SIMPLE ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^BITPIX ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^NAXIS ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^NAXIS") != 0) {
+ index = LEN_NAXIS_KYWRD + 1
+ if (ctoi (card, index, axis) > 0)
+ stat = NO
+ else
+ stat = YES
+ } else if (strmatch (card, "^GCOUNT ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^PCOUNT ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^PSIZE ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^BSCALE ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^BZERO ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^BLANK ") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^IRAF-MAX") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^IRAF-MIN") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^IRAFTYPE") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^IRAF-B/P") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^IRAF-BPX") != 0) {
+ stat = NO
+ } else if (strmatch (card, "^END ") != 0) {
+ stat = NO
+ } else
+ stat = YES
+ }
+
+ return (stat)
+ }
+end
+
+
+# WFT_LAST_CARD -- Procedure to encode the FITS end card.
+
+int procedure wft_last_card (card)
+
+char card[ARB] # FITS card image
+
+begin
+ call sprintf (card, LEN_CARD, "%-8.8s %70w")
+ call pargstr ("END")
+
+ return (YES)
+end
diff --git a/pkg/obsolete/fits/fits_params.x b/pkg/obsolete/fits/fits_params.x
new file mode 100644
index 00000000..e3bf04ba
--- /dev/null
+++ b/pkg/obsolete/fits/fits_params.x
@@ -0,0 +1,234 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <time.h>
+include "wfits.h"
+
+# WFT_ENCODEB -- Procedure to encode a boolean parameter into a FITS card.
+
+procedure wft_encodeb (keyword, param, card, comment)
+
+char keyword[ARB] # FITS keyword
+int param # integer parameter equal to YES/NO
+char card[ARB] # FITS card image
+char comment[ARB] # FITS comment string
+
+char truth
+
+begin
+ if (param == YES)
+ truth = 'T'
+ else
+ truth = 'F'
+
+ call sprintf (card, LEN_CARD, "%-8.8s= %20c / %-45.45s")
+ call pargstr (keyword)
+ call pargc (truth)
+ call pargstr (comment)
+end
+
+
+# WFT_ENCODEI -- Procedure to encode an integer parameter into a FITS card.
+
+procedure wft_encodei (keyword, param, card, comment)
+
+char keyword[ARB] # FITS keyword
+int param # integer parameter
+char card[ARB] # FITS card image
+char comment[ARB] # FITS comment string
+
+begin
+ call sprintf (card, LEN_CARD, "%-8.8s= %20d / %-45.45s")
+ call pargstr (keyword)
+ call pargi (param)
+ call pargstr (comment)
+end
+
+
+# WFT_ENCODEL -- Procedure to encode a long parameter into a FITS card.
+
+procedure wft_encodel (keyword, param, card, comment)
+
+char keyword[ARB] # FITS keyword
+long param # long integer parameter
+char card[ARB] # FITS card image
+char comment[ARB] # FITS comment string
+
+begin
+ call sprintf (card, LEN_CARD, "%-8.8s= %20d / %-45.45s")
+ call pargstr (keyword)
+ call pargl (param)
+ call pargstr (comment)
+end
+
+
+# WFT_ENCODER -- Procedure to encode a real parameter into a FITS card.
+
+procedure wft_encoder (keyword, param, card, comment, precision)
+
+char keyword[ARB] # FITS keyword
+real param # real parameter
+char card[ARB] # FITS card image
+char comment[ARB] # FITS comment card
+int precision # precision of real
+
+begin
+ call sprintf (card, LEN_CARD, "%-8.8s= %20.*e / %-45.45s")
+ call pargstr (keyword)
+ call pargi (precision)
+ call pargr (param)
+ call pargstr (comment)
+end
+
+
+# WFT_ENCODED -- Procedure to encode a double parameter into a FITS card.
+
+procedure wft_encoded (keyword, param, card, comment, precision)
+
+char keyword[ARB] # FITS keyword
+double param # double parameter
+char card[ARB] # FITS card image
+char comment[ARB] # FITS comment string
+int precision # FITS precision
+
+begin
+ call sprintf (card, LEN_CARD, "%-8.8s= %20.*e / %-45.45s")
+ call pargstr (keyword)
+ call pargi (precision)
+ call pargd (param)
+ call pargstr (comment)
+end
+
+
+# WFT_ENCODE_AXIS -- Procedure to add the axis number to axis dependent
+# keywords.
+
+procedure wft_encode_axis (root, keyword, axisno)
+
+char root[ARB] # FITS root keyword
+char keyword[ARB] # FITS keyword
+int axisno # FITS axis number
+
+begin
+ call strcpy (root, keyword, LEN_KEYWORD)
+ call sprintf (keyword, LEN_KEYWORD, "%-5.5s%-3.3s")
+ call pargstr (root)
+ call pargi (axisno)
+end
+
+
+# WFT_ENCODEC -- Procedure to encode an IRAF string parameter into a FITS card.
+
+procedure wft_encodec (keyword, param, maxch, card, comment)
+
+char keyword[ARB] # FITS keyword
+char param[ARB] # FITS string parameter
+int maxch # maximum number of characters in string parameter
+char card[ARB] # FITS card image
+char comment[ARB] # comment string
+
+char strparam[LEN_ALIGN+2]
+int maxchar, nblanks
+
+begin
+ maxchar = min (maxch, LEN_OBJECT)
+ if (maxchar <= LEN_ALIGN - 1) {
+ strparam[1] = '\''
+ call sprintf (strparam[2], maxchar, "%*.*s")
+ call pargi (-maxchar)
+ call pargi (maxchar)
+ call pargstr (param)
+ strparam[maxchar+2] = '\''
+ strparam[maxchar+3] = EOS
+ call sprintf (card, LEN_CARD, "%-8.8s= %-20.20s / %-45.45s")
+ call pargstr (keyword)
+ call pargstr (strparam)
+ call pargstr (comment)
+ } else {
+ nblanks = LEN_OBJECT - maxchar
+ call sprintf (card, LEN_CARD, "%-8.8s= '%*.*s' / %*.*s")
+ call pargstr (keyword)
+ call pargi (-maxchar)
+ call pargi (maxchar)
+ call pargstr (param)
+ call pargi (-nblanks)
+ call pargi (nblanks)
+ call pargstr (comment)
+ }
+end
+
+
+# WFT_ENCODE_BLANK -- Procedure to encode the FITS blank parameter. Necessary
+# because the 32 bit blank value equals INDEFL.
+
+procedure wft_encode_blank (keyword, blank_str, card, comment)
+
+char keyword[ARB] # FITS keyword
+char blank_str[ARB] # string containing values of FITS blank integer
+char card[ARB] # FITS card image
+char comment[ARB] # FITS comment string
+
+begin
+ call sprintf (card, LEN_CARD, "%-8.8s= %20.20s / %-45.45s")
+ call pargstr (keyword)
+ call pargstr (blank_str)
+ call pargstr (comment)
+end
+
+
+# WFT_ENCODE_DATE -- Procedure to encode the date in the form dd-mm-yy.
+
+procedure wft_encode_date (datestr, szdate)
+
+char datestr[ARB] # string containing the date
+int szdate # number of chars in the date string
+
+long ctime
+int time[LEN_TMSTRUCT]
+long clktime()
+
+begin
+ ctime = clktime (long (0))
+ call brktime (ctime, time)
+
+ call sprintf (datestr, szdate, "%02s-%02s-%02s")
+ call pargi (TM_MDAY(time))
+ call pargi (TM_MONTH(time))
+ call pargi (mod (TM_YEAR(time), CENTURY))
+end
+
+
+# WFT_FITS_CARD -- Procedure to fetch a single line from a string parameter
+# padding it to a maximum of maxcols characters and trimmimg the delim
+# character.
+
+procedure wft_fits_card (instr, ip, card, col_out, maxcols, delim)
+
+char instr[ARB] # input string
+int ip # input string pointer, updated at each call
+char card[ARB] # FITS card image
+int col_out # pointer to column in card
+int maxcols # maximum columns in card
+int delim # 1 character string delimiter
+
+int op
+
+begin
+ op = col_out
+
+ # Copy string
+ while (op <= maxcols && instr[ip] != EOS && instr[ip] != delim) {
+ card[op] = instr[ip]
+ ip = ip + 1
+ op = op + 1
+ }
+
+ # Fill remainder of card with blanks
+ while (op <= maxcols ) {
+ card[op] = ' '
+ op = op + 1
+ }
+
+ if (instr[ip] == delim)
+ ip = ip + 1
+
+end
diff --git a/pkg/obsolete/fits/fits_read.x b/pkg/obsolete/fits/fits_read.x
new file mode 100644
index 00000000..bcbdb745
--- /dev/null
+++ b/pkg/obsolete/fits/fits_read.x
@@ -0,0 +1,173 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <imhdr.h>
+include <fset.h>
+include "rfits.h"
+
+# RFT_READ_FITZ -- Convert a FITS file. An EOT is signalled by returning EOF.
+
+int procedure rft_read_fitz (fitsfile, iraffile)
+
+char fitsfile[ARB] # FITS file name
+char iraffile[ARB] # IRAF file name
+
+int fits_fd, stat, min_lenuserarea, ip
+pointer im, sp, fits, envstr
+int rft_read_header(), mtopen(), immap(), strlen(), envfind(), ctoi()
+errchk smark, sfree, salloc, rft_read_header, rft_read_image, rft_find_eof()
+errchk rft_scan_file, mtopen, immap, imdelete, close, imunmap
+
+include "rfits.com"
+
+begin
+ # Open input FITS data.
+ fits_fd = mtopen (fitsfile, READ_ONLY, 0)
+
+ # Allocate memory for program data structure.
+ call smark (sp)
+ call salloc (fits, LEN_FITS, TY_STRUCT)
+ call salloc (envstr, SZ_FNAME, TY_CHAR)
+
+ # Set up for printing a long or a short header.
+ if (long_header == YES || short_header == YES) {
+ if (make_image == YES) {
+ call printf ("File: %s ")
+ call pargstr (iraffile)
+ } else {
+ call printf ("File: %s ")
+ call pargstr (fitsfile)
+ }
+ if (long_header == YES)
+ call printf ("\n")
+ }
+ call flush (STDOUT)
+
+ # Create the IRAF image header. If only a header listing is desired
+ # then map the scratch image onto DEV$NULL (faster than a real file).
+
+ if (make_image == NO)
+ call strcpy ("dev$null", iraffile, SZ_FNAME)
+ if (envfind ("min_lenuserarea", Memc[envstr], SZ_FNAME) > 0) {
+ ip = 1
+ if (ctoi (Memc[envstr], ip, min_lenuserarea) <= 0)
+ min_lenuserarea = LEN_USERAREA
+ else
+ min_lenuserarea = max (LEN_USERAREA, min_lenuserarea)
+ } else
+ min_lenuserarea = LEN_USERAREA
+ im = immap (iraffile, NEW_IMAGE, min_lenuserarea)
+
+ # Read header. EOT is signalled by an EOF status from fits_read_header.
+ # Create an IRAF image if desired.
+
+ iferr {
+ IRAFNAME(fits) = EOS
+ stat = rft_read_header (fits_fd, fits, im)
+ if (stat == EOF)
+ call printf ("End of data\n")
+ else {
+ if (make_image == YES) {
+ call rft_read_image (fits_fd, fits, im)
+ if (fe > 0.0)
+ call rft_find_eof (fits_fd)
+ } else if (fe > 0.0)
+ call rft_scan_file (fits_fd, fits, im, fe)
+ }
+ } then {
+ call flush (STDOUT)
+ call erract (EA_WARN)
+ }
+
+ # Close files and clean up.
+ call imunmap (im)
+
+ # Optionally restore the old IRAF name.
+ if (stat == EOF || make_image == NO) {
+ call imdelete (iraffile)
+ } else if (old_name == YES && strlen (IRAFNAME(fits)) != 0) {
+ iferr {
+ call imgimage (IRAFNAME(fits), IRAFNAME(fits), SZ_FNAME)
+ call imrename (iraffile, IRAFNAME(fits))
+ } then {
+ call printf (" Cannot rename image %s to %s\n")
+ call pargstr (iraffile)
+ call pargstr (IRAFNAME(fits))
+ call flush (STDOUT)
+ call erract (EA_WARN)
+ } else {
+ call printf (" File: %s restored to IRAF File: %s\n")
+ call pargstr (iraffile)
+ call pargstr (IRAFNAME(fits))
+ }
+ }
+
+ if (long_header == YES)
+ call printf ("\n")
+
+ call close (fits_fd)
+ call sfree (sp)
+
+ return (stat)
+end
+
+
+# RFT_FIND_EOF -- Read the FITS data file until EOF is reached.
+
+procedure rft_find_eof (fd)
+
+int fd # the FITS file descriptor
+
+int szbuf
+pointer sp, buf
+int fstati(), read()
+errchk read
+
+begin
+ # Scan through the file.
+ szbuf = fstati (fd, F_BUFSIZE)
+ call smark (sp)
+ call salloc (buf, szbuf, TY_CHAR)
+ while (read (fd, Memc[buf], szbuf) != EOF)
+ ;
+ call sfree (sp)
+end
+
+
+# RFT_SCAN_FILE -- Determine whether it is more efficient to read the
+# entire file or to skip forward to the next file if the parameter
+# make_image was set to no.
+
+procedure rft_scan_file (fd, fits, im, fe)
+
+int fd # the FITS file descriptor
+pointer fits # pointer to the FITS descriptor
+pointer im # pointer to the output image
+real fe # maximum file size in Kb for scan mode
+
+int i, szbuf
+pointer sp, buf
+real file_size
+int fstati(), read()
+errchk read
+
+begin
+ # Compute the file size in Kb and return if it is bigger than fe.
+ file_size = 1.0
+ do i = 1, IM_NDIM(im)
+ file_size = file_size * IM_LEN(im,i)
+ if (IM_NDIM(im) <= 0)
+ file_size = 0.0
+ else
+ file_size = file_size * abs (BITPIX(fits)) / FITS_BYTE / 1.0e3
+ if (file_size >= fe)
+ return
+
+ # Scan through the file.
+ szbuf = fstati (fd, F_BUFSIZE)
+ call smark (sp)
+ call salloc (buf, szbuf, TY_CHAR)
+ while (read (fd, Memc[buf], szbuf) != EOF)
+ ;
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/fits/fits_rheader.x b/pkg/obsolete/fits/fits_rheader.x
new file mode 100644
index 00000000..8efb5562
--- /dev/null
+++ b/pkg/obsolete/fits/fits_rheader.x
@@ -0,0 +1,575 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctype.h>
+include <imhdr.h>
+include <imio.h>
+include <mach.h>
+include "rfits.h"
+
+define NEPSILON 10.0d0 # number of machine epsilon
+
+# RFT_READ_HEADER -- Read a FITS header.
+# If BSCALE and BZERO are different from 1.0 and 0.0 scale is set to true
+# otherwise scale is false.
+# EOT is detected by an EOF on the first read and EOF is returned to the calling
+# routine. Any error is passed to the calling routine.
+
+int procedure rft_read_header (fits_fd, fits, im)
+
+int fits_fd # FITS file descriptor
+pointer fits # FITS data structure
+pointer im # IRAF image descriptor
+
+int i, stat, nread, max_lenuser, fd_usr, ndiscard
+char card[LEN_CARD+1]
+int rft_decode_card(), rft_init_read_pixels(), rft_read_pixels(), strmatch()
+int stropen()
+errchk rft_decode_card, rft_init_read_pixels, rft_read_pixels
+errchk stropen, close
+
+include "rfits.com"
+
+begin
+ # Initialization.
+ SIMPLE(fits) = NO
+ BITPIX(fits) = INDEFI
+ NAXIS(im) = INDEFI
+ do i = 1, IM_MAXDIM
+ IM_LEN(im,i) = INDEFL
+ SCALE(fits) = NO
+ FITS_BSCALE(fits) = 1.0d0
+ FITS_BZERO(fits) = 0.0d0
+ BLANKS(fits) = NO
+ BLANK_VALUE(fits) = INDEFL
+ NRECORDS(fits) = 0
+ ndiscard = 0
+ max_lenuser = (LEN_IMDES + IM_LENHDRMEM(im) - IMU) * SZ_STRUCT - 1
+
+ # The FITS header is character data in FITS_BYTE form. Open the
+ # header for reading. Open the user area which is a character
+ # string as a file.
+
+ i = rft_init_read_pixels (len_record, FITS_BYTE, LSBF, TY_CHAR)
+ fd_usr = stropen (UNKNOWN(im), max_lenuser, NEW_FILE)
+
+ # Loop until the END card is encountered.
+ nread = 0
+ repeat {
+
+ # Read the card.
+ i = rft_read_pixels (fits_fd, card, LEN_CARD, NRECORDS(fits), 1)
+ card[LEN_CARD + 1] = '\n'
+ card[LEN_CARD + 2] = EOS
+
+ # Decode the card images.
+ if ((i == EOF) && (nread == 0)) {
+ return (EOF)
+ } else if ((nread == 0) && strmatch (card, "^SIMPLE ") == 0) {
+ call flush (STDOUT)
+ call error (30,
+ "RFT_READ_HEADER: Not a FITS file (no SIMPLE keyword)")
+ } else if (i != LEN_CARD) {
+ call error (2, "RFT_READ_HEADER: Error reading FITS header")
+ } else
+ nread = nread + 1
+
+ # Remove contaminating control characters and replace with blanks.
+ call rft_control_to_blank (card, card, LEN_CARD)
+
+ # Print FITS card images if long_header option specified.
+ if (long_header == YES) {
+ call printf ("%-80.80s\n")
+ call pargstr (card)
+ }
+
+ # Stat = YES if FITS END card is encountered.
+ stat = rft_decode_card (fits, im, fd_usr, card, ndiscard)
+
+ } until (stat == YES)
+
+ # Print optional short header.
+ if (short_header == YES && long_header == NO) {
+ if (make_image == NO && old_name == YES) {
+ call printf ("(%s) %-20.20s ")
+ call pargstr (IRAFNAME(fits))
+ call pargstr (OBJECT(im))
+ } else {
+ call printf ("%-20.20s ")
+ call pargstr (OBJECT(im))
+ }
+ do i = 1, NAXIS(im) {
+ if (i == 1) {
+ call printf ("Size = %d")
+ call pargl (NAXISN(im,i))
+ } else {
+ call printf (" x %d")
+ call pargl (NAXISN(im,i))
+ }
+ }
+ call printf ("\n")
+ }
+
+ # Let the user know if there is not enough space in the user area.
+ if (ndiscard > 0) {
+ call printf (
+ "Warning: User area too small %d card images discarded\n")
+ call pargi (ndiscard)
+ call rft_last_user (UNKNOWN(im), max_lenuser)
+ }
+
+ call close (fd_usr)
+ return (OK)
+end
+
+
+# RFT_CONTROL_TO_BLANK -- Replace an ACSII control characters in the
+# FITS card image with blanks.
+
+procedure rft_control_to_blank (incard, outcard, len_card)
+
+char incard[ARB] # the input FITS card image
+char outcard[ARB] # the output FITS card image
+int len_card # the length of the FITS card image
+
+int i
+
+begin
+ for (i = 1; i <= len_card; i = i + 1) {
+ if (IS_PRINT(incard[i]))
+ outcard[i] = incard[i]
+ else
+ outcard[i] = ' '
+ }
+end
+
+
+# RFT_DECODE_CARD -- Decode a FITS card and return YES when the END
+# card is encountered. The keywords understood are given in rfits.h.
+
+int procedure rft_decode_card (fits, im, fd_usr, card, ndiscard)
+
+pointer fits # FITS data structure
+pointer im # IRAF image descriptor
+int fd_usr # file descriptor of user area
+char card[ARB] # FITS card
+int ndiscard # Number of cards for which no space available
+
+char cval, str[LEN_CARD]
+double dval
+int nchar, ival, i, j, k, len
+pointer sp, comment
+
+bool rft_equald()
+int strmatch(), ctoi(), ctol(), ctod(), cctoc(), rft_hms()
+errchk putline
+
+include "rfits.com"
+
+begin
+ call smark (sp)
+ call salloc (comment, SZ_LINE, TY_CHAR)
+
+ i = COL_VALUE
+ if (strmatch (card, "^END ") != 0) {
+ call sfree (sp)
+ return(YES)
+ } else if (strmatch (card, "^SIMPLE ") != 0) {
+ if (SIMPLE(fits) == YES)
+ call printf ("Warning: Duplicate SIMPLE keyword ignored\n")
+ else {
+ nchar = cctoc (card, i, cval)
+ if (cval != 'T')
+ call error (13, "RFT_DECODE_CARD: Non-standard FITS format")
+ SIMPLE(fits) = YES
+ }
+ } else if (strmatch (card, "^BITPIX ") != 0) {
+ if (! IS_INDEFI(BITPIX(fits)))
+ call printf ("Warning: Duplicate BITPIX keyword ignored\n")
+ else
+ nchar = ctoi (card, i, BITPIX(fits))
+ } else if (strmatch (card, "^BLANK ") != 0) {
+ BLANKS(fits) = YES
+ nchar = ctol (card, i, BLANK_VALUE(fits))
+ } else if (strmatch (card, "^NAXIS ") != 0) {
+ if (! IS_INDEFI(NAXIS(im)))
+ call printf ("Warning: Duplicate NAXIS keyword ignored\n")
+ else
+ nchar = ctoi (card, i, NAXIS(im))
+ if (NAXIS(im) > IM_MAXDIM)
+ call error (5, "RFT_DECODE_CARD: FITS NAXIS too large")
+ } else if (strmatch (card, "^NAXIS") != 0) {
+ k = strmatch (card, "^NAXIS")
+ nchar = ctoi (card, k, j)
+ if (! IS_INDEFL(NAXISN(im,j))) {
+ call printf ("Warning: Duplicate NAXIS%d keyword ignored\n")
+ call pargi (j)
+ } else
+ nchar = ctol (card, i, NAXISN(im, j))
+ } else if (strmatch (card, "^GROUPS ") != 0) {
+ nchar = cctoc (card, i, cval)
+ if (cval == 'T') {
+ NAXIS(im) = 0
+ call error (6, "RFT_DECODE_CARD: Group data not implemented")
+ }
+ } else if (strmatch (card, "^TABLES ") != 0) {
+ nchar = ctoi (card, i, ival)
+ if (ival > 0)
+ call printf ("Warning: FITS special records not decoded\n")
+ } else if (strmatch (card, "^BSCALE ") != 0) {
+ nchar = ctod (card, i, dval)
+ if (nchar > 0)
+ FITS_BSCALE(fits) = dval
+ else
+ call printf ("Warning: Error decoding BSCALE, BSCALE=1.0\n")
+ if (! rft_equald (dval, 1.0d0) && (scale == YES))
+ SCALE(fits) = YES
+ } else if (strmatch (card, "^BZERO ") != 0) {
+ nchar = ctod (card, i, dval)
+ if (nchar > 0)
+ FITS_BZERO(fits) = dval
+ else
+ call printf ("Warning: Error decoding BZERO, BZERO=0.0\n")
+ if (! rft_equald (dval, 0.0d0) && (scale == YES))
+ SCALE(fits) = YES
+ } else if (strmatch (card, "^OBJECT ") != 0) {
+ call rft_get_fits_string (card, OBJECT(im), SZ_OBJECT)
+ } else if (strmatch (card, "^IRAFNAME") != 0) {
+ call rft_get_fits_string (card, IRAFNAME(fits), SZ_FNAME)
+ } else if (strmatch (card, "^ORIGIN ") != 0) {
+ call rft_trim_card (card, card, LEN_CARD)
+ call strcat (card[i], HISTORY(im), SZ_HISTORY)
+ } else if (strmatch (card, "^DATE ") != 0) {
+ call rft_trim_card (card, card, LEN_CARD)
+ call strcat (card[i], HISTORY(im), SZ_HISTORY)
+ #} else if (strmatch (card, "^HISTORY ") != 0) {
+ #call rft_trim_card (card, card, LEN_CARD)
+ #call strcat (card[i - 2], HISTORY(im), SZ_HISTORY)
+ } else if (strmatch (card, "^UT ") != 0) {
+ len = rft_hms (card, str, Memc[comment], LEN_CARD)
+ if (len > 0) {
+ call wft_encodec ("UT", str, len, card, Memc[comment])
+ card[LEN_CARD+1] = '\n'
+ card[LEN_CARD+2] = EOS
+ }
+ if (ndiscard > 1)
+ ndiscard = ndiscard + 1
+ else {
+ iferr (call putline (fd_usr, card))
+ ndiscard = ndiscard + 1
+ }
+ } else if (strmatch (card, "^ZD ") != 0) {
+ len = rft_hms (card, str, Memc[comment], LEN_CARD)
+ if (len > 0) {
+ call wft_encodec ("ZD", str, len, card, Memc[comment])
+ card[LEN_CARD+1] = '\n'
+ card[LEN_CARD+2] = EOS
+ }
+ if (ndiscard > 1)
+ ndiscard = ndiscard + 1
+ else {
+ iferr (call putline (fd_usr, card))
+ ndiscard = ndiscard + 1
+ }
+ } else if (strmatch (card, "^ST ") != 0) {
+ len = rft_hms (card, str, Memc[comment], LEN_CARD)
+ if (len > 0) {
+ call wft_encodec ("ST", str, len, card, Memc[comment])
+ card[LEN_CARD+1] = '\n'
+ card[LEN_CARD+2] = EOS
+ }
+ if (ndiscard > 1)
+ ndiscard = ndiscard + 1
+ else {
+ iferr (call putline (fd_usr, card))
+ ndiscard = ndiscard + 1
+ }
+ } else if (strmatch (card, "^RA ") != 0) {
+ len = rft_hms (card, str, Memc[comment], LEN_CARD)
+ if (len > 0) {
+ call wft_encodec ("RA", str, len, card, Memc[comment])
+ card[LEN_CARD+1] = '\n'
+ card[LEN_CARD+2] = EOS
+ }
+ if (ndiscard > 1)
+ ndiscard = ndiscard + 1
+ else {
+ iferr (call putline (fd_usr, card))
+ ndiscard = ndiscard + 1
+ }
+ } else if (strmatch (card, "^DEC ") != 0) {
+ len = rft_hms (card, str, Memc[comment], LEN_CARD)
+ if (len > 0) {
+ call wft_encodec ("DEC", str, len, card, Memc[comment])
+ card[LEN_CARD+1] = '\n'
+ card[LEN_CARD+2] = EOS
+ }
+ if (ndiscard > 1)
+ ndiscard = ndiscard + 1
+ else {
+ iferr (call putline (fd_usr, card))
+ ndiscard = ndiscard + 1
+ }
+ } else {
+ if (ndiscard > 1)
+ ndiscard = ndiscard + 1
+ else {
+ iferr (call putline (fd_usr, card))
+ ndiscard = ndiscard + 1
+ }
+ }
+
+ call sfree (sp)
+
+ return (NO)
+
+end
+
+
+# RFT_HMS -- Procedure to decode a FITS HMS card from the mountain.
+
+int procedure rft_hms (card, str, comment, maxch)
+
+char card[ARB] # FITS card
+char str[ARB] # string
+char comment[ARB] # comment string
+int maxch # maximum number of characters
+
+char colon, minus
+int ip, nchar, fst, lst, deg, min
+real sec
+int stridx(), strldx(), strlen(), ctoi(), ctor()
+
+begin
+ # Return if not a FITS string parameter.
+ if (card[COL_VALUE] != '\'')
+ return (0)
+
+ # Set up key characters.
+ colon = ':'
+ minus = '-'
+
+ # Get the FITS string.
+ call rft_get_fits_string (card, str, maxch)
+
+ # Get the comment string.
+ call rft_get_comment (card, comment, maxch)
+
+ # Test for blank string and for 2 colon delimiters.
+ if (str[1] == EOS)
+ return (0)
+ fst = stridx (colon, str)
+ if (fst == 0)
+ return (0)
+ lst = strldx (colon, str)
+ if (lst == 0)
+ return (0)
+ if (fst == lst)
+ return (0)
+
+ # Decode the degrees field.
+ ip = 1
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == '+' || str[ip] == '-')
+ ip = ip + 1
+ nchar = ctoi (str, ip, deg)
+ if (nchar == 0)
+ deg = 0
+
+ # Decode the minutes field.
+ ip = fst + 1
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == '+' || str[ip] == '-')
+ ip = ip + 1
+ nchar = ctoi (str, ip, min)
+ if (nchar == 0)
+ min = 0
+
+ # Decode the seconds field.
+ ip = lst + 1
+ while (IS_WHITE(str[ip]))
+ ip = ip + 1
+ if (str[ip] == '+' || str[ip] == '-')
+ ip = ip + 1
+ nchar = ctor (str, ip, sec)
+ if (nchar == 0)
+ sec = 0.0
+
+ # Reformat the HMS card.
+ if (stridx (minus, str) > 0 || deg < 0 || min < 0 || sec < 0.0) {
+ call sprintf (str, maxch, "%c%d:%02d:%05.2f")
+ call pargc (minus)
+ call pargi (abs (deg))
+ call pargi (abs (min))
+ call pargr (abs (sec))
+ } else {
+ call sprintf (str, maxch, "%2d:%02d:%05.2f")
+ call pargi (deg)
+ call pargi (abs (min))
+ call pargr (abs (sec))
+ }
+
+ return (strlen (str))
+end
+
+
+# RFT_GET_COMMENT -- Extract the comment field from a FITS card.
+
+procedure rft_get_comment (card, comment, maxch)
+
+char card[ARB] # FITS card
+char comment[ARB] # comment string
+int maxch # maximum number of characters
+
+int istart, j
+
+begin
+ istart = 0
+ for (j = LEN_CARD; (j >= 1) && (card[j] != '\''); j = j - 1) {
+ if (card[j] == '/') {
+ for (istart = j + 1; IS_WHITE(card[istart]) && istart <=
+ LEN_CARD; istart = istart + 1)
+ ;
+ break
+ }
+ }
+
+ if (istart == 0)
+ comment[1] = EOS
+ else
+ call strcpy (card[istart], comment, LEN_CARD - istart + 1 )
+end
+
+
+# RFT_GET_FITS_STRING -- Extract a string from a FITS card and trim trailing
+# blanks. The EOS is marked by either ', /, or the end of the card.
+# There may be an optional opening ' (FITS standard).
+
+procedure rft_get_fits_string (card, str, maxchar)
+
+char card[ARB] # FITS card
+char str[ARB] # FITS string
+int maxchar # maximum number of characters
+
+int j, istart, nchar
+
+begin
+ # Check for opening quote
+ for (istart = COL_VALUE; istart <= LEN_CARD && card[istart] != '\'';
+ istart = istart + 1)
+ ;
+ istart = istart + 1
+
+ # Check for closing quote.
+ for (j = istart; (j<LEN_CARD)&&(card[j]!='\''); j = j + 1)
+ ;
+ for (j = j - 1; (j >= istart) && (card[j] == ' '); j = j - 1)
+ ;
+ nchar = min (maxchar, j - istart + 1)
+
+ # Copy the string.
+ if (nchar <= 0)
+ str[1] = EOS
+ else
+ call strcpy (card[istart], str, nchar)
+end
+
+
+# RFT_EQUALD -- Procedure to compare two double precision numbers for equality
+# to within the machine precision for doubles.
+
+bool procedure rft_equald (x, y)
+
+double x, y # the two numbers to be compared for equality
+
+int ex, ey
+double x1, x2, normed_x, normed_y
+
+begin
+ if (x == y)
+ return (true)
+
+ call rft_normd (x, normed_x, ex)
+ call rft_normd (y, normed_y, ey)
+
+ if (ex != ey)
+ return (false)
+ else {
+ x1 = 1.0d0 + abs (normed_x - normed_y)
+ x2 = 1.0d0 + NEPSILON * EPSILOND
+ return (x1 <= x2)
+ }
+end
+
+
+# RFT_NORMED -- Normalize a double precision number x to the value normed_x,
+# in the range [1-10]. Expon is returned such that x = normed_x *
+# (10.0d0 ** expon).
+
+procedure rft_normd (x, normed_x, expon)
+
+double x # number to be normailized
+double normed_x # normalized number
+int expon # exponent
+
+double ax
+
+begin
+ ax = abs (x)
+ expon = 0
+
+ if (ax > 0) {
+ while (ax < (1.0d0 - NEPSILON * EPSILOND)) {
+ ax = ax * 10.0d0
+ expon = expon - 1
+ }
+
+ while (ax >= (10.0d0 - NEPSILON * EPSILOND)) {
+ ax = ax / 10.0d0
+ expon = expon + 1
+ }
+ }
+
+ if (x < 0)
+ normed_x = -ax
+ else
+ normed_x = ax
+end
+
+
+# RFT_TRIM_CARD -- Procedure to trim trailing whitespace from the card
+
+procedure rft_trim_card (incard, outcard, maxch)
+
+char incard[ARB] # input FITS card image
+char outcard[ARB] # output FITS card
+int maxch # maximum size of card
+
+int ip
+
+begin
+ ip = maxch
+ while (incard[ip] == ' ' || incard[ip] == '\t' || incard[ip] == '\0')
+ ip = ip - 1
+ call amovc (incard, outcard, ip)
+ outcard[ip+1] = '\n'
+ outcard[ip+2] = EOS
+end
+
+
+# RFT_LAST_CARD -- Remove a partially written card from the data base
+
+procedure rft_last_user (user, maxch)
+
+char user[ARB] # user area
+int maxch # maximum number of characters
+
+int ip
+
+begin
+ ip = maxch
+ while (user[ip] != '\n')
+ ip = ip - 1
+ user[ip+1] = EOS
+end
diff --git a/pkg/obsolete/fits/fits_rimage.x b/pkg/obsolete/fits/fits_rimage.x
new file mode 100644
index 00000000..e74e2dbb
--- /dev/null
+++ b/pkg/obsolete/fits/fits_rimage.x
@@ -0,0 +1,605 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include <fset.h>
+include "rfits.h"
+
+# RFT_READ_IMAGE -- Convert FITS image pixels to IRAF image pixels.
+
+procedure rft_read_image (fits_fd, fits, im)
+
+int fits_fd # FITS file descriptor
+pointer fits # FITS data structure
+pointer im # IRAF image descriptor
+
+int i, npix, npix_record, blksize, ndummy
+long v[IM_MAXDIM], nlines, il
+pointer tempbuf, buf
+real linemax, linemin, lirafmin, lirafmax
+double dblank
+
+long clktime()
+int fstati(), rft_init_read_pixels(), rft_read_pixels()
+
+errchk malloc, mfree, rft_init_read_pixels, rft_read_pixels, rft_lscale_pix
+errchk rft_lchange_pix, rft_rchange_pix, rfit_dchange_pix, rft_put_image_line
+errchk rft_pix_limits, rft_rscale_pix, rft_dscale_pix
+
+include "rfits.com"
+
+begin
+ # No pixel file was created.
+ if (NAXIS(im) == 0) {
+ call printf ("Warning: No pixel file created\n")
+ return
+ }
+
+ # Initialize the header.
+ call rft_set_image_header (fits, im)
+
+ # Compute the number of columns and lines in the image.
+ npix = NAXISN(im, 1)
+ nlines = 1
+ do i = 2, NAXIS(im)
+ nlines = nlines * NAXISN(im, i)
+ lirafmax = -MAX_REAL
+ lirafmin = MAX_REAL
+
+ # Compute the number of pixels per record and the number of records
+ # per output block.
+
+ npix_record = len_record * FITS_BYTE / abs (BITPIX(fits))
+ blksize = fstati (fits_fd, F_SZBBLK)
+ if (mod (blksize, FITS_RECORD) == 0)
+ blksize = blksize / FITS_RECORD
+ else
+ blksize = 1
+
+ # FITS data is converted to type LONG, REAL or DOUBLE. If BITPIX is
+ # not one of the MII types then rft_read_pixels returns an ERROR.
+
+ call amovkl (long(1), v, IM_MAXDIM)
+ switch (BITPIX(fits)) {
+ case FITS_REAL:
+
+ # Allocate temporary space.
+ call malloc (tempbuf, npix, TY_REAL)
+
+ # Initialize the read.
+ i = rft_init_read_pixels (npix_record, BITPIX(fits), LSBF, TY_REAL)
+
+ # Turn on the ieee NaN mapping.
+ call ieesnanr (blank)
+ #call ieemapr (YES, NO)
+ #call ieezstatr ()
+ NBPIX(im) = 0
+
+ # Allocate the space for the output line, read in the image
+ # line, convert from the ieee to native format, and compute the
+ # minimum and maximum.
+
+ do il = 1, nlines {
+ call rft_put_image_line (im, buf, v, PIXTYPE(im))
+ if (rft_read_pixels (fits_fd, Memr[tempbuf], npix,
+ NRECORDS(fits), blksize) != npix)
+ call printf ("Error reading FITS data\n")
+ if (SCALE(fits) == YES)
+ call rft_rscale_pix (Memr[tempbuf], buf, npix,
+ FITS_BSCALE(fits), FITS_BZERO(fits), PIXTYPE(im))
+ else
+ call rft_rchange_pix (Memr[tempbuf], buf, npix, PIXTYPE(im))
+ call rft_pix_limits (buf, npix, PIXTYPE(im), linemin, linemax)
+ lirafmax = max (lirafmax, linemax)
+ lirafmin = min (lirafmin, linemin)
+ }
+
+ # Set the number of bad pixels.
+ call ieestatr (NBPIX(im), ndummy)
+
+ # Free space.
+ call mfree (tempbuf, TY_REAL)
+
+ case FITS_DOUBLE:
+
+ # Allocate temporary space.
+ call malloc (tempbuf, npix, TY_DOUBLE)
+
+ # Initialize the read.
+ i = rft_init_read_pixels (npix_record, BITPIX(fits), LSBF,
+ TY_DOUBLE)
+
+ # Turn on the ieee NaN mapping.
+ dblank = blank
+ call ieesnand (dblank)
+ #call ieemapd (YES, NO)
+ #call ieezstatd ()
+ NBPIX(im) = 0
+
+ # Allocate the space for the output line, read in the image
+ # line, convert from the ieee to native format, and compute the
+ # minimum and maximum.
+
+ do il = 1, nlines {
+ call rft_put_image_line (im, buf, v, PIXTYPE(im))
+ if (rft_read_pixels (fits_fd, Memd[tempbuf], npix,
+ NRECORDS(fits), blksize) != npix)
+ call printf ("Error reading FITS data\n")
+ if (SCALE(fits) == YES)
+ call rft_dscale_pix (Memd[tempbuf], buf, npix,
+ FITS_BSCALE(fits), FITS_BZERO(fits), PIXTYPE(im))
+ else
+ call rft_dchange_pix (Memd[tempbuf], buf, npix, PIXTYPE(im))
+ call rft_pix_limits (buf, npix, PIXTYPE(im), linemin, linemax)
+ if (IS_INDEFR(linemax))
+ lirafmax = INDEFR
+ else
+ lirafmax = max (lirafmax, linemax)
+ if (IS_INDEFR(linemin))
+ lirafmin = INDEFR
+ else
+ lirafmin = min (lirafmin, linemin)
+ }
+
+ # Set the number of bad pixels.
+ call ieestatd (NBPIX(im), ndummy)
+
+ # Free space.
+ call mfree (tempbuf, TY_DOUBLE)
+
+ default:
+
+ # Allocate the required space.
+ call malloc (tempbuf, npix, TY_LONG)
+
+ # Allocate the space for the output line, read in the image
+ # line, convert from the ieee to native format, and compute the
+ # minimum and maximum.
+
+ i = rft_init_read_pixels (npix_record, BITPIX(fits), LSBF, TY_LONG)
+ do il = 1, nlines {
+ call rft_put_image_line (im, buf, v, PIXTYPE(im))
+ if (rft_read_pixels (fits_fd, Meml[tempbuf], npix,
+ NRECORDS(fits), blksize) != npix)
+ call printf ("Error reading FITS data\n")
+ if (SCALE(fits) == YES)
+ call rft_lscale_pix (Meml[tempbuf], buf, npix,
+ FITS_BSCALE(fits), FITS_BZERO(fits), PIXTYPE(im))
+ else
+ call rft_lchange_pix (Meml[tempbuf], buf, npix, PIXTYPE(im))
+ if (BLANKS(fits) == YES)
+ call rft_map_blanks (Meml[tempbuf], buf, npix, PIXTYPE(im),
+ BLANK_VALUE(fits), blank, NBPIX(im))
+ call rft_pix_limits (buf, npix, PIXTYPE(im), linemin, linemax)
+ lirafmax = max (lirafmax, linemax)
+ lirafmin = min (lirafmin, linemin)
+ }
+
+ # Free space.
+ call mfree (tempbuf, TY_LONG)
+ }
+
+ IRAFMIN(im) = lirafmin
+ IRAFMAX(im) = lirafmax
+ LIMTIME(im) = clktime (long(0))
+
+ if (NBPIX (im) != 0) {
+ call printf ("Warning: %d bad pixels replaced in image\n")
+ call pargl (NBPIX (im))
+ }
+ if (IS_INDEFR(lirafmax) || lirafmax > MAX_REAL) {
+ call printf ("Warning: image contains pixel values > %g\n")
+ call pargr (MAX_REAL)
+ }
+ if (IS_INDEFR(lirafmin) || lirafmin < -MAX_REAL) {
+ call printf ("Warning: image contains pixel values < %g\n")
+ call pargr (-MAX_REAL)
+ }
+end
+
+
+# RFT_SET_IMAGE_HEADER -- Set remaining header fields not set in
+# rft_read_header.
+
+procedure rft_set_image_header (fits, im)
+
+pointer fits # FITS data structure
+pointer im # IRAF image pointer
+
+include "rfits.com"
+
+begin
+ # Determine data type from BITPIX if user data type not specified.
+
+ if (data_type == ERR) {
+ if (BITPIX(fits) < 0) {
+ if (abs (BITPIX(fits)) <= (SZ_REAL * SZB_CHAR * NBITS_BYTE))
+ PIXTYPE(im) = TY_REAL
+ else
+ PIXTYPE(im) = TY_DOUBLE
+ } else if (SCALE(fits) == YES) {
+ PIXTYPE(im) = TY_REAL
+ } else {
+ if (BITPIX(fits) <= (SZ_SHORT * SZB_CHAR * NBITS_BYTE))
+ PIXTYPE(im) = TY_SHORT
+ else
+ PIXTYPE(im) = TY_LONG
+ }
+
+ } else
+ PIXTYPE(im) = data_type
+end
+
+
+# RFT_SET_PRECISION -- Procedure to determine the precision of the FITS data
+# type.
+
+procedure rft_set_precision (bitpix, precision)
+
+int bitpix # FITS bits per pixel
+int precision # FITS decimal digits of precision
+
+begin
+ switch (bitpix) {
+ case FITS_BYTE:
+ precision = FITSB_PREC
+ case FITS_SHORT:
+ precision = FITSS_PREC
+ case FITS_LONG:
+ precision = FITSL_PREC
+ default:
+ call error (16, "RFT_SET_PRECISION: Unknown FITS type")
+ }
+end
+
+
+# RFT_PUT_IMAGE_LINE -- Procedure to output an image line to and IRAF file.
+
+procedure rft_put_image_line (im, buf, v, data_type)
+
+pointer im # IRAF image descriptor
+pointer buf # Pointer to output image line
+long v[ARB] # imio pointer
+int data_type # output pixel type
+
+int impnll(), impnlr(), impnld(), impnlx()
+errchk impnll, impnlr, impnld, impnlx
+
+begin
+ switch (data_type) {
+ case TY_SHORT, TY_INT, TY_USHORT, TY_LONG:
+ if (impnll (im, buf, v) == EOF)
+ call error (3, "RFT_PUT_IMAGE_LINE: Error writing FITS data")
+ case TY_REAL:
+ if (impnlr (im, buf, v) == EOF)
+ call error (3, "RFT_PUT_IMAGE_LINE: Error writing FITS data")
+ case TY_DOUBLE:
+ if (impnld (im, buf, v) == EOF)
+ call error (3, "RFT_PUT_IMAGE_LINE: Error writing FITS data")
+ case TY_COMPLEX:
+ if (impnlx (im, buf, v) == EOF)
+ call error (3, "RFT_PUT_IMAGE_LINE: Error writing FITS data")
+ default:
+ call error (10, "RFT_PUT_IMAGE_LINE: Unsupported IRAF image type")
+ }
+end
+
+
+# RFT_RSCALE_PIX -- Procedure to convert an IRAF image line from type real
+# to the requested output data type with optional scaling using the
+# FITS parameters BSCALE and BZERO.
+
+procedure rft_rscale_pix (inbuf, outbuf, npix, bscale, bzero, data_type)
+
+real inbuf[ARB] # buffer of FITS integers
+pointer outbuf # pointer to output image line
+int npix # number of pixels
+double bscale, bzero # FITS bscale and bzero
+int data_type # IRAF image pixel type
+
+errchk altmdr, achtrl, amovr, achtrd, achtrx
+
+begin
+ switch (data_type) {
+ case TY_SHORT, TY_USHORT, TY_INT, TY_LONG:
+ call altmdr (inbuf, inbuf, npix, bscale, bzero)
+ call achtrl (inbuf, Meml[outbuf], npix)
+ case TY_REAL:
+ call altmdr (inbuf, inbuf, npix, bscale, bzero)
+ call amovr (inbuf, Memr[outbuf], npix)
+ case TY_DOUBLE:
+ call altmdr (inbuf, inbuf, npix, bscale, bzero)
+ call achtrd (inbuf, Memd[outbuf], npix)
+ case TY_COMPLEX:
+ call altmdr (inbuf, inbuf, npix, bscale, bzero)
+ call achtrx (inbuf, Memx[outbuf], npix)
+ default:
+ call error (10, "RFT_SCALE_LINE: Illegal IRAF image type")
+ }
+end
+
+
+# RFT_DSCALE_PIX -- Procedure to convert an IRAF image line from type double
+# to the requested output data type with optional scaling using the
+# FITS parameters BSCALE and BZERO.
+
+procedure rft_dscale_pix (inbuf, outbuf, npix, bscale, bzero, data_type)
+
+double inbuf[ARB] # buffer of FITS integers
+pointer outbuf # pointer to output image line
+int npix # number of pixels
+double bscale, bzero # FITS bscale and bzero
+int data_type # IRAF image pixel type
+
+errchk altmd, achtdl, amovd, achtdr, achtdx
+
+begin
+ switch (data_type) {
+ case TY_SHORT, TY_USHORT, TY_INT, TY_LONG:
+ call altmd (inbuf, inbuf, npix, bscale, bzero)
+ call achtdl (inbuf, Meml[outbuf], npix)
+ case TY_REAL:
+ call altmd (inbuf, inbuf, npix, bscale, bzero)
+ call achtdr (inbuf, Memr[outbuf], npix)
+ case TY_DOUBLE:
+ call altmd (inbuf, inbuf, npix, bscale, bzero)
+ call amovd (inbuf, Memd[outbuf], npix)
+ case TY_COMPLEX:
+ call altmd (inbuf, inbuf, npix, bscale, bzero)
+ call achtdx (inbuf, Memx[outbuf], npix)
+ default:
+ call error (10, "RFT_SCALE_LINE: Illegal IRAF image type")
+ }
+end
+
+
+
+# RFT_LSCALE_PIX -- Procedure to convert an IRAF image line from type long
+# to the requested output data type with optional scaling using the
+# FITS parameters BSCALE and BZERO.
+
+procedure rft_lscale_pix (inbuf, outbuf, npix, bscale, bzero, data_type)
+
+long inbuf[ARB] # buffer of FITS integers
+pointer outbuf # pointer to output image line
+int npix # number of pixels
+double bscale, bzero # FITS bscale and bzero
+int data_type # IRAF image pixel type
+
+errchk achtll, achtlr, achtld, achtlx
+errchk altml, altmr, altmd, altmx
+
+begin
+ switch (data_type) {
+ case TY_SHORT, TY_USHORT, TY_INT, TY_LONG:
+ call achtll (inbuf, Meml[outbuf], npix)
+ call altml (Meml[outbuf], Meml[outbuf], npix, bscale, bzero)
+ case TY_REAL:
+ call altmlr (inbuf, Memr[outbuf], npix, bscale, bzero)
+ #call achtlr (inbuf, Memr[outbuf], npix)
+ #call altmdr (Memr[outbuf], Memr[outbuf], npix, bscale, bzero)
+ case TY_DOUBLE:
+ call achtld (inbuf, Memd[outbuf], npix)
+ call altmd (Memd[outbuf], Memd[outbuf], npix, bscale, bzero)
+ case TY_COMPLEX:
+ call achtlx (inbuf, Memx[outbuf], npix)
+ call altmx (Memx[outbuf], Memx[outbuf], npix, real (bscale),
+ real (bzero))
+ default:
+ call error (10, "RFT_SCALE_LINE: Illegal IRAF image type")
+ }
+end
+
+
+# RFT_RCHANGE_PIX -- Procedure to change a line of real numbers to the
+# IRAF image type.
+
+procedure rft_rchange_pix (inbuf, outbuf, npix, data_type)
+
+real inbuf[ARB] # array of FITS integers
+pointer outbuf # pointer to IRAF image line
+int npix # number of pixels
+int data_type # IRAF pixel type
+
+errchk achtrl, amovr, achtrd, achtrx
+
+begin
+ switch (data_type) {
+ case TY_SHORT, TY_INT, TY_USHORT, TY_LONG:
+ call achtrl (inbuf, Meml[outbuf], npix)
+ case TY_REAL:
+ call amovr (inbuf, Memr[outbuf], npix)
+ case TY_DOUBLE:
+ call achtrd (inbuf, Memd[outbuf], npix)
+ case TY_COMPLEX:
+ call achtrx (inbuf, Memx[outbuf], npix)
+ default:
+ call error (10, "RFT_RCHANGE_LINE: Illegal IRAF image type")
+ }
+end
+
+
+# RFT_DCHANGE_PIX -- Procedure to change a line of double precision numbers
+# to the IRAF image type.
+
+procedure rft_dchange_pix (inbuf, outbuf, npix, data_type)
+
+double inbuf[ARB] # array of FITS integers
+pointer outbuf # pointer to IRAF image line
+int npix # number of pixels
+int data_type # IRAF pixel type
+
+errchk achtdl, achtdr, amovd, achtdx
+
+begin
+ switch (data_type) {
+ case TY_SHORT, TY_INT, TY_USHORT, TY_LONG:
+ call achtdl (inbuf, Meml[outbuf], npix)
+ case TY_REAL:
+ call achtdr (inbuf, Memr[outbuf], npix)
+ case TY_DOUBLE:
+ call amovd (inbuf, Memd[outbuf], npix)
+ case TY_COMPLEX:
+ call achtdx (inbuf, Memx[outbuf], npix)
+ default:
+ call error (10, "RFT_DCHANGE_LINE: Illegal IRAF image type")
+ }
+end
+
+
+
+# RFT_LCHANGE_PIX -- Procedure to change a line of long integers to the
+# IRAF image type.
+
+procedure rft_lchange_pix (inbuf, outbuf, npix, data_type)
+
+long inbuf[ARB] # array of FITS integers
+pointer outbuf # pointer to IRAF image line
+int npix # number of pixels
+int data_type # IRAF pixel type
+
+begin
+ switch (data_type) {
+ case TY_SHORT, TY_USHORT, TY_INT, TY_LONG:
+ call achtll (inbuf, Meml[outbuf], npix)
+ case TY_REAL:
+ call achtlr (inbuf, Memr[outbuf], npix)
+ case TY_DOUBLE:
+ call achtld (inbuf, Memd[outbuf], npix)
+ case TY_COMPLEX:
+ call achtlx (inbuf, Memx[outbuf], npix)
+ default:
+ call error (10, "RFT_CHANGE_LINE: Illegal IRAF image type")
+ }
+end
+
+
+# RFT_MAP_BLANKS -- Map the blank pixels. Currently only the number of blank
+# pixels is determined without an further mapping.
+
+procedure rft_map_blanks (a, buf, npts, pixtype, blank_value, blank, nbadpix)
+
+long a[ARB] # integer input buffer
+pointer buf # pointer to output image buffer
+int npts # number of points
+int pixtype # image data type
+long blank_value # FITS blank value
+real blank # user blank value
+long nbadpix # number of bad pixels
+
+int i
+
+begin
+ # Do blank mapping here
+ switch (pixtype) {
+ case TY_SHORT, TY_INT, TY_USHORT, TY_LONG:
+ do i = 1, npts {
+ if (a[i] == blank_value) {
+ nbadpix = nbadpix + 1
+ Meml[buf+i-1] = blank
+ }
+ }
+ case TY_REAL:
+ do i = 1, npts {
+ if (a[i] == blank_value) {
+ nbadpix = nbadpix + 1
+ Memr[buf+i-1] = blank
+ }
+ }
+ case TY_DOUBLE:
+ do i = 1, npts {
+ if (a[i] == blank_value) {
+ nbadpix = nbadpix + 1
+ Memd[buf+i-1] = blank
+ }
+ }
+ case TY_COMPLEX:
+ do i = 1, npts {
+ if (a[i] == blank_value) {
+ nbadpix = nbadpix + 1
+ Memx[buf+i-1] = blank
+ }
+ }
+ }
+end
+
+
+# RFT_PIX_LIMITS -- Procedure to determine to maxmimum and minimum values in a
+# line. Note that double precision is somewhat of a special case because
+# MAX_DOUBLE is a lot less than the maximum permitted ieee numbers for iraf.
+
+procedure rft_pix_limits (buf, npix, pixtype, linemin, linemax)
+
+pointer buf # pointer to IRAF image line
+int npix # number of pixels
+int pixtype # output data type
+real linemax, linemin # min and max pixel values
+
+long lmax, lmin
+real rmax, rmin
+double dmax, dmin
+complex xmax, xmin
+
+begin
+ switch (pixtype) {
+ case TY_SHORT, TY_INT, TY_USHORT, TY_LONG:
+ call aliml (Meml[buf], npix, lmin, lmax)
+ linemax = lmax
+ linemin = lmin
+ case TY_REAL:
+ call alimr (Memr[buf], npix, rmin, rmax)
+ linemax = rmax
+ linemin = rmin
+ case TY_DOUBLE:
+ call alimd (Memd[buf], npix, dmin, dmax)
+ if (dmax > MAX_REAL)
+ linemax = INDEFR
+ else
+ linemax = dmax
+ if (dmin < -MAX_REAL)
+ linemin = INDEFR
+ else
+ linemin = dmin
+ case TY_COMPLEX:
+ call alimx (Memx[buf], npix, xmin, xmax)
+ linemax = xmax
+ linemin = xmin
+ default:
+ call error (30, "RFT_PIX_LIMITS: Unknown IRAF type")
+ }
+end
+
+
+# ALTMDR -- procedure to scale a long vector into a real vector using
+# double precision constants to preserve accuracy
+
+procedure altmlr (a, b, npix, bscale, bzero)
+
+long a[ARB] # input array
+real b[ARB] # output array
+int npix # number of pixels
+double bscale, bzero # scaling parameters
+
+int i
+
+begin
+ do i = 1, npix
+ b[i] = a[i] * bscale + bzero
+end
+
+
+# ALTMDR -- procedure to scale a real vector with double precision constants.
+
+procedure altmdr (a, b, npix, bscale, bzero)
+
+real a[ARB] # input array
+real b[ARB] # output array
+int npix # number of pixels
+double bscale, bzero # scaling parameters
+
+int i
+
+begin
+ do i = 1, npix
+ b[i] = a[i] * bscale + bzero
+end
diff --git a/pkg/obsolete/fits/fits_rpixels.x b/pkg/obsolete/fits/fits_rpixels.x
new file mode 100644
index 00000000..dfce821d
--- /dev/null
+++ b/pkg/obsolete/fits/fits_rpixels.x
@@ -0,0 +1,154 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include <mii.h>
+include <mach.h>
+
+# RFT_INIT_READ_PIXELS and READ_PIXELS -- Read pixel data with record buffering
+# and data type conversion. The input data must meet the MII standard
+# except for possibly in the case of integers having the least significant
+# byte first.
+#
+# Read data in records of len_record and convert to the specified IRAF
+# data type. Successive calls of rft_read_pixels returns the next npix pixels.
+# Read_pixels returns EOF or the number of pixels converted.
+# Init_read_pixels must be called before read_pixels.
+#
+# Error conditions are:
+# 1. A short input record
+# 2. Error in converting the pixels by miiup.
+#
+# This routine is based on the MII unpack routine which is machine dependent.
+# The bitpix must correspond to an MII type. If the lsbf (least significant
+# byte first) flag is YES then the pixels do not satisfy the MII standard.
+# In this case the bytes are first swapped into most significant byte first
+# before the MII unpack routine is called.
+
+int procedure rft_init_read_pixels (npix_record, bitpix, lsbf, spp_type)
+
+int npix_record # number of pixels per input record
+int bitpix # bits per pixel (must correspond to an MII type)
+int lsbf # byte swap?
+int spp_type # SPP data type to be returned
+
+# entry rft_read_pixels (fd, buffer, npix)
+
+int rft_read_pixels
+int fd # input file descriptor
+char buffer[1] # output buffer
+int npix # number of pixels to read
+
+int swap
+int ty_mii, ty_spp, npix_rec, nch_rec, sz_rec, nchars, len_mii, recptr
+int bufsize, i, n, ip, op
+pointer mii, spp
+
+int rft_getbuf(), sizeof(), miilen()
+errchk miilen, mfree, malloc, rft_getbuf, miiupk
+data mii/NULL/, spp/NULL/
+
+begin
+ ty_mii = bitpix
+ ty_spp = spp_type
+ swap = lsbf
+ npix_rec = npix_record
+ nch_rec = npix_rec * sizeof (ty_spp)
+
+ len_mii = miilen (npix_rec, ty_mii)
+ sz_rec = len_mii * SZ_INT
+
+ if (mii != NULL)
+ call mfree (mii, TY_INT)
+ call malloc (mii, len_mii, TY_INT)
+
+ if (spp != NULL)
+ call mfree (spp, TY_CHAR)
+ call malloc (spp, nch_rec, TY_CHAR)
+
+ ip = nch_rec
+ return (OK)
+
+entry rft_read_pixels (fd, buffer, npix, recptr, bufsize)
+
+ nchars = npix * sizeof (ty_spp)
+ op = 0
+
+ repeat {
+
+ # If data is exhausted read the next record
+ if (ip == nch_rec) {
+
+ i = rft_getbuf (fd, Memi[mii], sz_rec, bufsize, recptr)
+ if (i == EOF)
+ return (EOF)
+
+ if (swap == YES)
+ switch (ty_mii) {
+ case MII_SHORT:
+ call bswap2 (Memi[mii], 1, Memi[mii], 1,
+ sz_rec * SZB_CHAR)
+ case MII_LONG:
+ call bswap4 (Memi[mii], 1, Memi[mii], 1,
+ sz_rec * SZB_CHAR)
+ }
+
+ call miiupk (Memi[mii], Memc[spp], npix_rec, ty_mii, ty_spp)
+
+ ip = 0
+ #recptr = recptr + 1
+ }
+
+ n = min (nch_rec - ip, nchars - op)
+ call amovc (Memc[spp+ip], buffer[1+op], n)
+ ip = ip + n
+ op = op + n
+
+ } until (op == nchars)
+
+ return (npix)
+end
+
+
+# RFT_GETBUF -- Procedure to get the buffer.
+
+int procedure rft_getbuf (fd, buf, sz_rec, bufsize, recptr)
+
+int fd # file descriptor
+char buf[ARB] # buffer to be filled
+int sz_rec # size in chars of record to be read
+int bufsize # buffer size in records
+int recptr # last successful FITS record read
+
+int i, nchars
+int read(), fstati()
+errchk read
+
+begin
+ nchars = 0
+ repeat {
+ iferr {
+ i = read (fd, buf[nchars+1], sz_rec - nchars)
+ } then {
+ call printf ("Error reading FITS record %d\n")
+ if (mod (recptr + 1, bufsize) == 0)
+ call pargi ((recptr + 1) / bufsize)
+ else
+ call pargi ((recptr + 1) / bufsize + 1)
+ call fseti (fd, F_VALIDATE, fstati (fd, F_SZBBLK) / SZB_CHAR)
+ i = read (fd, buf[nchars+1], sz_rec - nchars)
+ }
+
+ if (i == EOF)
+ break
+ else
+ nchars = nchars + i
+
+ } until (nchars >= sz_rec)
+
+ if ((i == EOF) && (nchars == 0))
+ return (EOF)
+ else {
+ recptr = recptr + 1
+ return (nchars)
+ }
+end
diff --git a/pkg/obsolete/fits/fits_wheader.x b/pkg/obsolete/fits/fits_wheader.x
new file mode 100644
index 00000000..f00a0de6
--- /dev/null
+++ b/pkg/obsolete/fits/fits_wheader.x
@@ -0,0 +1,471 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include <fset.h>
+include "wfits.h"
+
+# WFT_WRITE_HEADER -- Write the FITS headers. The FITS header
+# parameters are encoded one by one until the FITS END keyword is detected.
+# If the long_header switch is set the full FITS header is printed on the
+# standard output. If the short header parameter is specified only the image
+# title and dimensions are printed.
+
+procedure wft_write_header (im, fits, fits_fd)
+
+pointer im # pointer to the IRAF image
+pointer fits # pointer to the FITS structure
+int fits_fd # the FITS file descriptor
+
+char card[LEN_CARD+1], trim_card[LEN_CARD+1]
+int nrecords, recntr, cardptr, cardcnt, stat, cards_per_rec, i
+int wft_card_encode(), wft_set_bitpix(), sizeof(), strncmp()
+int wft_init_card_encode(), fstati()
+
+errchk wft_set_bitpix, wft_get_iraf_typestring, wft_set_scale, wft_set_blank
+errchk wft_fits_set_scale, wft_init_card_encode, wft_card_encode
+errchk wft_init_write_pixels, wft_write_pixels, wft_write_last_record
+
+include "wfits.com"
+
+begin
+ # SET the data and FITS bits per pixel.
+
+ DATA_BITPIX(fits) = sizeof (PIXTYPE(im)) * SZB_CHAR * NBITS_BYTE
+ FITS_BITPIX(fits) = wft_set_bitpix (bitpix, PIXTYPE(im),
+ DATA_BITPIX(fits))
+
+ # Calculate the FITS bscale and bzero parameters. Notice for the
+ # time being that scaling is turned off if IEEE floating point
+ # output is selected. May decide to change this later after
+ # checking the specifications.
+
+ if (FITS_BITPIX(fits) < 0) {
+
+ IRAFMIN(fits) = IM_MIN(im)
+ IRAFMAX(fits) = IM_MAX(im)
+ SCALE(fits) = NO
+ BZERO(fits) = 0.0d0
+ BSCALE(fits) = 1.0d0
+
+ } else if (autoscale == YES) {
+
+ call wft_get_tape_limits (FITS_BITPIX(fits), TAPEMIN(fits),
+ TAPEMAX(fits))
+ call wft_data_limits (im, IRAFMIN(fits), IRAFMAX(fits))
+ call wft_fits_set_scale (im, DATA_BITPIX(fits), FITS_BITPIX(fits),
+ IRAFMIN(fits), IRAFMAX(fits), TAPEMIN(fits), TAPEMAX(fits),
+ SCALE(fits), BSCALE(fits), BZERO(fits))
+
+ } else {
+
+ IRAFMIN(fits) = IM_MIN(im)
+ IRAFMAX(fits) = IM_MAX(im)
+ SCALE(fits) = scale
+ BZERO(fits) = bzero
+ BSCALE(fits) = bscale
+ }
+
+ # If blanks in the image set the blank parameter. Currently information
+ # on blanks is not written out so this is effectively a null operation
+ # in IRAF.
+
+ if (NBPIX(im) > 0)
+ call wft_set_blank (FITS_BITPIX(fits), BLANK(fits),
+ BLANK_STRING(fits))
+
+ # Set the IRAF datatype parameter.
+ call wft_get_iraf_typestring (PIXTYPE(im), TYPE_STRING(fits))
+
+ # Initialize the card counters. These counters are used only for
+ # information printed to the standard output.
+
+ recntr = 1
+ cardptr = 1
+ cardcnt = 1
+ cards_per_rec = len_record / LEN_CARD
+
+ # Get set up to write the FITS header. Initialize for an ASCII write.
+ stat = wft_init_card_encode (im, fits)
+ if (make_image == YES)
+ call wft_init_wrt_pixels (len_record, TY_CHAR, FITS_BYTE, blkfac)
+
+ # Print short header.
+ if (short_header == YES && long_header == NO) {
+
+ call printf ("%-20.20s ")
+ call pargstr (OBJECT(im))
+ do i = 1, NAXIS(im) {
+ if (i == 1) {
+ call printf ("Size = %d")
+ call pargl (NAXISN(im,i))
+ } else {
+ call printf (" x %d")
+ call pargl (NAXISN(im,i))
+ }
+ }
+ call printf ("\n")
+
+ call strlwr (TYPE_STRING(fits))
+ call printf ("\tpixtype=%s bitpix=%d")
+ call pargstr (TYPE_STRING(fits))
+ call pargi (FITS_BITPIX(fits))
+
+ if (fstati (fits_fd, F_BLKSIZE) == 0) {
+ call printf (" blkfac=%d")
+ call pargi (blkfac)
+ } else
+ call printf (" blkfac=fixed")
+
+ if (SCALE(fits) == YES) {
+ call printf (" bscale=%.7g bzero=%.7g\n")
+ call pargd (BSCALE(fits))
+ call pargd (BZERO(fits))
+ } else
+ call printf (" scaling=none\n")
+ call strupr (TYPE_STRING(fits))
+ }
+
+ # Write the cards to the FITS header.
+ repeat {
+
+ # Encode the card.
+ stat = wft_card_encode (im, fits, card)
+ if (stat == NO)
+ next
+
+ # Write the card to the output file if make_image is yes.
+ if (make_image == YES)
+ call wft_write_pixels (fits_fd, card, LEN_CARD)
+
+ # Trim the card and write is to the standard output if
+ # long_header is yes.
+
+ if (long_header == YES) {
+ call wft_trimstr (card, trim_card, LEN_CARD)
+ call printf ("%2d/%2d:-- %s\n")
+ call pargi (recntr)
+ call pargi (cardptr)
+ call pargstr (trim_card)
+ }
+
+ if (mod (cardcnt, cards_per_rec) == 0) {
+ recntr = recntr + 1
+ cardptr = 1
+ } else
+ cardptr = cardptr + 1
+ cardcnt = cardcnt + 1
+
+ } until (strncmp (card, "END ", LEN_KEYWORD) == 0)
+
+ # Issue warning about possible precision loss. Comment this out
+ # for time being, since the short header was modified.
+ #if (SCALE(fits) == YES && bitpix != ERR) {
+ #call printf (
+ #"\tDefault bitpix overridden: maximum precision loss ~%.7g\n")
+ #call pargd (BSCALE(fits))
+ #}
+
+ # Write the last header records.
+ if (make_image == YES) {
+ call wft_write_last_record (fits_fd, nrecords)
+ if (short_header == YES || long_header == YES) {
+ call printf ("\t%d Header ")
+ call pargi (nrecords)
+ }
+ }
+end
+
+
+# WFT_SET_BITPIX -- This procedure sets the FITS bitpix for each image based on
+# either the user given value or the precision of the IRAF data. Notice that
+# the user must explicitly set the bitpix parameter to -16 or -32 to select
+# the IEEE output format.
+
+int procedure wft_set_bitpix (bitpix, datatype, data_bitpix)
+
+int bitpix # the user set bits per pixel, ERR or legal bitpix
+int datatype # the IRAF image data type
+int data_bitpix # the bits per pixel in the data
+
+begin
+ if (bitpix == ERR) {
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_USHORT, TY_LONG:
+ if (data_bitpix <= FITS_BYTE)
+ return (FITS_BYTE)
+ else if (data_bitpix <= FITS_SHORT) {
+ if (datatype == TY_USHORT)
+ return (FITS_LONG)
+ else
+ return (FITS_SHORT)
+ } else
+ return (FITS_LONG)
+ case TY_REAL, TY_COMPLEX:
+ return (FITS_REAL)
+ case TY_DOUBLE:
+ return (FITS_DOUBLE)
+ default:
+ call error (2, "SET_BITPIX: Unknown IRAF data type.")
+ }
+ } else
+ return (bitpix)
+end
+
+
+# WFT_GET_IRAF_TYPESTRING -- Procedure to set the iraf datatype keyword.
+# Permitted strings are INTEGER, FLOATING or COMPLEX.
+
+procedure wft_get_iraf_typestring (datatype, type_str)
+
+int datatype # the IRAF data type
+char type_str[ARB] # the output IRAF type string
+
+begin
+ switch (datatype) {
+ case TY_SHORT:
+ call strcpy ("SHORT", type_str, LEN_STRING)
+ case TY_USHORT:
+ call strcpy ("USHORT", type_str, LEN_STRING)
+ case TY_INT:
+ call strcpy ("INTEGER", type_str, LEN_STRING)
+ case TY_LONG:
+ call strcpy ("LONG", type_str, LEN_STRING)
+ case TY_REAL:
+ call strcpy ("REAL", type_str, LEN_STRING)
+ case TY_DOUBLE:
+ call strcpy ("DOUBLE", type_str, LEN_STRING)
+ case TY_COMPLEX:
+ call strcpy ("COMPLEX", type_str, LEN_STRING)
+ default:
+ call error (3, "IRAF_TYPE: Unknown IRAF image type.")
+ }
+end
+
+
+# WFT_FITS_SET_SCALE -- Procedure to set the FITS scaling parameters if
+# autoscaling is enabled.
+
+procedure wft_fits_set_scale (im, data_bitpix, fits_bitpix, irafmin, irafmax,
+ tapemin, tapemax, scale, bscale, bzero )
+
+pointer im # pointer to IRAF image
+int data_bitpix # bits per pixel of data
+int fits_bitpix # fits bits per pixel
+real irafmin # minimum picture value
+real irafmax # maximum picture value
+double tapemin # minimum tape value
+double tapemax # maximum tape value
+int scale # scale data ?
+double bscale # FITS bscale
+double bzero # FITS bzero
+
+errchk wft_set_scale
+
+begin
+ switch (PIXTYPE(im)) {
+ case TY_SHORT, TY_INT, TY_LONG:
+ if (data_bitpix > fits_bitpix) {
+ scale = YES
+ call wft_set_scale (fits_bitpix, irafmin, irafmax, tapemin,
+ tapemax, bscale, bzero)
+ } else {
+ scale = NO
+ bscale = 1.0d0
+ bzero = 0.0d0
+ }
+ case TY_USHORT:
+ if (data_bitpix > fits_bitpix) {
+ scale = YES
+ call wft_set_scale (fits_bitpix, irafmin, irafmax, tapemin,
+ tapemax, bscale, bzero)
+ } else if (data_bitpix == fits_bitpix) {
+ scale = YES
+ bscale = 1.0d0
+ bzero = 3.2768d4
+ } else {
+ scale = NO
+ bscale = 1.0d0
+ bzero = 0.0d0
+ }
+ case TY_REAL, TY_DOUBLE, TY_COMPLEX:
+ scale = YES
+ call wft_set_scale (fits_bitpix, irafmin, irafmax, tapemin, tapemax,
+ bscale, bzero)
+ default:
+ call error (1, "WRT_HEADER: Unknown IRAF image type.")
+ }
+
+end
+
+
+# WFT_SET_SCALE -- This procedure calculates bscale and bzero for each frame
+# from the FITS bitpix and the maximum and minimum data values.
+
+procedure wft_set_scale (fits_bitpix, datamin, datamax, mintape, maxtape,
+ bscale, bzero)
+
+int fits_bitpix # the FITS integer bits per pixels
+real datamax, datamin # the IRAF image data minimum and maximum
+double mintape, maxtape # min and max FITS tape values
+double bscale, bzero # the calculated bscale and bzero values
+
+double maxdata, mindata, num, denom
+bool rft_equald()
+
+begin
+ # Calculate the maximum and minimum values in the data.
+ maxdata = datamax + abs ((datamax / (10.0 ** (NDIGITS_RP - 1))))
+ mindata = datamin - abs ((datamin / (10.0 ** (NDIGITS_RP - 1))))
+ denom = maxtape - mintape
+ num = maxdata - mindata
+ #denom = denom - denom / (1.0d1 ** (NDIGITS_RP - 1))
+ #num = num + num / (1.0d1 ** (NDIGITS_RP - 1))
+
+ # Check for constant image case.
+ mindata = datamin
+ maxdata = datamax
+ if (rft_equald (num, 0.0d0)) {
+ bscale = 1.0d0
+ bzero = maxdata
+ } else {
+ bscale = num / denom
+ bzero = (maxtape / denom) * mindata - (mintape / denom) * maxdata
+ }
+end
+
+
+# WFT_GET_TAPE_LIMITS -- Procedure for calculating the maximum and minimum FITS
+# integer values from the FITS bitpix.
+
+procedure wft_get_tape_limits (fits_bitpix, mintape, maxtape)
+
+int fits_bitpix # the bits per pixel of a FITS integer
+double maxtape, mintape # the maximun and minimum FITS tape integers
+
+begin
+ switch (fits_bitpix) {
+ case FITS_BYTE:
+ maxtape = BYTE_MAX
+ mintape = BYTE_MIN
+ case FITS_SHORT:
+ maxtape = SHORT_MAX
+ mintape = SHORT_MIN
+ case FITS_LONG:
+ maxtape = LONG_MAX
+ mintape = LONG_MIN
+ default:
+ call error (4, "TAPE_LIMITS: Unknown FITS type.")
+ }
+end
+
+
+# WFT_SET_BLANK -- Determine the FITS integer value for a blank pixel from the
+# FITS bitpix. Notice that these are null ops for IEEE floating point format.
+
+procedure wft_set_blank (fits_bitpix, blank, blank_str)
+
+int fits_bitpix # the requested FITS bits per pixel
+long blank # the FITS integer value of a blank pixel
+char blank_str[ARB] # the encoded FITS integer value of a blank pixel
+
+begin
+ switch (fits_bitpix) {
+ case FITS_BYTE:
+ blank = long (BYTE_BLANK)
+ call strcpy ("0", blank_str, LEN_BLANK)
+ case FITS_SHORT:
+ blank = long (SHORT_BLANK)
+ call strcpy ("-32768", blank_str, LEN_BLANK)
+ case FITS_LONG:
+ blank = long (LONG_BLANK)
+ call strcpy ("-2147483648", blank_str, LEN_BLANK)
+ case FITS_REAL:
+ blank = INDEFL
+ call strcpy ("", blank_str, LEN_BLANK)
+ case FITS_DOUBLE:
+ blank = INDEFL
+ call strcpy ("", blank_str, LEN_BLANK)
+ default:
+ call error (5, "SET_BLANK: Unknown FITS type.")
+ }
+end
+
+
+# WFT_INIT_CARD_ENCODE -- This procedure initializes the card encoding
+# procedure. The cards counters are initialized and the number of history cards
+# calculated.
+
+int procedure wft_init_card_encode (im, fits)
+
+# both entry points
+pointer im # pointer to the IRAF image
+pointer fits # pointer to the WFITS structure
+
+# entry wft_card_encode
+int wft_card_encode # entry point
+char card[LEN_CARD+1] # string containing the card image
+
+int cardno, axisno, optiono, hist_ptr, unknown_ptr
+int nstandard, noptions, stat
+int wft_standard_card(), wft_option_card(), wft_last_card()
+int wft_history_card(), wft_unknown_card()
+errchk wft_standard_card, wft_option_card, wft_history_card
+errchk wft_unknown_card, wft_last_card
+
+begin
+ # Initialize the card pointers.
+ cardno = 1
+ axisno = 1
+ optiono = 1
+ unknown_ptr = 1
+ hist_ptr = 1
+
+ # Initilaize the card counters.
+ nstandard = 3 + NAXIS(im)
+ noptions = NOPTIONS + nstandard
+
+ return (YES)
+
+
+# WFT_CARD_ENCODE -- Procedure to encode the FITS header parameters into
+# FITS card images.
+
+entry wft_card_encode (im, fits, card)
+
+ # Fetch the appropriate FITS header card image.
+ if (cardno <= nstandard) {
+ stat = wft_standard_card (cardno, im, fits, axisno, card)
+ } else if (cardno <= noptions) {
+ stat = wft_option_card (im, fits, optiono, card)
+ } else if (wft_unknown_card (im, unknown_ptr, card) == YES) {
+ stat = YES
+ } else if (wft_history_card (im, hist_ptr, card) == YES) {
+ stat = YES
+ } else {
+ stat = wft_last_card (card)
+ }
+
+ cardno = cardno + 1
+
+ return (stat)
+end
+
+
+# WFT_TRIMSTR -- Procedure to trim trailing blanks from a fixed size string.
+
+procedure wft_trimstr (instr, outstr, nchars)
+
+char instr[ARB] # input string
+char outstr[ARB] # output string
+int nchars # last character of instr
+
+int ip
+
+begin
+ call strcpy (instr, outstr, nchars)
+ ip = nchars
+ while (outstr[ip] == ' ')
+ ip = ip - 1
+ outstr[ip+1] = EOS
+end
diff --git a/pkg/obsolete/fits/fits_wimage.x b/pkg/obsolete/fits/fits_wimage.x
new file mode 100644
index 00000000..539114ea
--- /dev/null
+++ b/pkg/obsolete/fits/fits_wimage.x
@@ -0,0 +1,416 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <imhdr.h>
+include "wfits.h"
+
+# WFT_WRITE_IMAGE -- Procedure to convert IRAF image data to FITS format line by
+# line.
+
+procedure wft_write_image (im, fits, fits_fd)
+
+pointer im # IRAF image descriptor
+pointer fits # FITS data structure
+int fits_fd # FITS file descriptor
+
+int npix, nlines, npix_record, i, stat, nrecords
+long v[IM_MAXDIM]
+pointer tempbuf, buf
+
+int wft_get_image_line()
+errchk malloc, mfree, wft_get_image_line, wft_lscale_line, wft_long_line
+errchk wft_init_write_pixels, wft_write_pixels, wft_write_last_record
+errchk wft_rscale_line, wft_dscale_line
+
+include "wfits.com"
+
+begin
+ if (NAXIS(im) == 0)
+ return
+
+ # Initialize.
+ npix = NAXISN(im,1)
+ nlines = 1
+ do i = 2, NAXIS(im)
+ nlines = nlines * NAXISN(im, i)
+ npix_record = len_record * FITS_BYTE / abs (FITS_BITPIX(fits))
+
+ call amovkl (long(1), v, IM_MAXDIM)
+ switch (FITS_BITPIX(fits)) {
+ case FITS_REAL:
+
+ # Allocate temporary space.
+ call malloc (tempbuf, npix, TY_REAL)
+
+ # Initialize the pixel write.
+ call wft_init_write_pixels (npix_record, TY_REAL,
+ FITS_BITPIX(fits), blkfac)
+
+ # For the time being explicitly turn off ieee NaN mapping.
+ call ieemapr (NO, NO)
+
+ # Scale the lines, deal with the blanks via the ieee code which
+ # is currently turned off, and write the output records.
+
+ do i = 1, nlines {
+ iferr (stat = wft_get_image_line (im, buf, v, PIXTYPE(im))) {
+ call erract (EA_WARN)
+ call error (10, "WRT_IMAGE: Error writing IRAF image.")
+ }
+ if (stat == EOF )
+ return
+ if (stat != npix)
+ call error (10, "WRT_IMAGE: Error writing IRAF image.")
+ if (SCALE(fits) == YES)
+ call wft_rscale_line (buf, Memr[tempbuf], npix,
+ 1. / BSCALE(fits), -BZERO(fits), PIXTYPE(im))
+ else
+ call wft_real_line (buf, Memr[tempbuf], npix, PIXTYPE(im))
+ call wft_write_pixels (fits_fd, Memr[tempbuf], npix)
+ }
+
+ # Free space.
+ call mfree (tempbuf, TY_REAL)
+
+ case FITS_DOUBLE:
+
+ # Allocate temporary space.
+ call malloc (tempbuf, npix, TY_DOUBLE)
+
+ # Initialize the pixel write.
+ call wft_init_write_pixels (npix_record, TY_DOUBLE,
+ FITS_BITPIX(fits), blkfac)
+
+ # For the time being explicitly turn off ieee NaN mapping.
+ call ieemapd (NO, NO)
+
+ # Scale the lines, deal with the blanks via the ieee code which
+ # is currently turned off, and write the output records.
+
+ do i = 1, nlines {
+ iferr (stat = wft_get_image_line (im, buf, v, PIXTYPE(im))) {
+ call erract (EA_WARN)
+ call error (10, "WRT_IMAGE: Error writing IRAF image.")
+ }
+ if (stat == EOF )
+ return
+ if (stat != npix)
+ call error (10, "WRT_IMAGE: Error writing IRAF image.")
+ if (SCALE(fits) == YES)
+ call wft_dscale_line (buf, Memd[tempbuf], npix,
+ 1. / BSCALE(fits), -BZERO(fits), PIXTYPE(im))
+ else
+ call wft_double_line (buf, Memd[tempbuf], npix,
+ PIXTYPE(im))
+ call wft_write_pixels (fits_fd, Memd[tempbuf], npix)
+ }
+
+ # Free space.
+ call mfree (tempbuf, TY_DOUBLE)
+
+ default:
+
+ # Allocate temporary space.
+ call malloc (tempbuf, npix, TY_LONG)
+
+ # Scale the line, deal with the blanks, and write the output
+ # record. At the moement blanks are not dealt with.
+
+ call wft_init_write_pixels (npix_record, TY_LONG, FITS_BITPIX(fits),
+ blkfac)
+ do i = 1, nlines {
+ iferr (stat = wft_get_image_line (im, buf, v, PIXTYPE(im))) {
+ call erract (EA_WARN)
+ call error (10, "WRT_IMAGE: Error writing IRAF image.")
+ }
+ if (stat == EOF )
+ return
+ if (stat != npix)
+ call error (10, "WRT_IMAGE: Error writing IRAF image.")
+ if (SCALE(fits) == YES)
+ call wft_lscale_line (buf, Meml[tempbuf], npix,
+ 1. / BSCALE(fits), -BZERO(fits), PIXTYPE(im))
+ else
+ call wft_long_line (buf, Meml[tempbuf], npix, PIXTYPE(im))
+ # call map_blanks (im, Meml[tempbuf], blank)
+ call wft_write_pixels (fits_fd, Meml[tempbuf], npix)
+ }
+ # Free space.
+ call mfree (tempbuf, TY_LONG)
+ }
+
+ # Write the final record.
+ call wft_write_last_record (fits_fd, nrecords)
+ if (short_header == YES || long_header == YES) {
+ call printf ("%d Data logical (2880 byte) records written\n")
+ call pargi (nrecords)
+ }
+end
+
+
+# WFT_GET_IMAGE_LINE -- Procedure to fetch the next image line.
+
+int procedure wft_get_image_line (im, buf, v, datatype)
+
+pointer im # IRAF image descriptor
+pointer buf # pointer to image line
+long v[ARB] # imio dimension descriptor
+int datatype # IRAF image data type
+
+int npix
+int imgnll(), imgnlr(), imgnld(), imgnlx()
+errchk imgnll, imgnlr, imgnld, imgnlx
+
+begin
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_USHORT, TY_LONG:
+ npix = imgnll (im, buf, v)
+ case TY_REAL:
+ npix = imgnlr (im, buf, v)
+ case TY_DOUBLE:
+ npix = imgnld (im, buf, v)
+ case TY_COMPLEX:
+ npix = imgnlx (im, buf, v)
+ default:
+ call error (11, "GET_IMAGE_LINE: Unknown IRAF image type.")
+ }
+
+ return (npix)
+end
+
+
+# WFT_RSCALE_LINE -- This procedure converts the IRAF data to type real
+# and scales by the FITS parameters bscale and bzero.
+
+procedure wft_rscale_line (buf, outbuffer, npix, bscale, bzero, datatype)
+
+pointer buf # pointer to IRAF image line
+real outbuffer[ARB] # FITS integer buffer
+int npix # number of pixels
+double bscale, bzero # FITS bscale and bzero parameters
+int datatype # data type of image
+
+errchk achtlr, altadr, amovr, achtdr, acthxr
+
+begin
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_LONG, TY_USHORT:
+ call achtlr (Meml[buf], outbuffer, npix)
+ call altadr (outbuffer, outbuffer, npix, bzero, bscale)
+ case TY_REAL:
+ call amovr (Memr[buf], outbuffer, npix)
+ call altadr (outbuffer, outbuffer, npix, bzero, bscale)
+ case TY_DOUBLE:
+ call achtdr (Memd[buf], outbuffer, npix)
+ call altadr (outbuffer, outbuffer, npix, bzero, bscale)
+ case TY_COMPLEX:
+ call achtxr (Memx[buf], outbuffer, npix)
+ call altadr (outbuffer, outbuffer, npix, bzero, bscale)
+ default:
+ call error (12, "WFT_RSCALE_LINE: Unknown IRAF image type.")
+ }
+end
+
+
+# WFT_DSCALE_LINE -- This procedure converts the IRAF data to type double with
+# after scaling by the FITS parameters bscale and bzero.
+
+procedure wft_dscale_line (buf, outbuffer, npix, bscale, bzero, datatype)
+
+pointer buf # pointer to IRAF image line
+double outbuffer[ARB] # FITS integer buffer
+int npix # number of pixels
+double bscale, bzero # FITS bscale and bzero parameters
+int datatype # data type of image
+
+errchk achtld, altad, amovd, achtrd, achtxd
+
+begin
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_LONG, TY_USHORT:
+ call achtld (Meml[buf], outbuffer, npix)
+ call altad (outbuffer, outbuffer, npix, bzero, bscale)
+ case TY_REAL:
+ call achtrd (Memr[buf], outbuffer, npix)
+ call altad (outbuffer, outbuffer, npix, bzero, bscale)
+ case TY_DOUBLE:
+ call amovd (Memd[buf], outbuffer, npix)
+ call altad (outbuffer, outbuffer, npix, bzero, bscale)
+ case TY_COMPLEX:
+ call achtxd (Memx[buf], outbuffer, npix)
+ call altad (outbuffer, outbuffer, npix, bzero, bscale)
+ default:
+ call error (12, "WFT_DSCALE_LINE: Unknown IRAF image type.")
+ }
+end
+
+
+# WFT_LSCALE_LINE -- This procedure converts the IRAF data to type long with
+# after scaling by the FITS parameters bscale and bzero.
+
+procedure wft_lscale_line (buf, outbuffer, npix, bscale, bzero, datatype)
+
+pointer buf # pointer to IRAF image line
+long outbuffer[ARB] # FITS integer buffer
+int npix # number of pixels
+double bscale, bzero # FITS bscale and bzero parameters
+int datatype # data type of image
+
+errchk altal, amovl, altadr, achtrl, altad, achtdl, altax, achtxl
+
+begin
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_LONG, TY_USHORT:
+ call altal (Meml[buf], Meml[buf], npix, bzero, bscale)
+ call amovl (Meml[buf], outbuffer, npix)
+ case TY_REAL:
+ call altarl (Memr[buf], outbuffer, npix, bzero, bscale)
+ #call altadr (Memr[buf], Memr[buf], npix, bzero, bscale)
+ #call achtrl (Memr[buf], outbuffer, npix)
+ case TY_DOUBLE:
+ call altad (Memd[buf], Memd[buf], npix, bzero, bscale)
+ call achtdl (Memd[buf], outbuffer, npix)
+ case TY_COMPLEX:
+ call altadx (Memx[buf], Memx[buf], npix, bzero, bscale)
+ call achtxl (Memx[buf], outbuffer, npix)
+ default:
+ call error (12, "WFT_LSCALE_LINE: Unknown IRAF image type.")
+ }
+end
+
+
+# WFT_REAL_LINE -- This procedure converts the IRAF image line to type long with
+# no scaling.
+
+procedure wft_real_line (buf, outbuffer, npix, datatype)
+
+pointer buf # pointer to IRAF image line
+real outbuffer[ARB] # buffer of FITS integers
+int npix # number of pixels
+int datatype # IRAF image datatype
+
+errchk achtlr, achtdr, amovr, achtxr
+
+begin
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_LONG, TY_USHORT:
+ call achtlr (Meml[buf], outbuffer, npix)
+ case TY_REAL:
+ call amovr (Memr[buf], outbuffer, npix)
+ case TY_DOUBLE:
+ call achtdr (Memd[buf], outbuffer, npix)
+ case TY_COMPLEX:
+ call achtxr (Memx[buf], outbuffer, npix)
+ default:
+ call error (13, "WFT_REAL_LINE: Unknown IRAF data type.")
+ }
+end
+
+
+# WFT_DOUBLE_LINE -- This procedure converts the IRAF image line to type long
+# with no scaling.
+
+procedure wft_double_line (buf, outbuffer, npix, datatype)
+
+pointer buf # pointer to IRAF image line
+double outbuffer[ARB] # buffer of FITS integers
+int npix # number of pixels
+int datatype # IRAF image datatype
+
+errchk achtld, achtrd, amovd, achtxd
+
+begin
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_LONG, TY_USHORT:
+ call achtld (Meml[buf], outbuffer, npix)
+ case TY_REAL:
+ call achtrd (Memr[buf], outbuffer, npix)
+ case TY_DOUBLE:
+ call amovd (Memd[buf], outbuffer, npix)
+ case TY_COMPLEX:
+ call achtxd (Memx[buf], outbuffer, npix)
+ default:
+ call error (13, "WFT_DOUBLE_LINE: Unknown IRAF data type.")
+ }
+end
+
+
+# WFT_LONG_LINE -- This procedure converts the IRAF image line to type long with
+# no scaling.
+
+procedure wft_long_line (buf, outbuffer, npix, datatype)
+
+pointer buf # pointer to IRAF image line
+long outbuffer[ARB] # buffer of FITS integers
+int npix # number of pixels
+int datatype # IRAF image datatype
+
+errchk amovl, achtrl, achtdl, achtxl
+
+begin
+ switch (datatype) {
+ case TY_SHORT, TY_INT, TY_LONG, TY_USHORT:
+ call amovl (Meml[buf], outbuffer, npix)
+ case TY_REAL:
+ call achtrl (Memr[buf], outbuffer, npix)
+ case TY_DOUBLE:
+ call achtdl (Memd[buf], outbuffer, npix)
+ case TY_COMPLEX:
+ call achtxl (Memx[buf], outbuffer, npix)
+ default:
+ call error (13, "WFT_LONG_LINE: Unknown IRAF data type.")
+ }
+end
+
+
+# ALTARL -- Procedure to linearly scale a real vector into a long vector
+# using double precision constants to preserve precision.
+
+procedure altarl (a, b, npix, k1, k2)
+
+real a[ARB] # input vector
+long b[ARB] # output vector
+int npix # number of pixels
+double k1, k2 # scaling factors
+
+int i
+
+begin
+ do i = 1, npix
+ b[i] = (a[i] + k1) * k2
+end
+
+
+# ALTADR -- Procedure to linearly scale a real vector in double precision
+
+procedure altadr (a, b, npix, k1, k2)
+
+real a[ARB] # input vector
+real b[ARB] # output vector
+int npix # number of pixels
+double k1, k2 # scaling factors
+
+int i
+
+begin
+ do i = 1, npix
+ b[i] = (a[i] + k1) * k2
+end
+
+
+# ALTADX -- Procedure to linearly scale a complex vector in double precision
+
+procedure altadx (a, b, npix, k1, k2)
+
+complex a[ARB] # input vector
+complex b[ARB] # output vector
+int npix # number of pixels
+double k1, k2 # scaling factors
+
+int i
+
+begin
+ do i = 1, npix
+ b[i] = (a[i] + k1) * k2
+end
+
diff --git a/pkg/obsolete/fits/fits_wpixels.x b/pkg/obsolete/fits/fits_wpixels.x
new file mode 100644
index 00000000..11d4fd0a
--- /dev/null
+++ b/pkg/obsolete/fits/fits_wpixels.x
@@ -0,0 +1,162 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <fset.h>
+include "wfits.h"
+
+# WFT_INIT_WRITE_PIXELS -- This procedure calculates the input and
+# output buffer sizes based in the spp and mii data types and allocates
+# the required space.
+
+procedure wft_init_write_pixels (npix_record, spp_type, bitpix, blkfac)
+
+int npix_record # number of data pixels per record
+int spp_type # pixel data type
+int bitpix # output bits per pixel
+int blkfac # fits blocking factor (0 for disk)
+
+# entry wft_write_pixels, wft_write_last_record
+
+int fd # output file descriptor
+char buffer[1] # input buffer
+int npix # number of pixels in the input buffer
+int nrecords # number of FITS records written
+
+char blank, zero
+int ty_mii, ty_spp, npix_rec, nch_rec, len_mii, sz_rec, nchars, n, nrec
+int bf, szblk
+pointer spp, mii, ip, op
+
+int sizeof(), miilen(), fstati()
+long note()
+errchk malloc, mfree, write, miipak, amovc
+data mii /NULL/, spp/NULL/
+
+begin
+ # Change input parameters into local variables.
+ ty_mii = bitpix
+ ty_spp = spp_type
+ npix_rec = npix_record
+ nch_rec = npix_rec * sizeof (ty_spp)
+ bf = blkfac
+ blank = ' '
+ zero = 0
+
+ # Compute the size of the mii buffer.
+ len_mii = miilen (npix_rec, ty_mii)
+ sz_rec = len_mii * SZ_INT
+
+ # Allocate space for the buffers.
+ if (spp != NULL)
+ call mfree (spp, TY_CHAR)
+ call malloc (spp, nch_rec, TY_CHAR)
+ if (mii != NULL)
+ call mfree (mii, TY_INT)
+ call malloc (mii, len_mii, TY_INT)
+
+ op = 0
+ nrec = 0
+
+ return
+
+# WFT_WRITE_PIXELS -- Wft_wrt_pixels gets an image line and places it in the
+# output buffer. When the output buffer is full the data are packed by the mii
+# routines and written to the specified output.
+
+entry wft_write_pixels (fd, buffer, npix)
+
+ nchars = npix * sizeof (ty_spp)
+ ip = 0
+
+ repeat {
+
+ # Fill output buffer.
+ n = min (nch_rec - op, nchars - ip)
+ call amovc (buffer[1 + ip], Memc[spp + op], n)
+ ip = ip + n
+ op = op + n
+
+ # Write output record.
+ if (op == nch_rec) {
+ call miipak (Memc[spp], Memi[mii], npix_rec, ty_spp, ty_mii)
+ iferr (call write (fd, Memi[mii], sz_rec)) {
+ if (ty_spp == TY_CHAR) {
+ call printf (" File incomplete: %d logical header")
+ call pargi (nrec)
+ call printf (" (2880 byte) records written\n")
+ call error (18,
+ "WRT_RECORD: Error writing header record.")
+ } else {
+ call printf (" File incomplete: %d logical data")
+ call pargi (nrec)
+ call printf (" (2880 byte) records written\n")
+ call error (19,
+ "WRT_RECORD: Error writing data record.")
+ }
+ }
+
+ nrec = nrec + 1
+ op = 0
+ }
+
+ } until (ip == nchars)
+
+ return
+
+
+# WFT_WRITE_LAST_RECORD -- Procedure to write the last partially filled record
+# to tape. Fill with blanks if header record otherwise fill with zeros.
+
+entry wft_write_last_record (fd, nrecords)
+
+ if (op != 0) {
+
+ # Blank or zero fill the last record.
+ n = nch_rec - op
+ if (ty_spp == TY_CHAR)
+ call amovkc (blank, Memc[spp + op], n)
+ else
+ call amovkc (zero, Memc[spp + op], n)
+
+ # Write last record.
+ call miipak (Memc[spp], Memi[mii], npix_rec, ty_spp, ty_mii)
+ iferr (call write (fd, Memi[mii], sz_rec)) {
+ if (ty_spp == TY_CHAR) {
+ call printf ("File incomplete: %d logical header")
+ call pargi (nrec)
+ call printf (" (2880 byte) records written\n")
+ call error (18,
+ "WRT_LAST_RECORD: Error writing last header record.")
+ } else {
+ call printf ("File incomplete: %d logical data")
+ call pargi (nrec)
+ call printf (" (2880 byte) records written\n")
+ call error (19,
+ "WRT_LAST_RECORD: Error writing last data record.")
+ }
+ }
+
+
+ nrec = nrec + 1
+
+ # Pad out the record if the blocking is non-standard.
+ szblk = fstati (fd, F_BUFSIZE) * SZB_CHAR
+ if ((bf > 0) && mod (szblk, FITS_RECORD) != 0 &&
+ (ty_spp != TY_CHAR)) {
+ szblk = szblk / SZB_CHAR
+ n = note (fd) - 1
+ if (mod (n, szblk) == 0)
+ n = 0
+ else
+ n = szblk - mod (n, szblk)
+ for (op = 1; op <= n; op = op + nch_rec) {
+ szblk = min (nch_rec, n - op + 1)
+ call amovkc (zero, Memc[spp], szblk)
+ #call write (fd, Memc[spp], szblk)
+ }
+ }
+
+ }
+
+ nrecords = nrec
+end
diff --git a/pkg/obsolete/fits/fits_write.x b/pkg/obsolete/fits/fits_write.x
new file mode 100644
index 00000000..6887ead0
--- /dev/null
+++ b/pkg/obsolete/fits/fits_write.x
@@ -0,0 +1,156 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include <error.h>
+include <mach.h>
+include <imhdr.h>
+include "wfits.h"
+
+# WFT_WRITE_FITZ -- Procedure to convert a single IRAF file to a FITS file.
+# If the make_image switch is set the header and pixel files are output
+# to the output destination. If the make_image switch is off the header
+# is printed to the standard output.
+
+procedure wft_write_fitz (iraf_file, fits_file)
+
+char iraf_file[ARB] # IRAF file name
+char fits_file[ARB] # FITS file name
+
+int fits_fd, chars_rec, nchars, ip, min_lenuserarea
+pointer im, sp, fits, envstr
+
+int mtfile(), mtopen(), open(), fnldir(), envfind(), ctoi()
+pointer immap()
+errchk immap, imunmap, open, mtopen, close, smark, salloc, sfree
+errchk delete, wft_write_header, wft_write_image, wft_data_limits
+
+include "wfits.com"
+
+begin
+ # Allocate memory for program data structure.
+ call smark (sp)
+ call salloc (fits, LEN_FITS, TY_STRUCT)
+ call salloc (envstr, SZ_FNAME, TY_CHAR)
+
+ # Construct the old iraf name by removing the directory
+ # specification.
+
+ call imgcluster (iraf_file, IRAFNAME(fits), SZ_FNAME)
+ nchars = fnldir (IRAFNAME(fits), IRAFNAME(fits), SZ_FNAME)
+ call strcpy (iraf_file[nchars+1], IRAFNAME(fits), SZ_FNAME)
+
+ # Open the input image.
+ if (envfind ("min_lenuserarea", Memc[envstr], SZ_FNAME) > 0) {
+ ip = 1
+ if (ctoi (Memc[envstr], ip, min_lenuserarea) <= 0)
+ min_lenuserarea = LEN_USERAREA
+ else
+ min_lenuserarea = max (LEN_USERAREA, min_lenuserarea)
+ } else
+ min_lenuserarea = LEN_USERAREA
+ im = immap (iraf_file, READ_ONLY, min_lenuserarea)
+
+ # Open the output file. Check whether the output file is a magtape
+ # device or a binary file. If the output file is magtape check
+ # for a legal blocking factor.
+
+ if (make_image == NO)
+ call strcpy ("dev$null", fits_file, SZ_FNAME)
+
+ if (mtfile (fits_file) == YES) {
+ chars_rec = (blkfac * len_record * FITS_BYTE) / (SZB_CHAR *
+ NBITS_BYTE)
+ fits_fd = mtopen (fits_file, WRITE_ONLY, chars_rec)
+ } else
+ fits_fd = open (fits_file, NEW_FILE, BINARY_FILE)
+
+ # Write header and image.
+ iferr {
+
+ if (short_header == YES || long_header == YES) {
+ if (make_image == YES) {
+ call printf (" -> %s ")
+ call pargstr (fits_file)
+ }
+ if (long_header == YES)
+ call printf ("\n")
+ }
+ call flush (STDOUT)
+
+ call wft_write_header (im, fits, fits_fd)
+ if (make_image == YES)
+ call wft_write_image (im, fits, fits_fd)
+
+ if (long_header == YES)
+ call printf ("\n")
+
+ } then {
+
+ # Print the error message.
+ call flush (STDOUT)
+ call erract (EA_WARN)
+
+ # Close files and cleanup.
+ call imunmap (im)
+ call close (fits_fd)
+ if (make_image == NO)
+ call delete (fits_file)
+ call sfree (sp)
+
+ # Assert an error.
+ call erract (EA_ERROR)
+
+ } else {
+
+ # Close files and cleanup.
+ call imunmap (im)
+ call close (fits_fd)
+ if (make_image == NO)
+ call delete (fits_file)
+ call sfree (sp)
+ }
+
+end
+
+
+# WFT_DATA_LIMITS -- Procedure to calculate the maximum and minimum data values
+# in an IRAF image. Values are only calculated if the max and min are unknown
+# or the image has been modified since the last values were calculated.
+
+procedure wft_data_limits (im, irafmin, irafmax)
+
+pointer im # image pointer
+real irafmin # minimum picture value
+real irafmax # maximum picture value
+
+int npix
+long v[IM_MAXDIM]
+pointer buf
+real maxval, minval
+int imgnlr()
+errchk imgnlr
+
+begin
+ # Compute the data minimum and maximum if the image values
+ # are undefined out-of-date.
+
+ if (LIMTIME(im) < MTIME(im) && NAXIS(im) > 0) {
+
+ irafmax = -MAX_REAL
+ irafmin = MAX_REAL
+ npix = NAXISN(im,1)
+
+ call amovkl (long(1), v, IM_MAXDIM)
+ while (imgnlr (im, buf, v) != EOF) {
+ call alimr (Memr[buf], npix, minval, maxval)
+ irafmin = min (irafmin, minval)
+ irafmax = max (irafmax, maxval)
+ }
+
+ } else {
+
+ irafmax = IM_MAX(im)
+ irafmin = IM_MIN(im)
+
+ }
+end
diff --git a/pkg/obsolete/fits/mkpkg b/pkg/obsolete/fits/mkpkg
new file mode 100644
index 00000000..dd583c01
--- /dev/null
+++ b/pkg/obsolete/fits/mkpkg
@@ -0,0 +1,23 @@
+# Fits Library
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ fits_cards.x wfits.com wfits.h <imhdr.h>
+ fits_params.x wfits.h <time.h>
+ fits_read.x rfits.com rfits.h <error.h> <fset.h> <imhdr.h>
+ fits_rheader.x rfits.com rfits.h rfits.com <ctype.h> <imhdr.h>\
+ <imio.h> <mach.h>
+ fits_rimage.x rfits.com rfits.h <imhdr.h> <fset.h> <mach.h>
+ fits_rpixels.x <fset.h> <mach.h> <mii.h>
+ fits_wheader.x wfits.com wfits.h <fset.h> <imhdr.h> <mach.h>
+ fits_wimage.x wfits.com wfits.h <error.h> <imhdr.h>
+ fits_wpixels.x wfits.h <fset.h> <mach.h>
+ fits_write.x <error.h> wfits.com wfits.h <fset.h> <imhdr.h> <mach.h>
+ ranges.x <mach.h> <ctype.h>
+ t_rfits.x rfits.com rfits.h <error.h> <fset.h>
+ t_wfits.x wfits.com wfits.h <error.h> <fset.h> <mach.h>
+ ;
diff --git a/pkg/obsolete/fits/ranges.x b/pkg/obsolete/fits/ranges.x
new file mode 100644
index 00000000..b3812cd1
--- /dev/null
+++ b/pkg/obsolete/fits/ranges.x
@@ -0,0 +1,234 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <ctype.h>
+
+define FIRST 1 # Default starting range
+define LAST MAX_INT # Default ending range
+define STEP 1 # Default step
+
+# DECODE_RANGES -- Parse a string containing a list of integer numbers or
+# ranges, delimited by either spaces or commas. Return as output a list
+# of ranges defining a list of numbers, and the count of list numbers.
+# Range limits must be positive nonnegative integers. ERR is returned as
+# the function value if a conversion error occurs. The list of ranges is
+# delimited by a single NULL.
+
+int procedure decode_ranges (range_string, ranges, max_ranges, nvalues)
+
+char range_string[ARB] # Range string to be decoded
+int ranges[3, max_ranges] # Range array
+int max_ranges # Maximum number of ranges
+int nvalues # The number of values in the ranges
+
+int ip, nrange, first, last, step, ctoi()
+
+begin
+ ip = 1
+ nvalues = 0
+
+ do nrange = 1, max_ranges - 1 {
+ # Defaults to all positive integers
+ first = FIRST
+ last = LAST
+ step = STEP
+
+ # Skip delimiters
+ while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
+ ip = ip + 1
+
+ # Get first limit.
+ # Must be a number, '-', 'x', or EOS. If not return ERR.
+ if (range_string[ip] == EOS) { # end of list
+ if (nrange == 1) {
+ # Null string defaults
+ ranges[1, 1] = first
+ ranges[2, 1] = last
+ ranges[3, 1] = step
+ ranges[1, 2] = NULL
+ nvalues = nvalues + abs (last-first) / step + 1
+ return (OK)
+ } else {
+ ranges[1, nrange] = NULL
+ return (OK)
+ }
+ } else if (range_string[ip] == '-')
+ ;
+ else if (range_string[ip] == 'x')
+ ;
+ else if (IS_DIGIT(range_string[ip])) { # ,n..
+ if (ctoi (range_string, ip, first) == 0)
+ return (ERR)
+ } else
+ return (ERR)
+
+ # Skip delimiters
+ while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
+ ip = ip + 1
+
+ # Get last limit
+ # Must be '-', or 'x' otherwise last = first.
+ if (range_string[ip] == 'x')
+ ;
+ else if (range_string[ip] == '-') {
+ ip = ip + 1
+ while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
+ ip = ip + 1
+ if (range_string[ip] == EOS)
+ ;
+ else if (IS_DIGIT(range_string[ip])) {
+ if (ctoi (range_string, ip, last) == 0)
+ return (ERR)
+ } else if (range_string[ip] == 'x')
+ ;
+ else
+ return (ERR)
+ } else
+ last = first
+
+ # Skip delimiters
+ while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
+ ip = ip + 1
+
+ # Get step.
+ # Must be 'x' or assume default step.
+ if (range_string[ip] == 'x') {
+ ip = ip + 1
+ while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
+ ip = ip + 1
+ if (range_string[ip] == EOS)
+ ;
+ else if (IS_DIGIT(range_string[ip])) {
+ if (ctoi (range_string, ip, step) == 0)
+ ;
+ } else if (range_string[ip] == '-')
+ ;
+ else
+ return (ERR)
+ }
+
+ # Output the range triple.
+ ranges[1, nrange] = first
+ ranges[2, nrange] = last
+ ranges[3, nrange] = step
+ nvalues = nvalues + abs (last-first) / step + 1
+ }
+
+ return (ERR) # ran out of space
+end
+
+
+# GET_NEXT_NUMBER -- Given a list of ranges and the current file number,
+# find and return the next file number. Selection is done in such a way
+# that list numbers are always returned in monotonically increasing order,
+# regardless of the order in which the ranges are given. Duplicate entries
+# are ignored. EOF is returned at the end of the list.
+
+int procedure get_next_number (ranges, number)
+
+int ranges[ARB] # Range array
+int number # Both input and output parameter
+
+int ip, first, last, step, next_number, remainder
+
+begin
+ # If number+1 is anywhere in the list, that is the next number,
+ # otherwise the next number is the smallest number in the list which
+ # is greater than number+1.
+
+ number = number + 1
+ next_number = MAX_INT
+
+ for (ip=1; ranges[ip] != NULL; ip=ip+3) {
+ first = min (ranges[ip], ranges[ip+1])
+ last = max (ranges[ip], ranges[ip+1])
+ step = ranges[ip+2]
+ if (number >= first && number <= last) {
+ remainder = mod (number - first, step)
+ if (remainder == 0)
+ return (number)
+ if (number - remainder + step <= last)
+ next_number = number - remainder + step
+ } else if (first > number)
+ next_number = min (next_number, first)
+ }
+
+ if (next_number == MAX_INT)
+ return (EOF)
+ else {
+ number = next_number
+ return (number)
+ }
+end
+
+
+# GET_PREVIOUS_NUMBER -- Given a list of ranges and the current file number,
+# find and return the previous file number. Selection is done in such a way
+# that list numbers are always returned in monotonically decreasing order,
+# regardless of the order in which the ranges are given. Duplicate entries
+# are ignored. EOF is returned at the end of the list.
+
+int procedure get_previous_number (ranges, number)
+
+int ranges[ARB] # Range array
+int number # Both input and output parameter
+
+int ip, first, last, step, next_number, remainder
+
+begin
+ # If number-1 is anywhere in the list, that is the previous number,
+ # otherwise the previous number is the largest number in the list which
+ # is less than number-1.
+
+ number = number - 1
+ next_number = 0
+
+ for (ip=1; ranges[ip] != NULL; ip=ip+3) {
+ first = min (ranges[ip], ranges[ip+1])
+ last = max (ranges[ip], ranges[ip+1])
+ step = ranges[ip+2]
+ if (number >= first && number <= last) {
+ remainder = mod (number - first, step)
+ if (remainder == 0)
+ return (number)
+ if (number - remainder >= first)
+ next_number = number - remainder
+ } else if (last < number) {
+ remainder = mod (last - first, step)
+ if (remainder == 0)
+ next_number = max (next_number, last)
+ else if (last - remainder >= first)
+ next_number = max (next_number, last - remainder)
+ }
+ }
+
+ if (next_number == 0)
+ return (EOF)
+ else {
+ number = next_number
+ return (number)
+ }
+end
+
+
+# IS_IN_RANGE -- Test number to see if it is in range.
+
+bool procedure is_in_range (ranges, number)
+
+int ranges[ARB] # Range array
+int number # Number to be tested against ranges
+
+int ip, first, last, step
+
+begin
+ for (ip=1; ranges[ip] != NULL; ip=ip+3) {
+ first = min (ranges[ip], ranges[ip+1])
+ last = max (ranges[ip], ranges[ip+1])
+ step = ranges[ip+2]
+ if (number >= first && number <= last)
+ if (mod (number - first, step) == 0)
+ return (true)
+ }
+
+ return (false)
+end
diff --git a/pkg/obsolete/fits/rfits.com b/pkg/obsolete/fits/rfits.com
new file mode 100644
index 00000000..08f44c0e
--- /dev/null
+++ b/pkg/obsolete/fits/rfits.com
@@ -0,0 +1,18 @@
+
+# FITS reader common
+
+int len_record # Length of FITS records in bytes
+int data_type # Output data type
+real blank # Blank value
+real fe # Maximum size in megabytes for scan mode
+
+# Option flags
+
+int make_image # Create an IRAF image
+int long_header # Print a long header (FITS header cards)
+int short_header # Print a short header (Title and size)
+int scale # Scale the data
+int old_name # Use old IRAF name?
+
+common /rfitscom/ len_record, data_type, blank, fe, make_image, long_header,
+ short_header, scale, old_name
diff --git a/pkg/obsolete/fits/rfits.h b/pkg/obsolete/fits/rfits.h
new file mode 100644
index 00000000..8afc5b0b
--- /dev/null
+++ b/pkg/obsolete/fits/rfits.h
@@ -0,0 +1,80 @@
+# FITS Definitions
+
+# The FITS standard readable by the FITS reader using these definitions:
+#
+# 1. 8 bits / byte
+# 2. ASCII character code
+# 3. MII integer data format (i.e. 8 bit unsigned integers and 16 and 32
+# bit signed twos complement integers with most significant bytes first.)
+# 4. IEEE 32 and 64 bit floating point format
+#
+#
+# The following deviations from the FITS standard are allowed:
+#
+# 1. The number of FITS bytes per record is normally 2880 or up to 10 times
+# 2880 bytes but may be arbitrarily specified by the user.
+
+# Define the bits per pixel, precision and byte order of the basic FITS types
+
+define FITS_RECORD 2880 # number of bytes in a standard FITS record
+
+define FITS_BYTE 8 # Bits in a FITS byte
+define FITS_SHORT 16 # Bits in a FITS short
+define FITS_LONG 32 # Bits in a FITS long
+define FITS_REAL -32 # Bits in a FITS real * -1
+define FITS_DOUBLE -64 # Bits in a FITS double * -1
+
+define FITSB_PREC 3 # Decimal digits of precision in a FITS byte
+define FITSS_PREC 5 # Decimal digits of precision in a FITS short
+define FITSL_PREC 10 # Decimal digits of precision in a FITS long
+
+define LSBF NO # Least significant byte first
+
+# Define the basic format of a FITS cardimage
+
+define LEN_CARD 80 # Length of FITS card in characters
+define COL_VALUE 11 # Starting column for parameter values
+
+
+# FITS standards not recognized currently by IRAF.
+#
+# 1. SIMPLE SIMPLE = 'F' not implemented, file skipped
+# 2. GROUPS Group data not currently implemented, file skippped
+
+
+# Values for the following quantities are stored in the structure below.
+
+define LEN_FITS (15 + SZ_FNAME + 1)
+
+define FITS_BSCALE Memd[P2D($1)] # FITS scaling parameter
+define FITS_BZERO Memd[P2D($1+2)] # FITS zero parameter
+define BLANK_VALUE Meml[P2L($1+4)] # Blank value
+define BLANKS Memi[$1+5] # YES if blank keyword in header
+define BITPIX Memi[$1+6] # Bits per pixel (Must be an MII type)
+define SCALE Memi[$1+7] # Scale the data?
+define SIMPLE Memi[$1+8] # Standard FITS format
+define NRECORDS Memi[$1+9] # Number of FITS logical records
+define IRAFNAME Memc[P2C($1+12)] # Old IRAF name
+
+# Mapping of additional IRAF header parameters
+
+define PIXTYPE IM_PIXTYPE($1)
+define NBPIX IM_NBPIX($1)
+define IRAFMAX IM_MAX($1)
+define IRAFMIN IM_MIN($1)
+define LIMTIME IM_LIMTIME($1)
+define LEN_USERAREA 28800
+
+# Mapping of FITS Keywords to IRAF image header
+
+define NAXIS IM_NDIM($1)
+define NAXISN IM_LEN($1,$2)
+define OBJECT IM_TITLE($1)
+define HISTORY IM_HISTORY($1)
+define UNKNOWN Memc[($1+IMU-1)*SZ_STRUCT+1] # All unrecognized keywords
+ # are stored here
+# Miscellaneous definitions.
+
+define SZ_OBJECT SZ_IMTITLE
+define SZ_HISTORY SZ_IMHIST
+define SZ_FCTYPE SZ_CTYPE
diff --git a/pkg/obsolete/fits/structure.hlp b/pkg/obsolete/fits/structure.hlp
new file mode 100644
index 00000000..715ef185
--- /dev/null
+++ b/pkg/obsolete/fits/structure.hlp
@@ -0,0 +1,363 @@
+.help fits Apr84 "Program Structure"
+.sh
+RFITS Structure Chart
+
+.nf
+t_rfits ()
+# Returns when file list is satisfied or if EOT is encountered
+# Errors from called routines are trapped and printed as a warning.
+
+ read_fits (fitsfile, iraffile)
+ # Returns OK or EOF
+
+ read_header (fits_fd, fits, im)
+ # Returns OK or EOF
+
+ decode_fits_card (fits, im, card)
+ # Returns YES or NO
+
+ get_fits_string (card, str, maxchar)
+
+ read_image (fits_fd, fits, im)
+ # Invokes error handler if EOF is encountered
+
+ set_image_header (fits, im)
+
+ set_coords (im)
+ # sets the coordinate transformations to a 1 to 1
+ # mapping
+
+ init_read_pixels (npix_record, bitpix, lsbf, spp_type)
+ # Returns OK
+
+ put_imageline (im, bufptr, v, pixel_type)
+ # Outputs line to image
+
+ read_pixels (fd, buffer, npix)
+ # Returns EOF or the number of pixels converted
+
+ map_blanks (a, blanks, im)
+
+ scale_line (line, bufptr, npix, bscale, bzero,
+ pixel_type)
+ # Converts the pixels to the output data type after
+ # applying bscale and bzero to the data
+
+ change_line(line, bufptr, npix, pixel_type)
+ # Changes the FITS integers to the output pixel_type
+ # without scaling.
+.fi
+
+.sh
+RFITS Structure Summary
+
+.ls 4 t_rfits
+The main procedure reads the control parameters.
+The files to be read and converted are calculated from the specified source
+and file list. A loop through
+the files determines the specific input source names and output filenames
+and calls READ_FITS for each conversion.
+.ls read_fits
+The input source is opened and the output image header file is created.
+If only the FITS header is to be listed then a temporary image header file
+is created. The FITS header is read and decoded into the IRAF image
+header by READ_HEADER. If the image is to be read then MAKE_IMAGE is
+called. Finally, all files are closed. If a temporary image header file
+was created it is deleted.
+.ls read_header
+Some initialization is done on the IRAF header.
+The FITS header cards are read one at a time. If EOF is encountered
+then EOF is returned. If a long header listing has been specified then
+the card is printed. The card is passed to DECODE_FITS_CARD. If
+DECODE_FITS_CARD returns YES for the END card then the loop exits. If a
+short header listing has bee specified then the title and image size
+is printed. The routine returns OK if the header was successfully
+interpreted or EOF if encountered. All other errors are returned
+via the error handler.
+.ls decode_fits_card
+A series of STRMATCHes are made against the recognized FITS keywords.
+If a match is found the possible actions are:
+.ls
+Convert a value to the IRAF image header. The conversions are defined in
+fits.h
+.le
+.ls
+Invoke an error condition
+.le
+.ls
+Return a YES status if the keyword is END
+.le
+
+Otherwise, the card is concatenated to the User Area of the IRAF image
+header. If the keyword was not END then NO is returned.
+.ls get_fits_string
+The string field for a keyword with a string value is extracted. The
+leading and trailing quotes are removed as well as trailing blanks.
+The EOS is marked by either ', /, or the end of the card.
+.le
+.le
+.le
+.ls read_image
+The FITS image pixels are converted to an IRAF image file.
+The image file header is set.
+The lines of the image are converted one at a time.
+Each line is checked for blank values.
+When all the image data has been read the number of blank pixels encounter
+is printed (unless the value is zero).
+.ls set_image_header
+The pixel type for the IRAF image is set to the user specified type.
+If no type has been specified then the type is determined from the number
+of bits per pixel given in the FITS header.
+.le
+.ls set_coords
+Sets the coordinate transformation parameters to a 1 to 1 transformation.
+.le
+.ls init_read_pixels
+The pixel reading routine is initialized. The parameters are the number
+of pixels per record, the number of bits per pixel which must be a
+valid MII type, a byte order flag, and the SPP data type to be converted
+to. In the FITS reader the byte order is specified to be most significant
+byte first and the SPP data type is TY_LONG.
+.le
+.ls put_imageline
+Put_imageline outputs a single line of the FITS image to the IRAF image.
+.le
+.ls read_pixels
+The pixels are read into a record buffer. Data conversion is accomplished
+with the MII routines since FITS format is the same as MII format. The
+specified number of pixels is returned in the specified buffer.
+.le
+.ls map_blanks
+Pixels having the blank value as given in the FITS header are added into
+the bad pixel count in the image header. This routine will someday handle
+mapping of bad pixels in a more detailed manner.
+.le
+.ls scale_line
+The FITS integers from tape are converted to the output IRAF data type by
+applying the FITS scaling parameters BSCALE and BZERO.
+.le
+.ls change_line
+The FITS integers are converted directly to the output IRAF data type
+without scaling (BSCALE = 1.0 and BZERO = 0.0).
+.le
+.le
+.le
+
+.sh
+WFITS Structure Chart
+
+.nf
+t_wfits()
+# Returns when the input file list is satisfied.
+# Errors from called routines are trapped, an error message is issued and
+# wfits terminates.
+
+ wrt_fits (iraf_file, fits_file)
+
+ data_limits (im)
+
+ wrt_header (im, fits, fits_fd)
+
+ set_bitbix (bitpix, pixtype, data_bitpix)
+
+ iraf_type (pixtype, pixstring)
+
+ set_scale (fits_bitpix, datamax, datamin, bscale, bzero)
+
+ tape_limits (fits_bitpix, tapemax, tapemin)
+
+ set_blank (fits_bitpix, blank, blankstr)
+
+ init_wrt_pixels (npix_record, spp_type, mii_type)
+
+ init_card_encode (im, fits)
+ # Returns YES
+
+ card_encode (im, fits, card)
+ # Returns YES if valid FITS card
+
+ get_standard_card (cardno, im, fits, axisno,
+ card
+ # Returns YES or NO
+
+ get_option_card (im, fits, optiono, card)
+ # Returns YES or NO
+
+ get_coord_card (im, coordno, coordaxis, card)
+ # Returns YES or NO
+
+ get_history_card (im, histptr, card)
+ # Returns YES or NO
+
+ get_end_card (card)
+ # Returns YES or NO
+
+ wrt_pixels (fits_fd, card, len_card)
+
+ wrt_last_record (fits_fd)
+
+ wrt_image (im, fits, fits_fd)
+
+ init_wrt_pixels (npix_record, spp_type, mii_type)
+
+ get_image_line (im, bufptr, v, pixtype)
+ # Returns EOF or number of pixels in a line
+
+ scale_line (bufptr, long_array, npix, bscale, bzero,
+ pixtype)
+
+ long_line (bufptr, long_array, npix, pixtype)
+
+ map_blanks (im, long_array, blank)
+
+ wrt_pixels (fits_fd, long_array, npix)
+
+ wrt_last_record (fits_fd)
+.fi
+.sh
+WFITS Structure Summary
+
+.ls t_wfits
+The main procedure reads the control parameters. The files to be read and
+converted are calculated from the specified source and file list. A loop
+through the files determines the specific input source names and output
+file names and calls WRT_FITS for each file conversion. Write errors are trapped
+and cause termination of the program.
+.ls wrt_fits
+The input source is opened. If the make_image switch is set the output
+destination is opened. The IRAF image header parameters are encoded into
+the FITS header and both header and pixels are written to the output
+destination.
+DATA_LIMITS is called if the autoscale switch is enabled and the IRAF image
+data maximum and minimum values are unknown or the image has been modified
+since they were last calculated.
+If the make_image switch is turned off the FITS header is printed
+on the standard output and a temporary output file is created. Finally
+all the files are closed. If a temporary file was created it is deleted.
+.ls data_limits
+DATA_LIMITS calculates the minimum and maximum data values in an IRAF image.
+The calculation is made only if these values are
+undefined or the image has been modified since the last values were
+calculated.
+.le
+.ls wrt_header
+Some initialization is done on the FITS header. The appropriate FITS bitpix,
+bzero and bscale factors, and the tape value for blank pixels are calculated
+for each image.
+The FITS header cards are encoded one at a time. If a long_header listing
+has been specified then the FITS card is printed on the standard output.
+If a short_header listing
+is specified then the title and image size only are printed. Encoding terminates
+when the FITS END keyword is encountered. Partial header records are filled
+with blanks before being written to the output destination.
+.ls set_bitpix
+The value of the FITS bitpix is calculated. If the user given bitpix is
+not a valid FITS bitpix, SET_BITPIX uses the precision of the IRAF image data
+to set bitpix.
+.le
+.ls iraf_type
+The IRAF datatype value is set to either INTEGER, FLOATING or COMPLEX.
+.le
+.ls set_scale
+The bscale and bzero values are calculated from the IRAF minimum and maximum
+data values and the FITS bitpix.
+.ls tape_limits
+The maximum and minimum FITS integer values are calculated from the FITS bitpix.
+.le
+.le
+.ls set_blank
+The FITS integer value for a blank pixel is calculated from the FITS bitpix.
+.le
+.ls init_wrt_pixels
+The pixel writing routine is initialized. The parameters are the number of
+pixels per record, the spp_type and the number of bits per pixel which
+must be a valid mii type. For ASCII header card images the number of pixels
+per record is normally 2880 and the bits per pixel is 8. The spp type is
+always TY_CHAR.
+.le
+.ls init_card_encode
+The card encoding procedure is initialized. The number of standard keyword,
+optional keywords, coordinate transformation keywords, and history keywords
+are calculated.
+.le
+.ls card_encode
+An eighty character FITS format string is created for each permitted
+FITS keyword.
+.ls get_standard_card
+The minimum required FITS header parameters, SIMPLE, BITPIX, NAXIS and NAXIS#
+are encode into FITS cards.
+.le
+.ls get_option_card
+A set of optional FITS parameters are encoded into FITS cards.
+At present the permitted keywords are BSCALE, BZERO, BUNIT, BLANK
+OBJECT, ORIGIN, DATE, IRAFMAX, IRAFMIN, IRAF-B/P, and IRAFTYPE.
+The BLANK card is only encoded if the number of bad pixels in the
+IRAF image header is nonzero. BUNIT and OBJECT cards are only encoded if
+if the appropriate strings in the IRAF image header are defined.
+.le
+.ls get_coord_card
+The coordinate transformation parameters are encoded into FITS header cards.
+.le
+.ls get_history_card
+The IRAF history string is encoded into FITS header card(s). A maximum of
+seven HISTORY cards are currently permitted by imio.
+.le
+.ls get_end_card
+The FITS end card in encoded.
+.le
+.le
+.ls wrt_pixels
+The FITS card images are read into a record buffer. When the buffer is
+full data conversion is accomplished using the mii routines since FITS
+format is the same as mii format. After data conversion the record
+buffer is written to the output destination.
+.le
+.ls wrt_last_record
+The last partially filled header record is padded with blanks and written to
+the output destination.
+.le
+.le
+.ls wrt_image
+The IRAF image pixels are converted to FITS image format. The lines of the
+IRAF image are converted one at a time. Each line is scaled (if scaling is
+enabled and appropriate) and the IRAF pixels are converted to long integers.
+WRT_PIXELS is called to convert the integers to the appropriate FITS
+output type using the MII routines.
+.ls init_wrt_pixels
+The pixel writing routine is initialized. The parameters are the number of
+pixels per output record, the spp type and the number of FITS bits per pixel
+which must be a valid mii type. The number of pixels per output record is
+2880, 1440 or 720 for FITS bitpix of 8, 16 or 32 respectively. The spp type
+is always TY_LONG.
+.le
+.ls get_image_line
+A single IRAF image line is read into an internal buffer.
+.le
+.ls scale_line
+The IRAF image line is scaled by the FITS BSCALE and
+BZERO scaling factors and converted to long integers.
+SCALE_LINE is called if the scale switch is set.
+.le
+.ls long_line
+The IRAF image data values are converted directly to long integers.
+LONG_LINE is called if scaling switch is turned off.
+.le
+.ls map_blanks
+This function will eventually map IRAF blank pixels to the appropriate
+FITS integer for blanks. Implementation of this function is will occur
+after the imio mods.
+.le
+.ls wrt_pixels
+The scaled IRAF image lines are read into a record buffer. When the buffer is
+full data conversion is accomplished using the MII routines since FITS
+format is the same as mii format. After data conversion the record
+buffer is written to the output destination.
+.le
+.ls wrt_last_record
+The last partially full data record is padded with zeros and written to the
+output destination.
+.le
+.le
+.le
+.le
+.endhelp
diff --git a/pkg/obsolete/fits/t_rfits.x b/pkg/obsolete/fits/t_rfits.x
new file mode 100644
index 00000000..be4449ac
--- /dev/null
+++ b/pkg/obsolete/fits/t_rfits.x
@@ -0,0 +1,184 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <fset.h>
+include "rfits.h"
+
+define MAX_RANGES 100 # the maxium number of ranges
+define NTYPES 7 # the number of image data types
+
+# RFITS -- Read FITS format data. Further documentation given in rfits.hlp
+
+procedure t_rfits()
+
+char infile[SZ_FNAME] # fits file
+char file_list[SZ_LINE] # list of tape files
+char outfile[SZ_FNAME] # IRAF file
+char in_fname[SZ_FNAME] # input file name
+char out_fname[SZ_FNAME] # output file name
+
+int len_inlist, len_outlist
+int range[MAX_RANGES*3+1], file_number, offset, stat
+pointer inlist, outlist
+
+bool clgetb()
+char clgetc()
+int rft_get_image_type(), clgeti(), mtfile(), strlen(), btoi(), fntlenb()
+int rft_read_fitz(), decode_ranges(), get_next_number(), fntgfnb(), fstati()
+int mtneedfileno(), fntrfnb()
+pointer fntopnb()
+real clgetr(), rft_fe()
+
+include "rfits.com"
+
+begin
+ # Set up the standard output to flush on a newline.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Get RFITS parameters.
+ call clgstr ("fits_file", infile, SZ_FNAME)
+ long_header = btoi (clgetb ("long_header"))
+ short_header = btoi (clgetb ("short_header"))
+ len_record = FITS_RECORD
+ old_name = btoi (clgetb ("oldirafname"))
+ make_image = btoi (clgetb ("make_image"))
+
+ # Open the input file list.
+ if (mtfile (infile) == YES) {
+ inlist = NULL
+ if (mtneedfileno (infile) == YES)
+ call clgstr ("file_list", file_list, SZ_LINE)
+ else
+ call strcpy ("1", file_list, SZ_LINE)
+ } else {
+ inlist = fntopnb (infile, NO)
+ len_inlist = fntlenb (inlist)
+ if (len_inlist > 0) {
+ call sprintf (file_list, SZ_LINE, "1-%d")
+ call pargi (len_inlist)
+ } else
+ call sprintf (file_list, SZ_LINE, "0")
+ }
+
+ # Decode the ranges string.
+ if (decode_ranges (file_list, range, MAX_RANGES, len_inlist) == ERR)
+ call error (1, "T_RFITS: Illegal file number list")
+
+ # Open the output file list.
+ if (make_image == YES) {
+ call clgstr ("iraf_file", outfile, SZ_FNAME)
+ if (outfile[1] == EOS) {
+ if (old_name == YES)
+ call mktemp ("tmp", outfile, SZ_FNAME)
+ else
+ call error (0, "T_RFITS: Undefined output file name")
+ }
+ outlist = fntopnb (outfile, NO)
+ len_outlist = fntlenb (outlist)
+ data_type = rft_get_image_type (clgetc ("datatype"))
+ scale = btoi (clgetb ("scale"))
+ blank = clgetr ("blank")
+ offset = clgeti ("offset")
+ } else {
+ outfile[1] = EOS
+ outlist = NULL
+ len_outlist = 1
+ }
+ if ((len_outlist > 1) && (len_outlist != len_inlist))
+ call error (0,
+ "T_RFITS: Output and input lists have different lengths")
+
+ # Get the scan size parameter.
+ fe = rft_fe (infile)
+
+ # Read successive FITS files, convert and write into a numbered
+ # succession of output IRAF files.
+
+ file_number = 0
+ while (get_next_number (range, file_number) != EOF) {
+
+ # Get the input file name.
+ if (inlist != NULL) {
+ if (fntgfnb (inlist, in_fname, SZ_FNAME) == EOF)
+ call error (0, "T_RFITS: Error reading input file name")
+ } else {
+ if (mtneedfileno (infile) == YES)
+ call mtfname (infile, file_number, in_fname, SZ_FNAME)
+ else
+ call strcpy (infile, in_fname, SZ_FNAME)
+ }
+
+ # Get the output file name.
+ if (outlist == NULL) {
+ out_fname[1] = EOS
+ } else if (len_inlist > len_outlist) {
+ if (fntrfnb (outlist, 1, out_fname, SZ_FNAME) == EOF)
+ call strcpy (outfile, out_fname, SZ_FNAME)
+ if (len_inlist > 1) {
+ call sprintf (out_fname[strlen(out_fname)+1], SZ_FNAME,
+ "%04d")
+ call pargi (file_number + offset)
+ }
+ } else if (fntgfnb (outlist, out_fname, SZ_FNAME) == EOF)
+ call error (0, "T_RFITS: Error reading output file name")
+
+ # Convert FITS file to the output IRAF file. If EOT is reached
+ # then exit. If an error is detected then print a warning and
+ # continue with the next file.
+
+ iferr (stat = rft_read_fitz (in_fname, out_fname))
+ call erract (EA_FATAL)
+ if (stat == EOF)
+ break
+ }
+
+ if (inlist != NULL)
+ call fntclsb (inlist)
+ if (outlist != NULL)
+ call fntclsb (outlist)
+end
+
+
+# RFT_GET_IMAGE_TYPE -- Convert a character to and IRAF image type.
+
+int procedure rft_get_image_type (c)
+
+char c
+
+int type_codes[NTYPES], i
+string types "usilrdx"
+int stridx()
+data type_codes /TY_USHORT, TY_SHORT, TY_INT, TY_LONG, TY_REAL,
+ TY_DOUBLE, TY_COMPLEX/
+begin
+ i = stridx (c, types)
+ if (i == 0)
+ return (ERR)
+ else
+ return (type_codes[stridx(c,types)])
+end
+
+
+# RFT_FE -- Fetch the maximum file size in MB for tape scanning mode.
+
+real procedure rft_fe (file)
+
+char file[ARB] # the input file name
+
+pointer gty
+real fe
+int mtfile(), gtygeti()
+pointer mtcap()
+errchk gtygeti()
+
+begin
+ if (mtfile (file) == NO)
+ return (0.0)
+ iferr (gty = mtcap (file))
+ return (0.0)
+ iferr (fe = gtygeti (gty, "fe"))
+ fe = 0.0
+ call gtyclose (gty)
+ return (fe)
+end
diff --git a/pkg/obsolete/fits/t_wfits.x b/pkg/obsolete/fits/t_wfits.x
new file mode 100644
index 00000000..13cdd81f
--- /dev/null
+++ b/pkg/obsolete/fits/t_wfits.x
@@ -0,0 +1,216 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <error.h>
+include <fset.h>
+include "wfits.h"
+
+# T_WFITS -- This procedure converts a series of IRAF image files to
+# FITS image files.
+
+procedure t_wfits ()
+
+char iraf_files[SZ_FNAME] # list of IRAF images
+char fits_files[SZ_FNAME] # list of FITS files
+bool newtape # new or used tape ?
+char in_fname[SZ_FNAME] # input file name
+char out_fname[SZ_FNAME] # output file name
+
+int imlist, flist, nimages, nfiles, file_number
+bool clgetb()
+double clgetd()
+int imtopen(), imtlen (), wft_get_bitpix(), clgeti(), imtgetim()
+int mtfile(), btoi(), fstati(), fntlenb(), fntgfnb(), mtneedfileno()
+int wft_blkfac(), fntrfnb(), strlen()
+pointer fntopnb()
+
+include "wfits.com"
+
+begin
+ # Flush on a newline if STDOUT has not been redirected.
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Open iraf_files template and determine number of files in list.
+ call clgstr ("iraf_files", iraf_files, SZ_FNAME)
+ imlist = imtopen (iraf_files)
+ nimages = imtlen (imlist)
+
+ # Get the wfits parameters.
+ long_header = btoi (clgetb ("long_header"))
+ short_header = btoi (clgetb ("short_header"))
+ make_image = btoi (clgetb ("make_image"))
+
+ # Get the FITS bits per pixel and the FITS logical record size.
+ bitpix = wft_get_bitpix (clgeti ("bitpix"))
+ len_record = FITS_RECORD
+
+ # Get the scaling parameters.
+ scale = btoi (clgetb ("scale"))
+ if (scale == YES) {
+ if (clgetb ("autoscale"))
+ autoscale = YES
+ else {
+ bscale = clgetd ("bscale")
+ bzero = clgetd ("bzero")
+ autoscale = NO
+ }
+ } else {
+ autoscale = NO
+ bscale = 1.0d0
+ bzero = 0.0d0
+ }
+
+ # Get the output file name and type (tape or disk). If no tape file
+ # number is given for output, the user is asked if the tape is blank
+ # or contains data. If the tape is blank output begins at BOT,
+ # otherwise at EOT.
+
+ if (make_image == YES) {
+ call clgstr ("fits_files", fits_files, SZ_FNAME)
+ if (mtfile (fits_files) == YES) {
+ flist = NULL
+ if (mtneedfileno (fits_files) == YES) {
+ newtape = clgetb ("newtape")
+ if (newtape)
+ call mtfname (fits_files, 1, out_fname, SZ_FNAME)
+ else
+ call mtfname (fits_files, EOT, out_fname, SZ_FNAME)
+ } else {
+ call strcpy (fits_files, out_fname, SZ_FNAME)
+ newtape = false
+ }
+ } else {
+ flist = fntopnb (fits_files, NO)
+ nfiles = fntlenb (flist)
+ if ((nfiles > 1) && (nfiles != nimages))
+ call error (0,
+ "T_WFITS: Input and output lists are not the same length")
+ }
+ } else {
+ fits_files[1] = EOS
+ flist = NULL
+ }
+
+ # Get the fits file blocking factor.
+ blkfac = wft_blkfac (fits_files, clgeti ("blocking_factor"))
+
+ # Loop through the list of input images files.
+
+ file_number = 1
+ while (imtgetim (imlist, in_fname, SZ_FNAME) != EOF) {
+
+ # Print the id string.
+ if (long_header == YES || short_header == YES) {
+ call printf ("File %d: %s")
+ call pargi (file_number)
+ call pargstr (in_fname)
+ }
+
+ # Get the output file name. If single file output to disk, use
+ # name fits_file. If multiple file output to disk, the file number
+ # is added to the output file name, if no output name list is
+ # supplied. If an output name list is supplied then the names
+ # are extracted one by one from that list.
+
+ if (make_image == YES) {
+ if (mtfile (fits_files) == YES) {
+ if (file_number == 2)
+ call mtfname (out_fname, EOT, out_fname, SZ_FNAME)
+ } else if (nfiles > 1) {
+ if (fntgfnb (flist, out_fname, SZ_FNAME) == EOF)
+ call error (0, "Error reading output file name")
+ } else {
+ if (fntrfnb (flist, 1, out_fname, SZ_FNAME) == EOF)
+ call strcpy (fits_files, out_fname, SZ_FNAME)
+ if (nimages > 1) {
+ call sprintf (out_fname[strlen(out_fname)+1],
+ SZ_FNAME, "%04d")
+ call pargi (file_number)
+ }
+ }
+ }
+
+ # Write each output file.
+ iferr (call wft_write_fitz (in_fname, out_fname)) {
+ call printf ("Error writing file: %s\n")
+ call pargstr (out_fname)
+ call erract (EA_WARN)
+ break
+ } else
+ file_number = file_number + 1
+ }
+
+ # Close up the input and output lists.
+ call clpcls (imlist)
+ if (flist != NULL)
+ call fntclsb (flist)
+end
+
+
+# WFT_GET_BITPIX -- This procedure fetches the user determined bitpix or ERR if
+# the bitpix is not one of the permitted FITS types.
+
+int procedure wft_get_bitpix (bitpix)
+
+int bitpix
+
+begin
+ switch (bitpix) {
+ case FITS_BYTE, FITS_SHORT, FITS_LONG, FITS_REAL, FITS_DOUBLE:
+ return (bitpix)
+ default:
+ return (ERR)
+ }
+end
+
+
+# WFT_BLKFAC -- Get the fits tape blocking factor.
+
+int procedure wft_blkfac (file, ublkfac)
+
+char file[ARB] # the input file name
+int ublkfac # the user supplied blocking factor
+
+int bs, fb, blkfac
+pointer gty
+int mtfile(), mtcap(), gtygeti()
+errchk mtcap(), gtygeti()
+
+begin
+ # Return a blocking factor of 1 if the file is a disk file.
+ if (mtfile (file) == NO)
+ return (0)
+
+ # Open the tapecap device entry for the given device, and get
+ # the device block size and default FITS blocking factor
+ # parameters.
+
+ iferr (gty = mtcap (file))
+ return (max (ublkfac,1))
+ iferr (bs = gtygeti (gty, "bs")) {
+ call gtyclose (gty)
+ return (max (ublkfac,1))
+ }
+ iferr (fb = max (gtygeti (gty, "fb"), 1))
+ fb = 1
+
+ # Determine whether the device is a fixed or variable blocked
+ # device. Set the fits blocking factor to the value of the fb
+ # parameter if device is fixed block or if the user has
+ # requested the default blocking factor. Set the blocking factor
+ # to the user requested value if the device supports variable
+ # blocking factors.
+
+ if (bs == 0) {
+ if (ublkfac <= 0)
+ blkfac = fb
+ else
+ blkfac = ublkfac
+ } else
+ blkfac = fb
+
+ call gtyclose (gty)
+
+ return (blkfac)
+end
diff --git a/pkg/obsolete/fits/wfits.com b/pkg/obsolete/fits/wfits.com
new file mode 100644
index 00000000..4d2a58f8
--- /dev/null
+++ b/pkg/obsolete/fits/wfits.com
@@ -0,0 +1,15 @@
+# FITS common block
+
+double bscale # FITS scaling factor
+double bzero # FITS offset factor
+int bitpix # Output bits per pixel
+int len_record # Record length in FITS bytes
+int long_header # Print long header?
+int short_header # Print short header?
+int make_image # Make a FITS image?
+int scale # Scale the data with bzero and bscale?
+int autoscale # Allow program to calculate bscale and bzero?
+int blkfac # FITS tape blocking factor
+
+common /wfitscom/ bscale, bzero, bitpix, len_record, long_header, short_header,
+ make_image, scale, autoscale, blkfac
diff --git a/pkg/obsolete/fits/wfits.h b/pkg/obsolete/fits/wfits.h
new file mode 100644
index 00000000..d2a67c34
--- /dev/null
+++ b/pkg/obsolete/fits/wfits.h
@@ -0,0 +1,113 @@
+# WFITS header file
+
+# The basic FITS data structure
+
+define LEN_FITS (44 + SZ_FNAME + 1)
+
+define BSCALE Memd[P2D($1)] # FITS bscale value
+define BZERO Memd[P2D($1+2)] # FITS bzero value
+define TAPEMAX Memd[P2D($1+4)] # IRAF tape max
+define TAPEMIN Memd[P2D($1+6)] # IRAF tape min
+define IRAFMAX Memr[P2R($1+8)] # IRAF image maximum
+define IRAFMIN Memr[P2R($1+9)] # IRAF image minimum
+define BLANK Meml[P2L($1+10)] # FITS blank value
+define FITS_BITPIX Memi[$1+11] # FITS bits per pixel
+define DATA_BITPIX Memi[$1+12] # Data bits per pixel
+define SCALE Memi[$1+13] # Scale data?
+define BLANK_STRING Memc[P2C($1+19)] # String containing FITS blank value
+define TYPE_STRING Memc[P2C($1+31)] # String containing IRAF type
+define IRAFNAME Memc[P2C($1+41)] # IRAF file name
+
+
+# Define the FITS record size
+
+define FITS_RECORD 2880 # Size of standard FITS record (bytes)
+
+# Define the FITS data types
+
+define FITS_BYTE 8 # Number of bits in a FITS byte
+define FITS_SHORT 16 # Number of bits in a FITS short
+define FITS_LONG 32 # Number of bits in a FITS long
+define FITS_REAL -32 # Number of bits in a FITS real * -1
+define FITS_DOUBLE -64 # Number of bits in a FITS double * -1
+
+# Define the FITS precision in decimal digits
+
+define BYTE_PREC 3 # Precision of FITS byte
+define SHORT_PREC 5 # Precision of FITS short
+define LONG_PREC 10 # Precision of FITS long
+
+# Define the FITS blank data values
+
+define BYTE_BLANK 0.0d0 # Blank value for a FITS byte
+define SHORT_BLANK -3.2768d4 # Blank value for a FITS short
+define LONG_BLANK -2.147483648d9 # Blank value for a FITS long
+
+# Define the FITS integer max and min values
+
+define BYTE_MAX 2.55d2 # Max value for a FITS byte
+define BYTE_MIN 1.0d0 # Min value for a FITS byte
+define SHORT_MAX 3.2767d4 # Max value for a FITS short
+define SHORT_MIN -3.2767d4 # Min value for a FITS short
+define LONG_MAX 2.147483647d9 # Max value for a FITS long
+define LONG_MIN -2.147483647d9 # Min value for a FITS long
+
+# Define the FITS card image parameters
+
+define LEN_CARD 80 # Length of FITS header card
+define LEN_KEYWORD 8 # Length of FITS keyword
+define LEN_NAXIS_KYWRD 5 # Length of the NAXIS keyword string
+define COL_VALUE 11 # First column of value field
+
+# Mapping of FITS task keywords to IRAF image header keywords
+
+define NAXIS IM_NDIM($1) # Number of dimensions
+define NAXISN IM_LEN($1, $2) # Length of each dimension
+define OBJECT IM_TITLE($1) # Image title
+define HISTORY IM_HISTORY($1) # History
+define UNKNOWN Memc[($1+IMU-1)*SZ_STRUCT+1] # IRAF user area
+
+define PIXTYPE IM_PIXTYPE($1) # Image pixel type
+define NBPIX IM_NBPIX($1) # Number of bad pixels
+define LIMTIME IM_LIMTIME($1) # Last modify limits time
+define MTIME IM_MTIME($1) # Last modify time
+define CTIME IM_CTIME($1) # Create time
+
+define LEN_USERAREA 28800 # Default user area size
+
+# Set up a structure for the WFITS parameters
+
+# Define the required keywords
+
+define FIRST_CARD 1 # FITS simple parameter
+define SECOND_CARD 2 # FITS bitpix parameter
+define THIRD_CARD 3 # FITS naxis parameter
+
+# Define the optional FITS KEYWORD parameters
+
+define NOPTIONS 12 # Number of optional keywords
+
+define KEY_BSCALE 1 # FITS bscale parameter
+define KEY_BZERO 2 # FITS bzero parameter
+define KEY_BUNIT 3 # FITS physical units
+define KEY_BLANK 4 # FITS value of blank pixel
+define KEY_OBJECT 5 # FITS title string
+define KEY_ORIGIN 6 # Origin of FITS tape
+define KEY_DATE 7 # Date the tape was written
+define KEY_IRAFNAME 8 # Root name of IRAF image
+define KEY_IRAFMAX 9 # Maximum value of IRAF image
+define KEY_IRAFMIN 10 # Minimum value of IRAF image
+define KEY_IRAFBP 11 # Bits per pixel in IRAF image
+define KEY_IRAFTYPE 12 # IRAF image data type
+
+define LEN_STRING 8 # Minimum length of a string parameter
+define LEN_OBJECT 63 # Maximum length of string parameter
+define LEN_ALIGN 18 # Maximum length for aligning parameter
+define LEN_ORIGIN 9 # Length of origin string
+define LEN_BLANK 11 # Length of the blank string
+define NDEC_REAL 7 # Precision of real data
+define NDEC_DOUBLE 11 # Precision of double precision data
+
+# Miscellaneous
+
+define CENTURY 1900
diff --git a/pkg/obsolete/fixcol.gx b/pkg/obsolete/fixcol.gx
new file mode 100644
index 00000000..86e65688
--- /dev/null
+++ b/pkg/obsolete/fixcol.gx
@@ -0,0 +1,45 @@
+include <imhdr.h>
+include <imset.h>
+
+$for (silrdx)
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcol$t (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2$t(), imps2$t()
+
+begin
+ c = imps2$t (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2$t (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovk$t (Mem$t[a + i - 1], Mem$t[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2$t (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovk$t (Mem$t[a + i - 1], Mem$t[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2$t (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2$t (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Mem$t[a + i - 1]
+ f2 = Mem$t[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Mem$t[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+$endfor
diff --git a/pkg/obsolete/fixcol.x b/pkg/obsolete/fixcol.x
new file mode 100644
index 00000000..aa21a13a
--- /dev/null
+++ b/pkg/obsolete/fixcol.x
@@ -0,0 +1,248 @@
+include <imhdr.h>
+include <imset.h>
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcols (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2s(), imps2s()
+
+begin
+ c = imps2s (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2s (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovks (Mems[a + i - 1], Mems[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2s (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovks (Mems[a + i - 1], Mems[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2s (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2s (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Mems[a + i - 1]
+ f2 = Mems[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Mems[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcoli (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2i(), imps2i()
+
+begin
+ c = imps2i (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2i (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovki (Memi[a + i - 1], Memi[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2i (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovki (Memi[a + i - 1], Memi[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2i (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2i (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memi[a + i - 1]
+ f2 = Memi[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memi[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcoll (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2l(), imps2l()
+
+begin
+ c = imps2l (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2l (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkl (Meml[a + i - 1], Meml[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2l (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkl (Meml[a + i - 1], Meml[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2l (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2l (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Meml[a + i - 1]
+ f2 = Meml[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Meml[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcolr (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2r(), imps2r()
+
+begin
+ c = imps2r (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2r (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkr (Memr[a + i - 1], Memr[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2r (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkr (Memr[a + i - 1], Memr[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2r (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2r (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memr[a + i - 1]
+ f2 = Memr[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memr[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcold (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2d(), imps2d()
+
+begin
+ c = imps2d (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2d (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkd (Memd[a + i - 1], Memd[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2d (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkd (Memd[a + i - 1], Memd[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2d (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2d (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memd[a + i - 1]
+ f2 = Memd[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memd[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcolx (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2x(), imps2x()
+
+begin
+ c = imps2x (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2x (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkx (Memx[a + i - 1], Memx[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2x (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkx (Memx[a + i - 1], Memx[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2x (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2x (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memx[a + i - 1]
+ f2 = Memx[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memx[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
diff --git a/pkg/obsolete/fixline.gx b/pkg/obsolete/fixline.gx
new file mode 100644
index 00000000..8a6c3672
--- /dev/null
+++ b/pkg/obsolete/fixline.gx
@@ -0,0 +1,50 @@
+include <imhdr.h>
+include <imset.h>
+
+$for (silrdx)
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixline$t (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+$if (datatype == x)
+complex f1, f2
+$else $if (datatype == d)
+double f1, f2
+$else
+real f1, f2
+$endif $endif
+pointer a, b, c
+
+pointer imgs2$t(), imps2$t()
+
+begin
+ c = imps2$t (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2$t (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amov$t (Mem$t[a], Mem$t[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2$t (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amov$t (Mem$t[a], Mem$t[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2$t (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2$t (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsu$t (Mem$t[a], Mem$t[b], Mem$t[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+$endfor
diff --git a/pkg/obsolete/fixline.x b/pkg/obsolete/fixline.x
new file mode 100644
index 00000000..d11c031f
--- /dev/null
+++ b/pkg/obsolete/fixline.x
@@ -0,0 +1,242 @@
+include <imhdr.h>
+include <imset.h>
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlines (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2s(), imps2s()
+
+begin
+ c = imps2s (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2s (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovs (Mems[a], Mems[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2s (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovs (Mems[a], Mems[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2s (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2s (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsus (Mems[a], Mems[b], Mems[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlinei (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2i(), imps2i()
+
+begin
+ c = imps2i (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2i (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovi (Memi[a], Memi[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2i (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovi (Memi[a], Memi[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2i (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2i (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsui (Memi[a], Memi[b], Memi[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlinel (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2l(), imps2l()
+
+begin
+ c = imps2l (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2l (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovl (Meml[a], Meml[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2l (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovl (Meml[a], Meml[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2l (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2l (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsul (Meml[a], Meml[b], Meml[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixliner (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2r(), imps2r()
+
+begin
+ c = imps2r (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2r (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovr (Memr[a], Memr[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2r (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovr (Memr[a], Memr[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2r (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2r (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsur (Memr[a], Memr[b], Memr[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlined (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+double f1, f2
+pointer a, b, c
+
+pointer imgs2d(), imps2d()
+
+begin
+ c = imps2d (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2d (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovd (Memd[a], Memd[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2d (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovd (Memd[a], Memd[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2d (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2d (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsud (Memd[a], Memd[b], Memd[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlinex (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+complex f1, f2
+pointer a, b, c
+
+pointer imgs2x(), imps2x()
+
+begin
+ c = imps2x (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2x (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovx (Memx[a], Memx[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2x (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovx (Memx[a], Memx[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2x (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2x (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsux (Memx[a], Memx[b], Memx[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
diff --git a/pkg/obsolete/generic/fixcol.x b/pkg/obsolete/generic/fixcol.x
new file mode 100644
index 00000000..ef64694a
--- /dev/null
+++ b/pkg/obsolete/generic/fixcol.x
@@ -0,0 +1,250 @@
+include <imhdr.h>
+include <imset.h>
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcols (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2s(), imps2s()
+
+begin
+ c = imps2s (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2s (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovks (Mems[a + i - 1], Mems[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2s (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovks (Mems[a + i - 1], Mems[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2s (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2s (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Mems[a + i - 1]
+ f2 = Mems[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Mems[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcoli (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2i(), imps2i()
+
+begin
+ c = imps2i (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2i (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovki (Memi[a + i - 1], Memi[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2i (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovki (Memi[a + i - 1], Memi[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2i (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2i (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memi[a + i - 1]
+ f2 = Memi[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memi[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcoll (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2l(), imps2l()
+
+begin
+ c = imps2l (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2l (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkl (Meml[a + i - 1], Meml[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2l (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkl (Meml[a + i - 1], Meml[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2l (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2l (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Meml[a + i - 1]
+ f2 = Meml[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Meml[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcolr (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2r(), imps2r()
+
+begin
+ c = imps2r (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2r (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkr (Memr[a + i - 1], Memr[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2r (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkr (Memr[a + i - 1], Memr[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2r (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2r (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memr[a + i - 1]
+ f2 = Memr[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memr[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcold (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2d(), imps2d()
+
+begin
+ c = imps2d (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2d (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkd (Memd[a + i - 1], Memd[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2d (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkd (Memd[a + i - 1], Memd[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2d (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2d (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memd[a + i - 1]
+ f2 = Memd[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memd[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
+
+# FIXCOL -- Linearly interpolate columns across a region.
+
+procedure fixcolx (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, j, nx, ny
+real f1, f2, scale
+pointer a, b, c
+pointer imgs2x(), imps2x()
+
+begin
+ c = imps2x (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (x1 == 1) {
+ a = imgs2x (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny
+ call amovkx (Memx[a + i - 1], Memx[c + (i - 1) * nx], nx)
+ } else if (x2 == IM_LEN (image, 1)) {
+ a = imgs2x (image, x1 - 1, x1 - 1, y1, y2)
+ do i = 1, ny
+ call amovkx (Memx[a + i - 1], Memx[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2x (image, x1 - 1, x1 - 1, y1, y2)
+ b = imgs2x (image, x2 + 1, x2 + 1, y1, y2)
+ do i = 1, ny {
+ f1 = Memx[a + i - 1]
+ f2 = Memx[b + i - 1]
+ scale = (f2 - f1) / (nx + 1)
+ do j = 1, nx
+ Memx[c + (i - 1) * nx + j - 1] = j * scale + f1
+ }
+ }
+end
+
+
diff --git a/pkg/obsolete/generic/fixline.x b/pkg/obsolete/generic/fixline.x
new file mode 100644
index 00000000..86fcdcc0
--- /dev/null
+++ b/pkg/obsolete/generic/fixline.x
@@ -0,0 +1,244 @@
+include <imhdr.h>
+include <imset.h>
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlines (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2s(), imps2s()
+
+begin
+ c = imps2s (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2s (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovs (Mems[a], Mems[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2s (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovs (Mems[a], Mems[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2s (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2s (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsus (Mems[a], Mems[b], Mems[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlinei (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2i(), imps2i()
+
+begin
+ c = imps2i (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2i (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovi (Memi[a], Memi[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2i (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovi (Memi[a], Memi[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2i (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2i (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsui (Memi[a], Memi[b], Memi[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlinel (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2l(), imps2l()
+
+begin
+ c = imps2l (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2l (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovl (Meml[a], Meml[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2l (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovl (Meml[a], Meml[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2l (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2l (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsul (Meml[a], Meml[b], Meml[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixliner (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+real f1, f2
+pointer a, b, c
+
+pointer imgs2r(), imps2r()
+
+begin
+ c = imps2r (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2r (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovr (Memr[a], Memr[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2r (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovr (Memr[a], Memr[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2r (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2r (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsur (Memr[a], Memr[b], Memr[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlined (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+double f1, f2
+pointer a, b, c
+
+pointer imgs2d(), imps2d()
+
+begin
+ c = imps2d (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2d (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovd (Memd[a], Memd[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2d (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovd (Memd[a], Memd[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2d (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2d (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsud (Memd[a], Memd[b], Memd[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
+
+# FIXLINE -- Linearly interpolate lines across a region.
+
+procedure fixlinex (image, x1, x2, y1, y2)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+
+int i, nx, ny
+complex f1, f2
+pointer a, b, c
+
+pointer imgs2x(), imps2x()
+
+begin
+ c = imps2x (image, x1, x2, y1, y2)
+
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+ if (y1 == 1) {
+ a = imgs2x (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny
+ call amovx (Memx[a], Memx[c + (i - 1) * nx], nx)
+ } else if (y2 == IM_LEN (image, 2)) {
+ a = imgs2x (image, x1, x2, y1 - 1, y1 - 1)
+ do i = 1, ny
+ call amovx (Memx[a], Memx[c + (i - 1) * nx], nx)
+ } else {
+ call imseti (image, IM_NBUFS, 2)
+ a = imgs2x (image, x1, x2, y1 - 1, y1 - 1)
+ b = imgs2x (image, x1, x2, y2 + 1, y2 + 1)
+ do i = 1, ny {
+ f2 = i / (ny + 1.)
+ f1 = 1 - f2
+ call awsux (Memx[a], Memx[b], Memx[c+(i-1)*nx], nx, f1, f2)
+ }
+ }
+end
+
+
diff --git a/pkg/obsolete/generic/mkpkg b/pkg/obsolete/generic/mkpkg
new file mode 100644
index 00000000..b38ee3df
--- /dev/null
+++ b/pkg/obsolete/generic/mkpkg
@@ -0,0 +1,11 @@
+# Make generic routines.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ fixcol.x <imhdr.h> <imset.h>
+ fixline.x <imhdr.h> <imset.h>
+ ;
diff --git a/pkg/obsolete/imcombine/generic/icaclip.x b/pkg/obsolete/imcombine/generic/icaclip.x
new file mode 100644
index 00000000..2dd4d31e
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icaclip.x
@@ -0,0 +1,2198 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 3 # Minimum number of images for this algorithm
+
+
+# IC_AAVSIGCLIP -- Reject pixels using an average sigma about the average
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_aavsigclips (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, s1, r, one
+data one /1.0/
+pointer sp, sums, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (sums, npts, TY_REAL)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Since the unweighted average is computed here possibly skip combining
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Compute the unweighted average with the high and low rejected and
+ # the poisson scaled average sigma. There must be at least three
+ # pixels at each point to define the average and contributions to
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ nin = n[1]
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3)
+ next
+
+ # Unweighted average with the high and low rejected
+ low = Mems[d[1]+k]
+ high = Mems[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Mems[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Mems[dp1]
+ l = Memi[mp1]
+ s1 = max (one, (a + zeros[l]) / scales[l])
+ s = s + (d1 - a) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, a)
+ do j = 1, n1
+ s = s + (Mems[d[j]+k] - a) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the average and sum for later.
+ average[i] = a
+ Memr[sums+k] = sum
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+
+ # Reject pixels and compute the final average (if needed).
+ # There must be at least three pixels at each point for rejection.
+ # Iteratively scale the mean sigma and reject pixels
+ # Compact the data and keep track of the image IDs if needed.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (2, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Mems[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mems[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ a = average[i]
+ sum = Memr[sums+k]
+
+ repeat {
+ n2 = n1
+ if (s > 0.) {
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Mems[dp1]
+ l = Memi[mp1]
+ s1 = s * sqrt (max (one, (a+zeros[l]) / scales[l]))
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ s1 = s * sqrt (max (one, a))
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Mems[dp1]
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mems[dp1]
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Mems[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mems[dp1]
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Mems[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MAVSIGCLIP -- Reject pixels using an average sigma about the median
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_mavsigclips (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+pointer sp, resid, mp1, mp2
+real med, low, high, r, s, s1, one
+data one /1.0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute the poisson scaled average sigma about the median.
+ # There must be at least three pixels at each point to define
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ s = 0.
+ n2 = 0
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3) {
+ if (n1 == 0)
+ median[i] = blank
+ else if (n1 == 1)
+ median[i] = Mems[d[1]+k]
+ else {
+ low = Mems[d[1]+k]
+ high = Mems[d[2]+k]
+ median[i] = (low + high) / 2.
+ }
+ next
+ }
+
+ # Median
+ n3 = 1 + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Mems[d[n3-1]+k]
+ high = Mems[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Mems[d[n3]+k]
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ l = Memi[m[j]+k]
+ s1 = max (one, (med + zeros[l]) / scales[l])
+ s = s + (Mems[d[j]+k] - med) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, med)
+ do j = 1, n1
+ s = s + (Mems[d[j]+k] - med) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the median for later.
+ median[i] = med
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+ else
+ return
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 < max (3, maxkeep+1))
+ next
+ nl = 1
+ nh = n1
+ med = median[i]
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 >= max (MINCLIP, maxkeep+1) && s > 0.) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (med - Mems[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (Mems[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ s1 = s * sqrt (max (one, med))
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Mems[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Mems[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Mems[d[n3-1]+k]
+ high = Mems[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Mems[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Mems[d[n3-1]+k]
+ high = Mems[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Mems[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mems[d[l]+k] = Mems[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mems[d[l]+k] = Mems[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_AAVSIGCLIP -- Reject pixels using an average sigma about the average
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_aavsigclipi (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, s1, r, one
+data one /1.0/
+pointer sp, sums, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (sums, npts, TY_REAL)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Since the unweighted average is computed here possibly skip combining
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Compute the unweighted average with the high and low rejected and
+ # the poisson scaled average sigma. There must be at least three
+ # pixels at each point to define the average and contributions to
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ nin = n[1]
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3)
+ next
+
+ # Unweighted average with the high and low rejected
+ low = Memi[d[1]+k]
+ high = Memi[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memi[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Memi[dp1]
+ l = Memi[mp1]
+ s1 = max (one, (a + zeros[l]) / scales[l])
+ s = s + (d1 - a) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, a)
+ do j = 1, n1
+ s = s + (Memi[d[j]+k] - a) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the average and sum for later.
+ average[i] = a
+ Memr[sums+k] = sum
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+
+ # Reject pixels and compute the final average (if needed).
+ # There must be at least three pixels at each point for rejection.
+ # Iteratively scale the mean sigma and reject pixels
+ # Compact the data and keep track of the image IDs if needed.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (2, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memi[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memi[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ a = average[i]
+ sum = Memr[sums+k]
+
+ repeat {
+ n2 = n1
+ if (s > 0.) {
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Memi[dp1]
+ l = Memi[mp1]
+ s1 = s * sqrt (max (one, (a+zeros[l]) / scales[l]))
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ s1 = s * sqrt (max (one, a))
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Memi[dp1]
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memi[dp1]
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memi[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memi[dp1]
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memi[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MAVSIGCLIP -- Reject pixels using an average sigma about the median
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_mavsigclipi (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+pointer sp, resid, mp1, mp2
+real med, low, high, r, s, s1, one
+data one /1.0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute the poisson scaled average sigma about the median.
+ # There must be at least three pixels at each point to define
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ s = 0.
+ n2 = 0
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3) {
+ if (n1 == 0)
+ median[i] = blank
+ else if (n1 == 1)
+ median[i] = Memi[d[1]+k]
+ else {
+ low = Memi[d[1]+k]
+ high = Memi[d[2]+k]
+ median[i] = (low + high) / 2.
+ }
+ next
+ }
+
+ # Median
+ n3 = 1 + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memi[d[n3-1]+k]
+ high = Memi[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memi[d[n3]+k]
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ l = Memi[m[j]+k]
+ s1 = max (one, (med + zeros[l]) / scales[l])
+ s = s + (Memi[d[j]+k] - med) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, med)
+ do j = 1, n1
+ s = s + (Memi[d[j]+k] - med) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the median for later.
+ median[i] = med
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+ else
+ return
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 < max (3, maxkeep+1))
+ next
+ nl = 1
+ nh = n1
+ med = median[i]
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 >= max (MINCLIP, maxkeep+1) && s > 0.) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (med - Memi[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (Memi[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ s1 = s * sqrt (max (one, med))
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memi[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memi[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memi[d[n3-1]+k]
+ high = Memi[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memi[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memi[d[n3-1]+k]
+ high = Memi[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memi[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memi[d[l]+k] = Memi[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memi[d[l]+k] = Memi[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_AAVSIGCLIP -- Reject pixels using an average sigma about the average
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_aavsigclipr (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, s1, r, one
+data one /1.0/
+pointer sp, sums, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (sums, npts, TY_REAL)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Since the unweighted average is computed here possibly skip combining
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Compute the unweighted average with the high and low rejected and
+ # the poisson scaled average sigma. There must be at least three
+ # pixels at each point to define the average and contributions to
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ nin = n[1]
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3)
+ next
+
+ # Unweighted average with the high and low rejected
+ low = Memr[d[1]+k]
+ high = Memr[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memr[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Memr[dp1]
+ l = Memi[mp1]
+ s1 = max (one, (a + zeros[l]) / scales[l])
+ s = s + (d1 - a) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, a)
+ do j = 1, n1
+ s = s + (Memr[d[j]+k] - a) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the average and sum for later.
+ average[i] = a
+ Memr[sums+k] = sum
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+
+ # Reject pixels and compute the final average (if needed).
+ # There must be at least three pixels at each point for rejection.
+ # Iteratively scale the mean sigma and reject pixels
+ # Compact the data and keep track of the image IDs if needed.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (2, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memr[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memr[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ a = average[i]
+ sum = Memr[sums+k]
+
+ repeat {
+ n2 = n1
+ if (s > 0.) {
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Memr[dp1]
+ l = Memi[mp1]
+ s1 = s * sqrt (max (one, (a+zeros[l]) / scales[l]))
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ s1 = s * sqrt (max (one, a))
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Memr[dp1]
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memr[dp1]
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memr[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memr[dp1]
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memr[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MAVSIGCLIP -- Reject pixels using an average sigma about the median
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_mavsigclipr (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+pointer sp, resid, mp1, mp2
+real med, low, high, r, s, s1, one
+data one /1.0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute the poisson scaled average sigma about the median.
+ # There must be at least three pixels at each point to define
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ s = 0.
+ n2 = 0
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3) {
+ if (n1 == 0)
+ median[i] = blank
+ else if (n1 == 1)
+ median[i] = Memr[d[1]+k]
+ else {
+ low = Memr[d[1]+k]
+ high = Memr[d[2]+k]
+ median[i] = (low + high) / 2.
+ }
+ next
+ }
+
+ # Median
+ n3 = 1 + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memr[d[n3-1]+k]
+ high = Memr[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memr[d[n3]+k]
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ l = Memi[m[j]+k]
+ s1 = max (one, (med + zeros[l]) / scales[l])
+ s = s + (Memr[d[j]+k] - med) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, med)
+ do j = 1, n1
+ s = s + (Memr[d[j]+k] - med) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the median for later.
+ median[i] = med
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+ else
+ return
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 < max (3, maxkeep+1))
+ next
+ nl = 1
+ nh = n1
+ med = median[i]
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 >= max (MINCLIP, maxkeep+1) && s > 0.) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (med - Memr[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (Memr[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ s1 = s * sqrt (max (one, med))
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memr[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memr[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memr[d[n3-1]+k]
+ high = Memr[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memr[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memr[d[n3-1]+k]
+ high = Memr[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memr[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memr[d[l]+k] = Memr[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memr[d[l]+k] = Memr[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_AAVSIGCLIP -- Reject pixels using an average sigma about the average
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_aavsigclipd (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+double average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+double d1, low, high, sum, a, s, s1, r, one
+data one /1.0D0/
+pointer sp, sums, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (sums, npts, TY_REAL)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Since the unweighted average is computed here possibly skip combining
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Compute the unweighted average with the high and low rejected and
+ # the poisson scaled average sigma. There must be at least three
+ # pixels at each point to define the average and contributions to
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ nin = n[1]
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3)
+ next
+
+ # Unweighted average with the high and low rejected
+ low = Memd[d[1]+k]
+ high = Memd[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memd[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Memd[dp1]
+ l = Memi[mp1]
+ s1 = max (one, (a + zeros[l]) / scales[l])
+ s = s + (d1 - a) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, a)
+ do j = 1, n1
+ s = s + (Memd[d[j]+k] - a) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the average and sum for later.
+ average[i] = a
+ Memr[sums+k] = sum
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+
+ # Reject pixels and compute the final average (if needed).
+ # There must be at least three pixels at each point for rejection.
+ # Iteratively scale the mean sigma and reject pixels
+ # Compact the data and keep track of the image IDs if needed.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (2, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memd[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memd[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ a = average[i]
+ sum = Memr[sums+k]
+
+ repeat {
+ n2 = n1
+ if (s > 0.) {
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Memd[dp1]
+ l = Memi[mp1]
+ s1 = s * sqrt (max (one, (a+zeros[l]) / scales[l]))
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ s1 = s * sqrt (max (one, a))
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Memd[dp1]
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memd[dp1]
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memd[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memd[dp1]
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memd[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MAVSIGCLIP -- Reject pixels using an average sigma about the median
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_mavsigclipd (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+double median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+pointer sp, resid, mp1, mp2
+double med, low, high, r, s, s1, one
+data one /1.0D0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute the poisson scaled average sigma about the median.
+ # There must be at least three pixels at each point to define
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ s = 0.
+ n2 = 0
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3) {
+ if (n1 == 0)
+ median[i] = blank
+ else if (n1 == 1)
+ median[i] = Memd[d[1]+k]
+ else {
+ low = Memd[d[1]+k]
+ high = Memd[d[2]+k]
+ median[i] = (low + high) / 2.
+ }
+ next
+ }
+
+ # Median
+ n3 = 1 + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memd[d[n3-1]+k]
+ high = Memd[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memd[d[n3]+k]
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ l = Memi[m[j]+k]
+ s1 = max (one, (med + zeros[l]) / scales[l])
+ s = s + (Memd[d[j]+k] - med) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, med)
+ do j = 1, n1
+ s = s + (Memd[d[j]+k] - med) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the median for later.
+ median[i] = med
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+ else
+ return
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 < max (3, maxkeep+1))
+ next
+ nl = 1
+ nh = n1
+ med = median[i]
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 >= max (MINCLIP, maxkeep+1) && s > 0.) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (med - Memd[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (Memd[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ s1 = s * sqrt (max (one, med))
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memd[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memd[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memd[d[n3-1]+k]
+ high = Memd[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memd[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Memd[d[n3-1]+k]
+ high = Memd[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Memd[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memd[d[l]+k] = Memd[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memd[d[l]+k] = Memd[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/imcombine/generic/icaverage.x b/pkg/obsolete/imcombine/generic/icaverage.x
new file mode 100644
index 00000000..a2f6498d
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icaverage.x
@@ -0,0 +1,337 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+
+# IC_AVERAGE -- Compute the average image line.
+# Options include a weight average.
+
+procedure ic_averages (d, m, n, wts, npts, doblank, average)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+int doblank # Set blank values?
+real average[npts] # Average (returned)
+
+int i, j, k
+real sumwt, wt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average without checking the
+ # number of points and using the fact that the weights are normalized.
+ # If all the data has been excluded set the average to the blank value
+ # if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts) {
+ do i = 1, npts {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Mems[d[1]+k] * wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Mems[d[j]+k] * wt
+ }
+ average[i] = sum
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ sum = Mems[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Mems[d[j]+k]
+ average[i] = sum / n[i]
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Mems[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Mems[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ average[i] = sum / sumwt
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ sum = Mems[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Mems[d[j]+k]
+ average[i] = sum / n[i]
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_AVERAGE -- Compute the average image line.
+# Options include a weight average.
+
+procedure ic_averagei (d, m, n, wts, npts, doblank, average)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+int doblank # Set blank values?
+real average[npts] # Average (returned)
+
+int i, j, k
+real sumwt, wt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average without checking the
+ # number of points and using the fact that the weights are normalized.
+ # If all the data has been excluded set the average to the blank value
+ # if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts) {
+ do i = 1, npts {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memi[d[1]+k] * wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memi[d[j]+k] * wt
+ }
+ average[i] = sum
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ sum = Memi[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Memi[d[j]+k]
+ average[i] = sum / n[i]
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memi[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memi[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ average[i] = sum / sumwt
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ sum = Memi[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Memi[d[j]+k]
+ average[i] = sum / n[i]
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_AVERAGE -- Compute the average image line.
+# Options include a weight average.
+
+procedure ic_averager (d, m, n, wts, npts, doblank, average)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+int doblank # Set blank values?
+real average[npts] # Average (returned)
+
+int i, j, k
+real sumwt, wt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average without checking the
+ # number of points and using the fact that the weights are normalized.
+ # If all the data has been excluded set the average to the blank value
+ # if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts) {
+ do i = 1, npts {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memr[d[1]+k] * wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memr[d[j]+k] * wt
+ }
+ average[i] = sum
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ sum = Memr[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Memr[d[j]+k]
+ average[i] = sum / n[i]
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memr[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memr[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ average[i] = sum / sumwt
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ sum = Memr[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Memr[d[j]+k]
+ average[i] = sum / n[i]
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_AVERAGE -- Compute the average image line.
+# Options include a weight average.
+
+procedure ic_averaged (d, m, n, wts, npts, doblank, average)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+int doblank # Set blank values?
+double average[npts] # Average (returned)
+
+int i, j, k
+real sumwt, wt
+double sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average without checking the
+ # number of points and using the fact that the weights are normalized.
+ # If all the data has been excluded set the average to the blank value
+ # if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts) {
+ do i = 1, npts {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memd[d[1]+k] * wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memd[d[j]+k] * wt
+ }
+ average[i] = sum
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ sum = Memd[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Memd[d[j]+k]
+ average[i] = sum / n[i]
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memd[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memd[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ average[i] = sum / sumwt
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ sum = Memd[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Memd[d[j]+k]
+ average[i] = sum / n[i]
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
diff --git a/pkg/obsolete/imcombine/generic/iccclip.x b/pkg/obsolete/imcombine/generic/iccclip.x
new file mode 100644
index 00000000..bf655477
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/iccclip.x
@@ -0,0 +1,1790 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 2 # Mininum number of images for algorithm
+
+
+# IC_ACCDCLIP -- Reject pixels using CCD noise parameters about the average
+
+procedure ic_accdclips (d, m, n, scales, zeros, nm, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model parameters
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, r, zero
+data zero /0.0/
+pointer sp, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are no pixels go on to the combining. Since the unweighted
+ # average is computed here possibly skip the combining later.
+
+ # There must be at least max (1, nkeep) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ } else if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # There must be at least two pixels for rejection. The initial
+ # average is the low/high rejected average except in the case of
+ # just two pixels. The rejections are iterated and the average
+ # is recomputed. Corrections for scaling may be performed.
+ # Depending on other flags the image IDs may also need to be adjusted.
+
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (MINCLIP-1, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Mems[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mems[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ repeat {
+ if (n1 == 2) {
+ sum = Mems[d[1]+k]
+ sum = sum + Mems[d[2]+k]
+ a = sum / 2
+ } else {
+ low = Mems[d[1]+k]
+ high = Mems[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Mems[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+ }
+ n2 = n1
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ l = Memi[mp1]
+ s = scales[l]
+ d1 = max (zero, s * (a + zeros[l]))
+ s = sqrt (nm[1,l] + d1/nm[2,l] + (d1*nm[3,l])**2) / s
+
+ d1 = Mems[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, a)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (j=1; j<=n1; j=j+1) {
+ if (keepids) {
+ l = Memi[m[j]+k]
+ s = max (zero, a)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ dp1 = d[j] + k
+ d1 = Mems[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mems[dp1]
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Mems[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mems[dp1]
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Mems[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ }
+
+ n[i] = n1
+ if (!docombine)
+ if (n1 > 0)
+ average[i] = sum / n1
+ else
+ average[i] = blank
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_CCDCLIP -- Reject pixels using CCD noise parameters about the median
+
+procedure ic_mccdclips (d, m, n, scales, zeros, nm, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, mp1, mp2
+real med, zero
+data zero /0.0/
+
+include "../icombine.com"
+
+begin
+ # There must be at least max (MINCLIP, nkeep+1) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0) {
+ med = Mems[d[n3-1]+k]
+ med = (med + Mems[d[n3]+k]) / 2.
+ } else
+ med = Mems[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (med - Mems[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (Mems[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, med)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (; nl <= n2; nl = nl + 1) {
+ if (keepids) {
+ l = Memi[m[nl]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (med - Mems[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ if (keepids) {
+ l = Memi[m[nh]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (Mems[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mems[d[l]+k] = Mems[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mems[d[l]+k] = Mems[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_ACCDCLIP -- Reject pixels using CCD noise parameters about the average
+
+procedure ic_accdclipi (d, m, n, scales, zeros, nm, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model parameters
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, r, zero
+data zero /0.0/
+pointer sp, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are no pixels go on to the combining. Since the unweighted
+ # average is computed here possibly skip the combining later.
+
+ # There must be at least max (1, nkeep) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ } else if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # There must be at least two pixels for rejection. The initial
+ # average is the low/high rejected average except in the case of
+ # just two pixels. The rejections are iterated and the average
+ # is recomputed. Corrections for scaling may be performed.
+ # Depending on other flags the image IDs may also need to be adjusted.
+
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (MINCLIP-1, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memi[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memi[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ repeat {
+ if (n1 == 2) {
+ sum = Memi[d[1]+k]
+ sum = sum + Memi[d[2]+k]
+ a = sum / 2
+ } else {
+ low = Memi[d[1]+k]
+ high = Memi[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memi[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+ }
+ n2 = n1
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ l = Memi[mp1]
+ s = scales[l]
+ d1 = max (zero, s * (a + zeros[l]))
+ s = sqrt (nm[1,l] + d1/nm[2,l] + (d1*nm[3,l])**2) / s
+
+ d1 = Memi[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, a)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (j=1; j<=n1; j=j+1) {
+ if (keepids) {
+ l = Memi[m[j]+k]
+ s = max (zero, a)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ dp1 = d[j] + k
+ d1 = Memi[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memi[dp1]
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memi[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memi[dp1]
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memi[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ }
+
+ n[i] = n1
+ if (!docombine)
+ if (n1 > 0)
+ average[i] = sum / n1
+ else
+ average[i] = blank
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_CCDCLIP -- Reject pixels using CCD noise parameters about the median
+
+procedure ic_mccdclipi (d, m, n, scales, zeros, nm, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, mp1, mp2
+real med, zero
+data zero /0.0/
+
+include "../icombine.com"
+
+begin
+ # There must be at least max (MINCLIP, nkeep+1) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0) {
+ med = Memi[d[n3-1]+k]
+ med = (med + Memi[d[n3]+k]) / 2.
+ } else
+ med = Memi[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (med - Memi[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (Memi[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, med)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (; nl <= n2; nl = nl + 1) {
+ if (keepids) {
+ l = Memi[m[nl]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (med - Memi[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ if (keepids) {
+ l = Memi[m[nh]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (Memi[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memi[d[l]+k] = Memi[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memi[d[l]+k] = Memi[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_ACCDCLIP -- Reject pixels using CCD noise parameters about the average
+
+procedure ic_accdclipr (d, m, n, scales, zeros, nm, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model parameters
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, r, zero
+data zero /0.0/
+pointer sp, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are no pixels go on to the combining. Since the unweighted
+ # average is computed here possibly skip the combining later.
+
+ # There must be at least max (1, nkeep) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ } else if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # There must be at least two pixels for rejection. The initial
+ # average is the low/high rejected average except in the case of
+ # just two pixels. The rejections are iterated and the average
+ # is recomputed. Corrections for scaling may be performed.
+ # Depending on other flags the image IDs may also need to be adjusted.
+
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (MINCLIP-1, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memr[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memr[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ repeat {
+ if (n1 == 2) {
+ sum = Memr[d[1]+k]
+ sum = sum + Memr[d[2]+k]
+ a = sum / 2
+ } else {
+ low = Memr[d[1]+k]
+ high = Memr[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memr[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+ }
+ n2 = n1
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ l = Memi[mp1]
+ s = scales[l]
+ d1 = max (zero, s * (a + zeros[l]))
+ s = sqrt (nm[1,l] + d1/nm[2,l] + (d1*nm[3,l])**2) / s
+
+ d1 = Memr[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, a)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (j=1; j<=n1; j=j+1) {
+ if (keepids) {
+ l = Memi[m[j]+k]
+ s = max (zero, a)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ dp1 = d[j] + k
+ d1 = Memr[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memr[dp1]
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memr[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memr[dp1]
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memr[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ }
+
+ n[i] = n1
+ if (!docombine)
+ if (n1 > 0)
+ average[i] = sum / n1
+ else
+ average[i] = blank
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_CCDCLIP -- Reject pixels using CCD noise parameters about the median
+
+procedure ic_mccdclipr (d, m, n, scales, zeros, nm, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, mp1, mp2
+real med, zero
+data zero /0.0/
+
+include "../icombine.com"
+
+begin
+ # There must be at least max (MINCLIP, nkeep+1) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0) {
+ med = Memr[d[n3-1]+k]
+ med = (med + Memr[d[n3]+k]) / 2.
+ } else
+ med = Memr[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (med - Memr[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (Memr[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, med)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (; nl <= n2; nl = nl + 1) {
+ if (keepids) {
+ l = Memi[m[nl]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (med - Memr[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ if (keepids) {
+ l = Memi[m[nh]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (Memr[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memr[d[l]+k] = Memr[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memr[d[l]+k] = Memr[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_ACCDCLIP -- Reject pixels using CCD noise parameters about the average
+
+procedure ic_accdclipd (d, m, n, scales, zeros, nm, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model parameters
+int nimages # Number of images
+int npts # Number of output points per line
+double average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+double d1, low, high, sum, a, s, r, zero
+data zero /0.0D0/
+pointer sp, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are no pixels go on to the combining. Since the unweighted
+ # average is computed here possibly skip the combining later.
+
+ # There must be at least max (1, nkeep) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ } else if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # There must be at least two pixels for rejection. The initial
+ # average is the low/high rejected average except in the case of
+ # just two pixels. The rejections are iterated and the average
+ # is recomputed. Corrections for scaling may be performed.
+ # Depending on other flags the image IDs may also need to be adjusted.
+
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (MINCLIP-1, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memd[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memd[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ repeat {
+ if (n1 == 2) {
+ sum = Memd[d[1]+k]
+ sum = sum + Memd[d[2]+k]
+ a = sum / 2
+ } else {
+ low = Memd[d[1]+k]
+ high = Memd[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memd[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+ }
+ n2 = n1
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ l = Memi[mp1]
+ s = scales[l]
+ d1 = max (zero, s * (a + zeros[l]))
+ s = sqrt (nm[1,l] + d1/nm[2,l] + (d1*nm[3,l])**2) / s
+
+ d1 = Memd[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, a)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (j=1; j<=n1; j=j+1) {
+ if (keepids) {
+ l = Memi[m[j]+k]
+ s = max (zero, a)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ dp1 = d[j] + k
+ d1 = Memd[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memd[dp1]
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memd[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memd[dp1]
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memd[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ }
+
+ n[i] = n1
+ if (!docombine)
+ if (n1 > 0)
+ average[i] = sum / n1
+ else
+ average[i] = blank
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_CCDCLIP -- Reject pixels using CCD noise parameters about the median
+
+procedure ic_mccdclipd (d, m, n, scales, zeros, nm, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model
+int nimages # Number of images
+int npts # Number of output points per line
+double median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, mp1, mp2
+double med, zero
+data zero /0.0D0/
+
+include "../icombine.com"
+
+begin
+ # There must be at least max (MINCLIP, nkeep+1) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0) {
+ med = Memd[d[n3-1]+k]
+ med = (med + Memd[d[n3]+k]) / 2.
+ } else
+ med = Memd[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (med - Memd[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (Memd[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, med)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (; nl <= n2; nl = nl + 1) {
+ if (keepids) {
+ l = Memi[m[nl]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (med - Memd[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ if (keepids) {
+ l = Memi[m[nh]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (Memd[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memd[d[l]+k] = Memd[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memd[d[l]+k] = Memd[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/imcombine/generic/icgdata.x b/pkg/obsolete/imcombine/generic/icgdata.x
new file mode 100644
index 00000000..264acc34
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icgdata.x
@@ -0,0 +1,918 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+
+
+# IC_GDATA -- Get line of image and mask data and apply threshold and scaling.
+# Entirely empty lines are excluded. The data are compacted within the
+# input data buffers. If it is required, the connection to the original
+# image index is kept in the returned m data pointers.
+
+procedure ic_gdatas (in, out, dbuf, d, id, n, m, lflag, offsets, scales,
+ zeros, nimages, npts, v1, v2)
+
+pointer in[nimages] # Input images
+pointer out[3] # Output images
+pointer dbuf[nimages] # Data buffers
+pointer d[nimages] # Data pointers
+pointer id[nimages] # ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Empty mask flags
+int offsets[nimages,ARB] # Image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+int nimages # Number of input images
+int npts # NUmber of output points per line
+long v1[ARB], v2[ARB] # Line vectors
+
+int i, j, k, l, ndim, nused
+real a, b
+pointer buf, dp, ip, mp, imgnls()
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ ndim = IM_NDIM(out[1])
+ do i = 1, nimages {
+ if (lflag[i] == D_NONE)
+ next
+ if (dbuf[i] == NULL) {
+ call amovl (v1, v2, IM_MAXDIM)
+ if (project)
+ v2[ndim+1] = i
+ j = imgnls (in[i], d[i], v2)
+ } else {
+ v2[1] = v1[1]
+ do j = 2, ndim
+ v2[j] = v1[j] - offsets[i,j]
+ if (project)
+ v2[ndim+1] = i
+ j = imgnls (in[i], buf, v2)
+ call amovs (Mems[buf], Mems[dbuf[i]+offsets[i,1]],
+ IM_LEN(in[i],1))
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ dp = d[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ a = Mems[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ a = Mems[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+
+ # Check for completely empty lines
+ if (lflag[i] == D_MIX) {
+ lflag[i] = D_NONE
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ lflag[i] = D_MIX
+ break
+ }
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply scaling (avoiding masked pixels which might overflow?)
+ if (doscale) {
+ if (dflag == D_ALL) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ do j = 1, npts {
+ Mems[dp] = Mems[dp] / a + b
+ dp = dp + 1
+ }
+ }
+ } else if (dflag == D_MIX) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ Mems[dp] = Mems[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0)
+ Mems[dp] = Mems[dp] / a + b
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+ }
+
+ # Sort pointers to exclude unused images.
+ # Use the lflag array to keep track of the image index.
+
+ if (dflag == D_ALL)
+ nused = nimages
+ else {
+ nused = 0
+ do i = 1, nimages
+ if (lflag[i] != D_NONE) {
+ nused = nused + 1
+ d[nused] = d[i]
+ m[nused] = m[i]
+ lflag[nused] = i
+ }
+ if (nused == 0)
+ dflag = D_NONE
+ }
+
+ # Compact data to remove bad pixels
+ # Keep track of the image indices if needed
+ # If growing mark the end of the included image indices with zero
+
+ if (dflag == D_ALL) {
+ call amovki (nused, n, npts)
+ if (keepids)
+ do i = 1, nimages
+ call amovki (i, Memi[id[i]], npts)
+ } else if (dflag == D_NONE)
+ call aclri (n, npts)
+ else {
+ call aclri (n, npts)
+ if (keepids) {
+ do i = 1, nused {
+ l = lflag[i]
+ dp = d[i]
+ ip = id[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ Mems[d[k]+j-1] = Mems[dp]
+ Memi[id[k]+j-1] = l
+ } else
+ Memi[ip] = l
+ }
+ dp = dp + 1
+ ip = ip + 1
+ mp = mp + 1
+ }
+ }
+ if (grow >= 1.) {
+ do j = 1, npts {
+ do i = n[j]+1, nimages
+ Memi[id[i]+j-1] = 0
+ }
+ }
+ } else {
+ do i = 1, nused {
+ dp = d[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i)
+ Mems[d[k]+j-1] = Mems[dp]
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nimages, TY_SHORT)
+ if (keepids) {
+ call malloc (ip, nimages, TY_INT)
+ call ic_2sorts (d, Mems[dp], id, Memi[ip], n, npts)
+ call mfree (ip, TY_INT)
+ } else
+ call ic_sorts (d, Mems[dp], n, npts)
+ call mfree (dp, TY_SHORT)
+ }
+end
+
+# IC_GDATA -- Get line of image and mask data and apply threshold and scaling.
+# Entirely empty lines are excluded. The data are compacted within the
+# input data buffers. If it is required, the connection to the original
+# image index is kept in the returned m data pointers.
+
+procedure ic_gdatai (in, out, dbuf, d, id, n, m, lflag, offsets, scales,
+ zeros, nimages, npts, v1, v2)
+
+pointer in[nimages] # Input images
+pointer out[3] # Output images
+pointer dbuf[nimages] # Data buffers
+pointer d[nimages] # Data pointers
+pointer id[nimages] # ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Empty mask flags
+int offsets[nimages,ARB] # Image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+int nimages # Number of input images
+int npts # NUmber of output points per line
+long v1[ARB], v2[ARB] # Line vectors
+
+int i, j, k, l, ndim, nused
+real a, b
+pointer buf, dp, ip, mp, imgnli()
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ ndim = IM_NDIM(out[1])
+ do i = 1, nimages {
+ if (lflag[i] == D_NONE)
+ next
+ if (dbuf[i] == NULL) {
+ call amovl (v1, v2, IM_MAXDIM)
+ if (project)
+ v2[ndim+1] = i
+ j = imgnli (in[i], d[i], v2)
+ } else {
+ v2[1] = v1[1]
+ do j = 2, ndim
+ v2[j] = v1[j] - offsets[i,j]
+ if (project)
+ v2[ndim+1] = i
+ j = imgnli (in[i], buf, v2)
+ call amovi (Memi[buf], Memi[dbuf[i]+offsets[i,1]],
+ IM_LEN(in[i],1))
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ dp = d[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ a = Memi[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ a = Memi[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+
+ # Check for completely empty lines
+ if (lflag[i] == D_MIX) {
+ lflag[i] = D_NONE
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ lflag[i] = D_MIX
+ break
+ }
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply scaling (avoiding masked pixels which might overflow?)
+ if (doscale) {
+ if (dflag == D_ALL) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ do j = 1, npts {
+ Memi[dp] = Memi[dp] / a + b
+ dp = dp + 1
+ }
+ }
+ } else if (dflag == D_MIX) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ Memi[dp] = Memi[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0)
+ Memi[dp] = Memi[dp] / a + b
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+ }
+
+ # Sort pointers to exclude unused images.
+ # Use the lflag array to keep track of the image index.
+
+ if (dflag == D_ALL)
+ nused = nimages
+ else {
+ nused = 0
+ do i = 1, nimages
+ if (lflag[i] != D_NONE) {
+ nused = nused + 1
+ d[nused] = d[i]
+ m[nused] = m[i]
+ lflag[nused] = i
+ }
+ if (nused == 0)
+ dflag = D_NONE
+ }
+
+ # Compact data to remove bad pixels
+ # Keep track of the image indices if needed
+ # If growing mark the end of the included image indices with zero
+
+ if (dflag == D_ALL) {
+ call amovki (nused, n, npts)
+ if (keepids)
+ do i = 1, nimages
+ call amovki (i, Memi[id[i]], npts)
+ } else if (dflag == D_NONE)
+ call aclri (n, npts)
+ else {
+ call aclri (n, npts)
+ if (keepids) {
+ do i = 1, nused {
+ l = lflag[i]
+ dp = d[i]
+ ip = id[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ Memi[d[k]+j-1] = Memi[dp]
+ Memi[id[k]+j-1] = l
+ } else
+ Memi[ip] = l
+ }
+ dp = dp + 1
+ ip = ip + 1
+ mp = mp + 1
+ }
+ }
+ if (grow >= 1.) {
+ do j = 1, npts {
+ do i = n[j]+1, nimages
+ Memi[id[i]+j-1] = 0
+ }
+ }
+ } else {
+ do i = 1, nused {
+ dp = d[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i)
+ Memi[d[k]+j-1] = Memi[dp]
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nimages, TY_INT)
+ if (keepids) {
+ call malloc (ip, nimages, TY_INT)
+ call ic_2sorti (d, Memi[dp], id, Memi[ip], n, npts)
+ call mfree (ip, TY_INT)
+ } else
+ call ic_sorti (d, Memi[dp], n, npts)
+ call mfree (dp, TY_INT)
+ }
+end
+
+# IC_GDATA -- Get line of image and mask data and apply threshold and scaling.
+# Entirely empty lines are excluded. The data are compacted within the
+# input data buffers. If it is required, the connection to the original
+# image index is kept in the returned m data pointers.
+
+procedure ic_gdatar (in, out, dbuf, d, id, n, m, lflag, offsets, scales,
+ zeros, nimages, npts, v1, v2)
+
+pointer in[nimages] # Input images
+pointer out[3] # Output images
+pointer dbuf[nimages] # Data buffers
+pointer d[nimages] # Data pointers
+pointer id[nimages] # ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Empty mask flags
+int offsets[nimages,ARB] # Image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+int nimages # Number of input images
+int npts # NUmber of output points per line
+long v1[ARB], v2[ARB] # Line vectors
+
+int i, j, k, l, ndim, nused
+real a, b
+pointer buf, dp, ip, mp, imgnlr()
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ ndim = IM_NDIM(out[1])
+ do i = 1, nimages {
+ if (lflag[i] == D_NONE)
+ next
+ if (dbuf[i] == NULL) {
+ call amovl (v1, v2, IM_MAXDIM)
+ if (project)
+ v2[ndim+1] = i
+ j = imgnlr (in[i], d[i], v2)
+ } else {
+ v2[1] = v1[1]
+ do j = 2, ndim
+ v2[j] = v1[j] - offsets[i,j]
+ if (project)
+ v2[ndim+1] = i
+ j = imgnlr (in[i], buf, v2)
+ call amovr (Memr[buf], Memr[dbuf[i]+offsets[i,1]],
+ IM_LEN(in[i],1))
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ dp = d[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ a = Memr[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ a = Memr[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+
+ # Check for completely empty lines
+ if (lflag[i] == D_MIX) {
+ lflag[i] = D_NONE
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ lflag[i] = D_MIX
+ break
+ }
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply scaling (avoiding masked pixels which might overflow?)
+ if (doscale) {
+ if (dflag == D_ALL) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ do j = 1, npts {
+ Memr[dp] = Memr[dp] / a + b
+ dp = dp + 1
+ }
+ }
+ } else if (dflag == D_MIX) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ Memr[dp] = Memr[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0)
+ Memr[dp] = Memr[dp] / a + b
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+ }
+
+ # Sort pointers to exclude unused images.
+ # Use the lflag array to keep track of the image index.
+
+ if (dflag == D_ALL)
+ nused = nimages
+ else {
+ nused = 0
+ do i = 1, nimages
+ if (lflag[i] != D_NONE) {
+ nused = nused + 1
+ d[nused] = d[i]
+ m[nused] = m[i]
+ lflag[nused] = i
+ }
+ if (nused == 0)
+ dflag = D_NONE
+ }
+
+ # Compact data to remove bad pixels
+ # Keep track of the image indices if needed
+ # If growing mark the end of the included image indices with zero
+
+ if (dflag == D_ALL) {
+ call amovki (nused, n, npts)
+ if (keepids)
+ do i = 1, nimages
+ call amovki (i, Memi[id[i]], npts)
+ } else if (dflag == D_NONE)
+ call aclri (n, npts)
+ else {
+ call aclri (n, npts)
+ if (keepids) {
+ do i = 1, nused {
+ l = lflag[i]
+ dp = d[i]
+ ip = id[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ Memr[d[k]+j-1] = Memr[dp]
+ Memi[id[k]+j-1] = l
+ } else
+ Memi[ip] = l
+ }
+ dp = dp + 1
+ ip = ip + 1
+ mp = mp + 1
+ }
+ }
+ if (grow >= 1.) {
+ do j = 1, npts {
+ do i = n[j]+1, nimages
+ Memi[id[i]+j-1] = 0
+ }
+ }
+ } else {
+ do i = 1, nused {
+ dp = d[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i)
+ Memr[d[k]+j-1] = Memr[dp]
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nimages, TY_REAL)
+ if (keepids) {
+ call malloc (ip, nimages, TY_INT)
+ call ic_2sortr (d, Memr[dp], id, Memi[ip], n, npts)
+ call mfree (ip, TY_INT)
+ } else
+ call ic_sortr (d, Memr[dp], n, npts)
+ call mfree (dp, TY_REAL)
+ }
+end
+
+# IC_GDATA -- Get line of image and mask data and apply threshold and scaling.
+# Entirely empty lines are excluded. The data are compacted within the
+# input data buffers. If it is required, the connection to the original
+# image index is kept in the returned m data pointers.
+
+procedure ic_gdatad (in, out, dbuf, d, id, n, m, lflag, offsets, scales,
+ zeros, nimages, npts, v1, v2)
+
+pointer in[nimages] # Input images
+pointer out[3] # Output images
+pointer dbuf[nimages] # Data buffers
+pointer d[nimages] # Data pointers
+pointer id[nimages] # ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Empty mask flags
+int offsets[nimages,ARB] # Image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+int nimages # Number of input images
+int npts # NUmber of output points per line
+long v1[ARB], v2[ARB] # Line vectors
+
+int i, j, k, l, ndim, nused
+real a, b
+pointer buf, dp, ip, mp, imgnld()
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ ndim = IM_NDIM(out[1])
+ do i = 1, nimages {
+ if (lflag[i] == D_NONE)
+ next
+ if (dbuf[i] == NULL) {
+ call amovl (v1, v2, IM_MAXDIM)
+ if (project)
+ v2[ndim+1] = i
+ j = imgnld (in[i], d[i], v2)
+ } else {
+ v2[1] = v1[1]
+ do j = 2, ndim
+ v2[j] = v1[j] - offsets[i,j]
+ if (project)
+ v2[ndim+1] = i
+ j = imgnld (in[i], buf, v2)
+ call amovd (Memd[buf], Memd[dbuf[i]+offsets[i,1]],
+ IM_LEN(in[i],1))
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ dp = d[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ a = Memd[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ a = Memd[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+
+ # Check for completely empty lines
+ if (lflag[i] == D_MIX) {
+ lflag[i] = D_NONE
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ lflag[i] = D_MIX
+ break
+ }
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply scaling (avoiding masked pixels which might overflow?)
+ if (doscale) {
+ if (dflag == D_ALL) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ do j = 1, npts {
+ Memd[dp] = Memd[dp] / a + b
+ dp = dp + 1
+ }
+ }
+ } else if (dflag == D_MIX) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ Memd[dp] = Memd[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0)
+ Memd[dp] = Memd[dp] / a + b
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+ }
+
+ # Sort pointers to exclude unused images.
+ # Use the lflag array to keep track of the image index.
+
+ if (dflag == D_ALL)
+ nused = nimages
+ else {
+ nused = 0
+ do i = 1, nimages
+ if (lflag[i] != D_NONE) {
+ nused = nused + 1
+ d[nused] = d[i]
+ m[nused] = m[i]
+ lflag[nused] = i
+ }
+ if (nused == 0)
+ dflag = D_NONE
+ }
+
+ # Compact data to remove bad pixels
+ # Keep track of the image indices if needed
+ # If growing mark the end of the included image indices with zero
+
+ if (dflag == D_ALL) {
+ call amovki (nused, n, npts)
+ if (keepids)
+ do i = 1, nimages
+ call amovki (i, Memi[id[i]], npts)
+ } else if (dflag == D_NONE)
+ call aclri (n, npts)
+ else {
+ call aclri (n, npts)
+ if (keepids) {
+ do i = 1, nused {
+ l = lflag[i]
+ dp = d[i]
+ ip = id[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ Memd[d[k]+j-1] = Memd[dp]
+ Memi[id[k]+j-1] = l
+ } else
+ Memi[ip] = l
+ }
+ dp = dp + 1
+ ip = ip + 1
+ mp = mp + 1
+ }
+ }
+ if (grow >= 1.) {
+ do j = 1, npts {
+ do i = n[j]+1, nimages
+ Memi[id[i]+j-1] = 0
+ }
+ }
+ } else {
+ do i = 1, nused {
+ dp = d[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i)
+ Memd[d[k]+j-1] = Memd[dp]
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nimages, TY_DOUBLE)
+ if (keepids) {
+ call malloc (ip, nimages, TY_INT)
+ call ic_2sortd (d, Memd[dp], id, Memi[ip], n, npts)
+ call mfree (ip, TY_INT)
+ } else
+ call ic_sortd (d, Memd[dp], n, npts)
+ call mfree (dp, TY_DOUBLE)
+ }
+end
diff --git a/pkg/obsolete/imcombine/generic/icgrow.x b/pkg/obsolete/imcombine/generic/icgrow.x
new file mode 100644
index 00000000..d47af927
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icgrow.x
@@ -0,0 +1,251 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <pmset.h>
+include "../icombine.h"
+
+# IC_GROW -- Mark neigbors of rejected pixels.
+# The rejected pixels (original plus grown) are saved in pixel masks.
+
+procedure ic_grow (out, v, m, n, buf, nimages, npts, pms)
+
+pointer out # Output image pointer
+long v[ARB] # Output vector
+pointer m[ARB] # Image id pointers
+int n[ARB] # Number of good pixels
+int buf[npts,nimages] # Working buffer
+int nimages # Number of images
+int npts # Number of output points per line
+pointer pms # Pointer to array of pixel masks
+
+int i, j, k, l, line, nl, rop, igrow, nset, or()
+real grow2, i2
+pointer mp, pm, pm_newmask()
+errchk pm_newmask()
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE || grow == 0.)
+ return
+
+ line = v[2]
+ nl = IM_LEN(out,2)
+ rop = or (PIX_SRC, PIX_DST)
+
+ igrow = grow
+ grow2 = grow**2
+ do l = 0, igrow {
+ i2 = grow2 - l * l
+ call aclri (buf, npts*nimages)
+ nset = 0
+ do j = 1, npts {
+ do k = n[j]+1, nimages {
+ mp = Memi[m[k]+j-1]
+ if (mp == 0)
+ next
+ do i = 0, igrow {
+ if (i**2 > i2)
+ next
+ if (j > i)
+ buf[j-i,mp] = 1
+ if (j+i <= npts)
+ buf[j+i,mp] = 1
+ nset = nset + 1
+ }
+ }
+ }
+ if (nset == 0)
+ return
+
+ if (pms == NULL) {
+ call malloc (pms, nimages, TY_POINTER)
+ do i = 1, nimages
+ Memi[pms+i-1] = pm_newmask (out, 1)
+ }
+ do i = 1, nimages {
+ pm = Memi[pms+i-1]
+ v[2] = line - l
+ if (v[2] > 0)
+ call pmplpi (pm, v, buf[1,i], 1, npts, rop)
+ v[2] = line + l
+ if (v[2] <= nl)
+ call pmplpi (pm, v, buf[1,i], 1, npts, rop)
+ }
+ }
+ v[2] = line
+end
+
+
+
+# IC_GROW$T -- Reject pixels.
+
+procedure ic_grows (v, d, m, n, buf, nimages, npts, pms)
+
+long v[ARB] # Output vector
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[ARB] # Number of good pixels
+int buf[ARB] # Buffer of npts
+int nimages # Number of images
+int npts # Number of output points per line
+pointer pms # Pointer to array of pixel masks
+
+int i, j, k
+pointer pm
+bool pl_linenotempty()
+
+include "../icombine.com"
+
+begin
+ do k = 1, nimages {
+ pm = Memi[pms+k-1]
+ if (!pl_linenotempty (pm, v))
+ next
+ call pmglpi (pm, v, buf, 1, npts, PIX_SRC)
+ do i = 1, npts {
+ if (buf[i] == 0)
+ next
+ for (j = 1; j <= n[i]; j = j + 1) {
+ if (Memi[m[j]+i-1] == k) {
+ if (j < n[i]) {
+ Mems[d[j]+i-1] = Mems[d[n[i]]+i-1]
+ Memi[m[j]+i-1] = Memi[m[n[i]]+i-1]
+ }
+ n[i] = n[i] - 1
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+ }
+end
+
+# IC_GROW$T -- Reject pixels.
+
+procedure ic_growi (v, d, m, n, buf, nimages, npts, pms)
+
+long v[ARB] # Output vector
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[ARB] # Number of good pixels
+int buf[ARB] # Buffer of npts
+int nimages # Number of images
+int npts # Number of output points per line
+pointer pms # Pointer to array of pixel masks
+
+int i, j, k
+pointer pm
+bool pl_linenotempty()
+
+include "../icombine.com"
+
+begin
+ do k = 1, nimages {
+ pm = Memi[pms+k-1]
+ if (!pl_linenotempty (pm, v))
+ next
+ call pmglpi (pm, v, buf, 1, npts, PIX_SRC)
+ do i = 1, npts {
+ if (buf[i] == 0)
+ next
+ for (j = 1; j <= n[i]; j = j + 1) {
+ if (Memi[m[j]+i-1] == k) {
+ if (j < n[i]) {
+ Memi[d[j]+i-1] = Memi[d[n[i]]+i-1]
+ Memi[m[j]+i-1] = Memi[m[n[i]]+i-1]
+ }
+ n[i] = n[i] - 1
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+ }
+end
+
+# IC_GROW$T -- Reject pixels.
+
+procedure ic_growr (v, d, m, n, buf, nimages, npts, pms)
+
+long v[ARB] # Output vector
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[ARB] # Number of good pixels
+int buf[ARB] # Buffer of npts
+int nimages # Number of images
+int npts # Number of output points per line
+pointer pms # Pointer to array of pixel masks
+
+int i, j, k
+pointer pm
+bool pl_linenotempty()
+
+include "../icombine.com"
+
+begin
+ do k = 1, nimages {
+ pm = Memi[pms+k-1]
+ if (!pl_linenotempty (pm, v))
+ next
+ call pmglpi (pm, v, buf, 1, npts, PIX_SRC)
+ do i = 1, npts {
+ if (buf[i] == 0)
+ next
+ for (j = 1; j <= n[i]; j = j + 1) {
+ if (Memi[m[j]+i-1] == k) {
+ if (j < n[i]) {
+ Memr[d[j]+i-1] = Memr[d[n[i]]+i-1]
+ Memi[m[j]+i-1] = Memi[m[n[i]]+i-1]
+ }
+ n[i] = n[i] - 1
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+ }
+end
+
+# IC_GROW$T -- Reject pixels.
+
+procedure ic_growd (v, d, m, n, buf, nimages, npts, pms)
+
+long v[ARB] # Output vector
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[ARB] # Number of good pixels
+int buf[ARB] # Buffer of npts
+int nimages # Number of images
+int npts # Number of output points per line
+pointer pms # Pointer to array of pixel masks
+
+int i, j, k
+pointer pm
+bool pl_linenotempty()
+
+include "../icombine.com"
+
+begin
+ do k = 1, nimages {
+ pm = Memi[pms+k-1]
+ if (!pl_linenotempty (pm, v))
+ next
+ call pmglpi (pm, v, buf, 1, npts, PIX_SRC)
+ do i = 1, npts {
+ if (buf[i] == 0)
+ next
+ for (j = 1; j <= n[i]; j = j + 1) {
+ if (Memi[m[j]+i-1] == k) {
+ if (j < n[i]) {
+ Memd[d[j]+i-1] = Memd[d[n[i]]+i-1]
+ Memi[m[j]+i-1] = Memi[m[n[i]]+i-1]
+ }
+ n[i] = n[i] - 1
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+ }
+end
diff --git a/pkg/obsolete/imcombine/generic/icmedian.x b/pkg/obsolete/imcombine/generic/icmedian.x
new file mode 100644
index 00000000..80f36443
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icmedian.x
@@ -0,0 +1,556 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+
+# IC_MEDIAN -- Median of lines
+
+procedure ic_medians (d, n, npts, doblank, median)
+
+pointer d[ARB] # Input data line pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+int doblank # Set blank values?
+real median[npts] # Median
+
+int i, j1, j2, j3, k, n1
+bool even
+real val1, val2, val3
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # Check for previous sorting
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ even = (mod (n1, 2) == 0)
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ do i = 1, npts {
+ k = i - 1
+ if (even) {
+ val1 = Mems[d[j1]+k]
+ val2 = Mems[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Mems[d[j1]+k]
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod (n1, 2) == 0) {
+ j2 = n1 / 2
+ val1 = Mems[d[j1]+k]
+ val2 = Mems[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Mems[d[j1]+k]
+ } else if (doblank == YES)
+ median[i] = blank
+ }
+ }
+ return
+ }
+
+ # Repeatedly exchange the extreme values until there are three
+ # or fewer pixels.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ while (n1 > 3) {
+ j1 = 1
+ j2 = 1
+ val1 = Mems[d[j1]+k]
+ val2 = val1
+ do j3 = 2, n1 {
+ val3 = Mems[d[j3]+k]
+ if (val3 > val1) {
+ j1 = j3
+ val1 = val3
+ } else if (val3 < val2) {
+ j2 = j3
+ val2 = val3
+ }
+ }
+ j3 = n1 - 1
+ if (j1 < j3 && j2 < j3) {
+ Mems[d[j1]+k] = val3
+ Mems[d[j2]+k] = Mems[d[j3]+k]
+ Mems[d[j3]+k] = val1
+ Mems[d[n1]+k] = val2
+ } else if (j1 < j3) {
+ if (j2 == j3) {
+ Mems[d[j1]+k] = val3
+ Mems[d[n1]+k] = val1
+ } else {
+ Mems[d[j1]+k] = Mems[d[j3]+k]
+ Mems[d[j3]+k] = val1
+ }
+ } else if (j2 < j3) {
+ if (j1 == j3) {
+ Mems[d[j2]+k] = val3
+ Mems[d[n1]+k] = val2
+ } else {
+ Mems[d[j2]+k] = Mems[d[j3]+k]
+ Mems[d[j3]+k] = val2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ if (n1 == 3) {
+ val1 = Mems[d[1]+k]
+ val2 = Mems[d[2]+k]
+ val3 = Mems[d[3]+k]
+ if (val1 < val2) {
+ if (val2 < val3) # abc
+ median[i] = val2
+ else if (val1 < val3) # acb
+ median[i] = val3
+ else # cab
+ median[i] = val1
+ } else {
+ if (val2 > val3) # cba
+ median[i] = val2
+ else if (val1 > val3) # bca
+ median[i] = val3
+ else # bac
+ median[i] = val1
+ }
+ } else if (n1 == 2) {
+ val1 = Mems[d[1]+k]
+ val2 = Mems[d[2]+k]
+ median[i] = (val1 + val2) / 2
+ } else if (n1 == 1)
+ median[i] = Mems[d[1]+k]
+ else if (doblank == YES)
+ median[i] = blank
+ }
+end
+
+# IC_MEDIAN -- Median of lines
+
+procedure ic_mediani (d, n, npts, doblank, median)
+
+pointer d[ARB] # Input data line pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+int doblank # Set blank values?
+real median[npts] # Median
+
+int i, j1, j2, j3, k, n1
+bool even
+real val1, val2, val3
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # Check for previous sorting
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ even = (mod (n1, 2) == 0)
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ do i = 1, npts {
+ k = i - 1
+ if (even) {
+ val1 = Memi[d[j1]+k]
+ val2 = Memi[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Memi[d[j1]+k]
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod (n1, 2) == 0) {
+ j2 = n1 / 2
+ val1 = Memi[d[j1]+k]
+ val2 = Memi[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Memi[d[j1]+k]
+ } else if (doblank == YES)
+ median[i] = blank
+ }
+ }
+ return
+ }
+
+ # Repeatedly exchange the extreme values until there are three
+ # or fewer pixels.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ while (n1 > 3) {
+ j1 = 1
+ j2 = 1
+ val1 = Memi[d[j1]+k]
+ val2 = val1
+ do j3 = 2, n1 {
+ val3 = Memi[d[j3]+k]
+ if (val3 > val1) {
+ j1 = j3
+ val1 = val3
+ } else if (val3 < val2) {
+ j2 = j3
+ val2 = val3
+ }
+ }
+ j3 = n1 - 1
+ if (j1 < j3 && j2 < j3) {
+ Memi[d[j1]+k] = val3
+ Memi[d[j2]+k] = Memi[d[j3]+k]
+ Memi[d[j3]+k] = val1
+ Memi[d[n1]+k] = val2
+ } else if (j1 < j3) {
+ if (j2 == j3) {
+ Memi[d[j1]+k] = val3
+ Memi[d[n1]+k] = val1
+ } else {
+ Memi[d[j1]+k] = Memi[d[j3]+k]
+ Memi[d[j3]+k] = val1
+ }
+ } else if (j2 < j3) {
+ if (j1 == j3) {
+ Memi[d[j2]+k] = val3
+ Memi[d[n1]+k] = val2
+ } else {
+ Memi[d[j2]+k] = Memi[d[j3]+k]
+ Memi[d[j3]+k] = val2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ if (n1 == 3) {
+ val1 = Memi[d[1]+k]
+ val2 = Memi[d[2]+k]
+ val3 = Memi[d[3]+k]
+ if (val1 < val2) {
+ if (val2 < val3) # abc
+ median[i] = val2
+ else if (val1 < val3) # acb
+ median[i] = val3
+ else # cab
+ median[i] = val1
+ } else {
+ if (val2 > val3) # cba
+ median[i] = val2
+ else if (val1 > val3) # bca
+ median[i] = val3
+ else # bac
+ median[i] = val1
+ }
+ } else if (n1 == 2) {
+ val1 = Memi[d[1]+k]
+ val2 = Memi[d[2]+k]
+ median[i] = (val1 + val2) / 2
+ } else if (n1 == 1)
+ median[i] = Memi[d[1]+k]
+ else if (doblank == YES)
+ median[i] = blank
+ }
+end
+
+# IC_MEDIAN -- Median of lines
+
+procedure ic_medianr (d, n, npts, doblank, median)
+
+pointer d[ARB] # Input data line pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+int doblank # Set blank values?
+real median[npts] # Median
+
+int i, j1, j2, j3, k, n1
+bool even
+real val1, val2, val3
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # Check for previous sorting
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ even = (mod (n1, 2) == 0)
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ do i = 1, npts {
+ k = i - 1
+ if (even) {
+ val1 = Memr[d[j1]+k]
+ val2 = Memr[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Memr[d[j1]+k]
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod (n1, 2) == 0) {
+ j2 = n1 / 2
+ val1 = Memr[d[j1]+k]
+ val2 = Memr[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Memr[d[j1]+k]
+ } else if (doblank == YES)
+ median[i] = blank
+ }
+ }
+ return
+ }
+
+ # Repeatedly exchange the extreme values until there are three
+ # or fewer pixels.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ while (n1 > 3) {
+ j1 = 1
+ j2 = 1
+ val1 = Memr[d[j1]+k]
+ val2 = val1
+ do j3 = 2, n1 {
+ val3 = Memr[d[j3]+k]
+ if (val3 > val1) {
+ j1 = j3
+ val1 = val3
+ } else if (val3 < val2) {
+ j2 = j3
+ val2 = val3
+ }
+ }
+ j3 = n1 - 1
+ if (j1 < j3 && j2 < j3) {
+ Memr[d[j1]+k] = val3
+ Memr[d[j2]+k] = Memr[d[j3]+k]
+ Memr[d[j3]+k] = val1
+ Memr[d[n1]+k] = val2
+ } else if (j1 < j3) {
+ if (j2 == j3) {
+ Memr[d[j1]+k] = val3
+ Memr[d[n1]+k] = val1
+ } else {
+ Memr[d[j1]+k] = Memr[d[j3]+k]
+ Memr[d[j3]+k] = val1
+ }
+ } else if (j2 < j3) {
+ if (j1 == j3) {
+ Memr[d[j2]+k] = val3
+ Memr[d[n1]+k] = val2
+ } else {
+ Memr[d[j2]+k] = Memr[d[j3]+k]
+ Memr[d[j3]+k] = val2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ if (n1 == 3) {
+ val1 = Memr[d[1]+k]
+ val2 = Memr[d[2]+k]
+ val3 = Memr[d[3]+k]
+ if (val1 < val2) {
+ if (val2 < val3) # abc
+ median[i] = val2
+ else if (val1 < val3) # acb
+ median[i] = val3
+ else # cab
+ median[i] = val1
+ } else {
+ if (val2 > val3) # cba
+ median[i] = val2
+ else if (val1 > val3) # bca
+ median[i] = val3
+ else # bac
+ median[i] = val1
+ }
+ } else if (n1 == 2) {
+ val1 = Memr[d[1]+k]
+ val2 = Memr[d[2]+k]
+ median[i] = (val1 + val2) / 2
+ } else if (n1 == 1)
+ median[i] = Memr[d[1]+k]
+ else if (doblank == YES)
+ median[i] = blank
+ }
+end
+
+# IC_MEDIAN -- Median of lines
+
+procedure ic_mediand (d, n, npts, doblank, median)
+
+pointer d[ARB] # Input data line pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+int doblank # Set blank values?
+double median[npts] # Median
+
+int i, j1, j2, j3, k, n1
+bool even
+double val1, val2, val3
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # Check for previous sorting
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ even = (mod (n1, 2) == 0)
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ do i = 1, npts {
+ k = i - 1
+ if (even) {
+ val1 = Memd[d[j1]+k]
+ val2 = Memd[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Memd[d[j1]+k]
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod (n1, 2) == 0) {
+ j2 = n1 / 2
+ val1 = Memd[d[j1]+k]
+ val2 = Memd[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Memd[d[j1]+k]
+ } else if (doblank == YES)
+ median[i] = blank
+ }
+ }
+ return
+ }
+
+ # Repeatedly exchange the extreme values until there are three
+ # or fewer pixels.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ while (n1 > 3) {
+ j1 = 1
+ j2 = 1
+ val1 = Memd[d[j1]+k]
+ val2 = val1
+ do j3 = 2, n1 {
+ val3 = Memd[d[j3]+k]
+ if (val3 > val1) {
+ j1 = j3
+ val1 = val3
+ } else if (val3 < val2) {
+ j2 = j3
+ val2 = val3
+ }
+ }
+ j3 = n1 - 1
+ if (j1 < j3 && j2 < j3) {
+ Memd[d[j1]+k] = val3
+ Memd[d[j2]+k] = Memd[d[j3]+k]
+ Memd[d[j3]+k] = val1
+ Memd[d[n1]+k] = val2
+ } else if (j1 < j3) {
+ if (j2 == j3) {
+ Memd[d[j1]+k] = val3
+ Memd[d[n1]+k] = val1
+ } else {
+ Memd[d[j1]+k] = Memd[d[j3]+k]
+ Memd[d[j3]+k] = val1
+ }
+ } else if (j2 < j3) {
+ if (j1 == j3) {
+ Memd[d[j2]+k] = val3
+ Memd[d[n1]+k] = val2
+ } else {
+ Memd[d[j2]+k] = Memd[d[j3]+k]
+ Memd[d[j3]+k] = val2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ if (n1 == 3) {
+ val1 = Memd[d[1]+k]
+ val2 = Memd[d[2]+k]
+ val3 = Memd[d[3]+k]
+ if (val1 < val2) {
+ if (val2 < val3) # abc
+ median[i] = val2
+ else if (val1 < val3) # acb
+ median[i] = val3
+ else # cab
+ median[i] = val1
+ } else {
+ if (val2 > val3) # cba
+ median[i] = val2
+ else if (val1 > val3) # bca
+ median[i] = val3
+ else # bac
+ median[i] = val1
+ }
+ } else if (n1 == 2) {
+ val1 = Memd[d[1]+k]
+ val2 = Memd[d[2]+k]
+ median[i] = (val1 + val2) / 2
+ } else if (n1 == 1)
+ median[i] = Memd[d[1]+k]
+ else if (doblank == YES)
+ median[i] = blank
+ }
+end
diff --git a/pkg/obsolete/imcombine/generic/icmm.x b/pkg/obsolete/imcombine/generic/icmm.x
new file mode 100644
index 00000000..fc1a9239
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icmm.x
@@ -0,0 +1,612 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+
+# IC_MM -- Reject a specified number of high and low pixels
+
+procedure ic_mms (d, m, n, npts)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+
+int n1, ncombine, npairs, nlow, nhigh, np
+int i, i1, j, jmax, jmin
+pointer k, kmax, kmin
+short d1, d2, dmin, dmax
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE)
+ return
+
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = n1 - nlow - nhigh
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ do i = 1, npts {
+ i1 = i - 1
+ n1 = n[i]
+ if (dflag == D_MIX) {
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = max (ncombine, n1 - nlow - nhigh)
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ # Reject the npairs low and high points.
+ do np = 1, npairs {
+ k = d[1] + i1
+ d1 = Mems[k]
+ dmax = d1; dmin = d1; jmax = 1; jmin = 1; kmax = k; kmin = k
+ do j = 2, n1 {
+ d2 = d1
+ k = d[j] + i1
+ d1 = Mems[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ } else if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ j = n1 - 1
+ if (keepids) {
+ if (jmax < j) {
+ if (jmin != j) {
+ Mems[kmax] = d2
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ } else {
+ Mems[kmax] = d1
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Mems[kmin] = d1
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ } else {
+ Mems[kmin] = d2
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ }
+ }
+ } else {
+ if (jmax < j) {
+ if (jmin != j)
+ Mems[kmax] = d2
+ else
+ Mems[kmax] = d1
+ }
+ if (jmin < j) {
+ if (jmax != n1)
+ Mems[kmin] = d1
+ else
+ Mems[kmin] = d2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ # Reject the excess low points.
+ do np = 1, nlow {
+ k = d[1] + i1
+ d1 = Mems[k]
+ dmin = d1; jmin = 1; kmin = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Mems[k]
+ if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ if (keepids) {
+ if (jmin < n1) {
+ Mems[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmin < n1)
+ Mems[kmin] = d1
+ }
+ n1 = n1 - 1
+ }
+
+ # Reject the excess high points.
+ do np = 1, nhigh {
+ k = d[1] + i1
+ d1 = Mems[k]
+ dmax = d1; jmax = 1; kmax = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Mems[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ }
+ }
+ if (keepids) {
+ if (jmax < n1) {
+ Mems[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmax < n1)
+ Mems[kmax] = d1
+ }
+ n1 = n1 - 1
+ }
+ n[i] = n1
+ }
+
+ if (dflag == D_ALL && npairs + nlow + nhigh > 0)
+ dflag = D_MIX
+end
+
+# IC_MM -- Reject a specified number of high and low pixels
+
+procedure ic_mmi (d, m, n, npts)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+
+int n1, ncombine, npairs, nlow, nhigh, np
+int i, i1, j, jmax, jmin
+pointer k, kmax, kmin
+int d1, d2, dmin, dmax
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE)
+ return
+
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = n1 - nlow - nhigh
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ do i = 1, npts {
+ i1 = i - 1
+ n1 = n[i]
+ if (dflag == D_MIX) {
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = max (ncombine, n1 - nlow - nhigh)
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ # Reject the npairs low and high points.
+ do np = 1, npairs {
+ k = d[1] + i1
+ d1 = Memi[k]
+ dmax = d1; dmin = d1; jmax = 1; jmin = 1; kmax = k; kmin = k
+ do j = 2, n1 {
+ d2 = d1
+ k = d[j] + i1
+ d1 = Memi[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ } else if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ j = n1 - 1
+ if (keepids) {
+ if (jmax < j) {
+ if (jmin != j) {
+ Memi[kmax] = d2
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ } else {
+ Memi[kmax] = d1
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Memi[kmin] = d1
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ } else {
+ Memi[kmin] = d2
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ }
+ }
+ } else {
+ if (jmax < j) {
+ if (jmin != j)
+ Memi[kmax] = d2
+ else
+ Memi[kmax] = d1
+ }
+ if (jmin < j) {
+ if (jmax != n1)
+ Memi[kmin] = d1
+ else
+ Memi[kmin] = d2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ # Reject the excess low points.
+ do np = 1, nlow {
+ k = d[1] + i1
+ d1 = Memi[k]
+ dmin = d1; jmin = 1; kmin = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Memi[k]
+ if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ if (keepids) {
+ if (jmin < n1) {
+ Memi[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmin < n1)
+ Memi[kmin] = d1
+ }
+ n1 = n1 - 1
+ }
+
+ # Reject the excess high points.
+ do np = 1, nhigh {
+ k = d[1] + i1
+ d1 = Memi[k]
+ dmax = d1; jmax = 1; kmax = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Memi[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ }
+ }
+ if (keepids) {
+ if (jmax < n1) {
+ Memi[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmax < n1)
+ Memi[kmax] = d1
+ }
+ n1 = n1 - 1
+ }
+ n[i] = n1
+ }
+
+ if (dflag == D_ALL && npairs + nlow + nhigh > 0)
+ dflag = D_MIX
+end
+
+# IC_MM -- Reject a specified number of high and low pixels
+
+procedure ic_mmr (d, m, n, npts)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+
+int n1, ncombine, npairs, nlow, nhigh, np
+int i, i1, j, jmax, jmin
+pointer k, kmax, kmin
+real d1, d2, dmin, dmax
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE)
+ return
+
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = n1 - nlow - nhigh
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ do i = 1, npts {
+ i1 = i - 1
+ n1 = n[i]
+ if (dflag == D_MIX) {
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = max (ncombine, n1 - nlow - nhigh)
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ # Reject the npairs low and high points.
+ do np = 1, npairs {
+ k = d[1] + i1
+ d1 = Memr[k]
+ dmax = d1; dmin = d1; jmax = 1; jmin = 1; kmax = k; kmin = k
+ do j = 2, n1 {
+ d2 = d1
+ k = d[j] + i1
+ d1 = Memr[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ } else if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ j = n1 - 1
+ if (keepids) {
+ if (jmax < j) {
+ if (jmin != j) {
+ Memr[kmax] = d2
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ } else {
+ Memr[kmax] = d1
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Memr[kmin] = d1
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ } else {
+ Memr[kmin] = d2
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ }
+ }
+ } else {
+ if (jmax < j) {
+ if (jmin != j)
+ Memr[kmax] = d2
+ else
+ Memr[kmax] = d1
+ }
+ if (jmin < j) {
+ if (jmax != n1)
+ Memr[kmin] = d1
+ else
+ Memr[kmin] = d2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ # Reject the excess low points.
+ do np = 1, nlow {
+ k = d[1] + i1
+ d1 = Memr[k]
+ dmin = d1; jmin = 1; kmin = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Memr[k]
+ if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ if (keepids) {
+ if (jmin < n1) {
+ Memr[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmin < n1)
+ Memr[kmin] = d1
+ }
+ n1 = n1 - 1
+ }
+
+ # Reject the excess high points.
+ do np = 1, nhigh {
+ k = d[1] + i1
+ d1 = Memr[k]
+ dmax = d1; jmax = 1; kmax = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Memr[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ }
+ }
+ if (keepids) {
+ if (jmax < n1) {
+ Memr[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmax < n1)
+ Memr[kmax] = d1
+ }
+ n1 = n1 - 1
+ }
+ n[i] = n1
+ }
+
+ if (dflag == D_ALL && npairs + nlow + nhigh > 0)
+ dflag = D_MIX
+end
+
+# IC_MM -- Reject a specified number of high and low pixels
+
+procedure ic_mmd (d, m, n, npts)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+
+int n1, ncombine, npairs, nlow, nhigh, np
+int i, i1, j, jmax, jmin
+pointer k, kmax, kmin
+double d1, d2, dmin, dmax
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE)
+ return
+
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = n1 - nlow - nhigh
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ do i = 1, npts {
+ i1 = i - 1
+ n1 = n[i]
+ if (dflag == D_MIX) {
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = max (ncombine, n1 - nlow - nhigh)
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ # Reject the npairs low and high points.
+ do np = 1, npairs {
+ k = d[1] + i1
+ d1 = Memd[k]
+ dmax = d1; dmin = d1; jmax = 1; jmin = 1; kmax = k; kmin = k
+ do j = 2, n1 {
+ d2 = d1
+ k = d[j] + i1
+ d1 = Memd[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ } else if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ j = n1 - 1
+ if (keepids) {
+ if (jmax < j) {
+ if (jmin != j) {
+ Memd[kmax] = d2
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ } else {
+ Memd[kmax] = d1
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Memd[kmin] = d1
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ } else {
+ Memd[kmin] = d2
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ }
+ }
+ } else {
+ if (jmax < j) {
+ if (jmin != j)
+ Memd[kmax] = d2
+ else
+ Memd[kmax] = d1
+ }
+ if (jmin < j) {
+ if (jmax != n1)
+ Memd[kmin] = d1
+ else
+ Memd[kmin] = d2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ # Reject the excess low points.
+ do np = 1, nlow {
+ k = d[1] + i1
+ d1 = Memd[k]
+ dmin = d1; jmin = 1; kmin = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Memd[k]
+ if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ if (keepids) {
+ if (jmin < n1) {
+ Memd[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmin < n1)
+ Memd[kmin] = d1
+ }
+ n1 = n1 - 1
+ }
+
+ # Reject the excess high points.
+ do np = 1, nhigh {
+ k = d[1] + i1
+ d1 = Memd[k]
+ dmax = d1; jmax = 1; kmax = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ d1 = Memd[k]
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ }
+ }
+ if (keepids) {
+ if (jmax < n1) {
+ Memd[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmax < n1)
+ Memd[kmax] = d1
+ }
+ n1 = n1 - 1
+ }
+ n[i] = n1
+ }
+
+ if (dflag == D_ALL && npairs + nlow + nhigh > 0)
+ dflag = D_MIX
+end
diff --git a/pkg/obsolete/imcombine/generic/icombine.x b/pkg/obsolete/imcombine/generic/icombine.x
new file mode 100644
index 00000000..50c76cca
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icombine.x
@@ -0,0 +1,1645 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <imset.h>
+include <pmset.h>
+include <error.h>
+include <syserr.h>
+include <mach.h>
+include "../icombine.h"
+
+
+# ICOMBINE -- Combine images
+#
+# The memory and open file descriptor limits are checked and an attempt
+# to recover is made either by setting the image pixel files to be
+# closed after I/O or by notifying the calling program that memory
+# ran out and the IMIO buffer size should be reduced. After the checks
+# a procedure for the selected combine option is called.
+# Because there may be several failure modes when reaching the file
+# limits we first assume an error is due to the file limit, except for
+# out of memory, and close some pixel files. If the error then repeats
+# on accessing the pixels the error is passed back.
+
+
+procedure icombines (in, out, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output images
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, npts, fd, stropen(), errcode(), imstati()
+pointer sp, d, id, n, m, lflag, scales, zeros, wts, dbuf
+pointer buf, imgl1s(), impl1i()
+errchk stropen, imgl1s, impl1i
+pointer impl1r()
+errchk impl1r
+
+include "../icombine.com"
+
+begin
+ npts = IM_LEN(out[1],1)
+
+ # Allocate memory.
+ call smark (sp)
+ call salloc (dbuf, nimages, TY_POINTER)
+ call salloc (d, nimages, TY_POINTER)
+ call salloc (id, nimages, TY_POINTER)
+ call salloc (n, npts, TY_INT)
+ call salloc (m, nimages, TY_POINTER)
+ call salloc (lflag, nimages, TY_INT)
+ call salloc (scales, nimages, TY_REAL)
+ call salloc (zeros, nimages, TY_REAL)
+ call salloc (wts, nimages, TY_REAL)
+ call amovki (D_ALL, Memi[lflag], nimages)
+
+ # If not aligned or growing create data buffers of output length
+ # otherwise use the IMIO buffers.
+
+ if (!aligned || grow >= 1.) {
+ do i = 1, nimages
+ call salloc (Memi[dbuf+i-1], npts, TY_SHORT)
+ } else
+ call amovki (NULL, Memi[dbuf], nimages)
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ } else {
+ # Reserve FD for string operations.
+ fd = stropen (str, 1, NEW_FILE)
+
+ # Do I/O to the images.
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ buf = impl1r (out[1])
+ call aclrr (Memr[buf], npts)
+ if (out[3] != NULL) {
+ buf = impl1r (out[3])
+ call aclrr (Memr[buf], npts)
+ }
+ if (out[2] != NULL) {
+ buf = impl1i (out[2])
+ call aclri (Memi[buf], npts)
+ }
+
+ do i = 1, nimages {
+ call imseti (in[i], IM_BUFSIZE, bufsize)
+ iferr (buf = imgl1s (in[i])) {
+ switch (errcode()) {
+ case SYS_MFULL:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ case SYS_FTOOMANYFILES, SYS_IKIOPIX:
+ if (imstati (in[i], IM_CLOSEFD) == YES) {
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ do j = i-2, nimages
+ call imseti (in[j], IM_CLOSEFD, YES)
+ buf = imgl1s (in[i])
+ default:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ }
+ }
+
+ call strclose (fd)
+ }
+
+ call ic_combines (in, out, Memi[dbuf], Memi[d], Memi[id], Memi[n],
+ Memi[m], Memi[lflag], offsets, Memr[scales], Memr[zeros],
+ Memr[wts], nimages, npts)
+end
+
+
+# IC_COMBINE -- Combine images.
+
+procedure ic_combines (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, wts, nimages, npts)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output image
+pointer dbuf[nimages] # Data buffers for nonaligned images
+pointer d[nimages] # Data pointers
+pointer id[nimages] # Image index ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Line flags
+int offsets[nimages,ARB] # Input image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+real wts[nimages] # Combining weights
+int nimages # Number of input images
+int npts # Number of points per output line
+
+int i, ext, ctor(), ic_qsort(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nm, pms
+pointer immap(), impnli()
+pointer impnlr(), imgnlr()
+errchk immap, ic_scale, imgetr, ic_grow, ic_grows, ic_rmasks
+extern ic_qsort
+
+include "../icombine.com"
+data ext/0/
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (v3, IM_MAXDIM, TY_LONG)
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+
+ call ic_scale (in, out, offsets, scales, zeros, wts, nimages)
+
+ # Set combine parameters
+ switch (combine) {
+ case AVERAGE:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Set rejection algorithm specific parameters
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ call salloc (nm, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nm+3*(i-1)+2] = r
+ }
+ }
+ if (!keepids) {
+ if (doscale1)
+ keepids = true
+ else {
+ do i = 2, nimages {
+ if (Memr[nm+3*(i-1)] != Memr[nm] ||
+ Memr[nm+3*(i-1)+1] != Memr[nm+1] ||
+ Memr[nm+3*(i-1)+2] != Memr[nm+2]) {
+ keepids = true
+ break
+ }
+ }
+ }
+ }
+ if (reject == CRREJECT)
+ lsigma = MAX_REAL
+ case MINMAX:
+ mclip = false
+ case PCLIP:
+ mclip = true
+ case AVSIGCLIP, SIGCLIP:
+ if (doscale1)
+ keepids = true
+ case NONE:
+ mclip = false
+ }
+
+ if (out[4] != NULL)
+ keepids = true
+
+ if (grow >= 1.) {
+ keepids = true
+ call salloc (work, npts * nimages, TY_INT)
+ }
+ pms = NULL
+
+ if (keepids) {
+ do i = 1, nimages
+ call salloc (id[i], npts, TY_INT)
+ }
+
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatas (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ if (mclip)
+ call ic_mccdclips (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ else
+ call ic_accdclips (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ case MINMAX:
+ call ic_mms (d, id, n, npts)
+ case PCLIP:
+ call ic_pclips (d, id, n, nimages, npts, Memr[outdata])
+ case SIGCLIP:
+ if (mclip)
+ call ic_msigclips (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ else
+ call ic_asigclips (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ case AVSIGCLIP:
+ if (mclip)
+ call ic_mavsigclips (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ else
+ call ic_aavsigclips (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ }
+
+ if (pms == NULL || nkeep > 0) {
+ if (docombine) {
+ switch (combine) {
+ case AVERAGE:
+ call ic_averages (d, id, n, wts, npts, YES,
+ Memr[outdata])
+ case MEDIAN:
+ call ic_medians (d, n, npts, YES, Memr[outdata])
+ }
+ }
+ }
+
+ if (grow >= 1.)
+ call ic_grow (out, Meml[v2], id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (pms == NULL) {
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigmas (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+ }
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ if (pms != NULL) {
+ if (nkeep > 0) {
+ call imstats (out[1], IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call imunmap (out[1])
+ iferr (buf = immap (Memc[fname], READ_WRITE, 0)) {
+ switch (errcode()) {
+ case SYS_FXFOPNOEXTNV:
+ call imgcluster (Memc[fname], Memc[fname], SZ_FNAME)
+ ext = ext + 1
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext)
+ iferr (buf = immap (Memc[imname], READ_WRITE, 0)) {
+ buf = NULL
+ ext = 0
+ }
+ repeat {
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext+1)
+ iferr (outdata = immap (Memc[imname],READ_WRITE,0))
+ break
+ if (buf != NULL)
+ call imunmap (buf)
+ buf = outdata
+ ext = ext + 1
+ }
+ default:
+ call erract (EA_ERROR)
+ }
+ }
+ out[1] = buf
+ }
+
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatas (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ call ic_grows (Meml[v2], d, id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (nkeep > 0) {
+ do i = 1, npts {
+ if (n[i] < nkeep) {
+ Meml[v1+1] = Meml[v1+1] - 1
+ if (imgnlr (out[1], buf, Meml[v1]) == EOF)
+ ;
+ call amovr (Memr[buf], Memr[outdata], npts)
+ break
+ }
+ }
+ }
+
+ switch (combine) {
+ case AVERAGE:
+ call ic_averages (d, id, n, wts, npts, NO, Memr[outdata])
+ case MEDIAN:
+ call ic_medians (d, n, npts, NO, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigmas (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ do i = 1, nimages
+ call pm_close (Memi[pms+i-1])
+ call mfree (pms, TY_POINTER)
+ }
+
+ call sfree (sp)
+end
+
+procedure icombinei (in, out, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output images
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, npts, fd, stropen(), errcode(), imstati()
+pointer sp, d, id, n, m, lflag, scales, zeros, wts, dbuf
+pointer buf, imgl1i(), impl1i()
+errchk stropen, imgl1i, impl1i
+pointer impl1r()
+errchk impl1r
+
+include "../icombine.com"
+
+begin
+ npts = IM_LEN(out[1],1)
+
+ # Allocate memory.
+ call smark (sp)
+ call salloc (dbuf, nimages, TY_POINTER)
+ call salloc (d, nimages, TY_POINTER)
+ call salloc (id, nimages, TY_POINTER)
+ call salloc (n, npts, TY_INT)
+ call salloc (m, nimages, TY_POINTER)
+ call salloc (lflag, nimages, TY_INT)
+ call salloc (scales, nimages, TY_REAL)
+ call salloc (zeros, nimages, TY_REAL)
+ call salloc (wts, nimages, TY_REAL)
+ call amovki (D_ALL, Memi[lflag], nimages)
+
+ # If not aligned or growing create data buffers of output length
+ # otherwise use the IMIO buffers.
+
+ if (!aligned || grow >= 1.) {
+ do i = 1, nimages
+ call salloc (Memi[dbuf+i-1], npts, TY_INT)
+ } else
+ call amovki (NULL, Memi[dbuf], nimages)
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ } else {
+ # Reserve FD for string operations.
+ fd = stropen (str, 1, NEW_FILE)
+
+ # Do I/O to the images.
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ buf = impl1r (out[1])
+ call aclrr (Memr[buf], npts)
+ if (out[3] != NULL) {
+ buf = impl1r (out[3])
+ call aclrr (Memr[buf], npts)
+ }
+ if (out[2] != NULL) {
+ buf = impl1i (out[2])
+ call aclri (Memi[buf], npts)
+ }
+
+ do i = 1, nimages {
+ call imseti (in[i], IM_BUFSIZE, bufsize)
+ iferr (buf = imgl1i (in[i])) {
+ switch (errcode()) {
+ case SYS_MFULL:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ case SYS_FTOOMANYFILES, SYS_IKIOPIX:
+ if (imstati (in[i], IM_CLOSEFD) == YES) {
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ do j = i-2, nimages
+ call imseti (in[j], IM_CLOSEFD, YES)
+ buf = imgl1i (in[i])
+ default:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ }
+ }
+
+ call strclose (fd)
+ }
+
+ call ic_combinei (in, out, Memi[dbuf], Memi[d], Memi[id], Memi[n],
+ Memi[m], Memi[lflag], offsets, Memr[scales], Memr[zeros],
+ Memr[wts], nimages, npts)
+end
+
+
+# IC_COMBINE -- Combine images.
+
+procedure ic_combinei (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, wts, nimages, npts)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output image
+pointer dbuf[nimages] # Data buffers for nonaligned images
+pointer d[nimages] # Data pointers
+pointer id[nimages] # Image index ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Line flags
+int offsets[nimages,ARB] # Input image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+real wts[nimages] # Combining weights
+int nimages # Number of input images
+int npts # Number of points per output line
+
+int i, ext, ctor(), ic_qsort(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nm, pms
+pointer immap(), impnli()
+pointer impnlr(), imgnlr()
+errchk immap, ic_scale, imgetr, ic_grow, ic_growi, ic_rmasks
+extern ic_qsort
+
+include "../icombine.com"
+data ext/0/
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (v3, IM_MAXDIM, TY_LONG)
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+
+ call ic_scale (in, out, offsets, scales, zeros, wts, nimages)
+
+ # Set combine parameters
+ switch (combine) {
+ case AVERAGE:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Set rejection algorithm specific parameters
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ call salloc (nm, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nm+3*(i-1)+2] = r
+ }
+ }
+ if (!keepids) {
+ if (doscale1)
+ keepids = true
+ else {
+ do i = 2, nimages {
+ if (Memr[nm+3*(i-1)] != Memr[nm] ||
+ Memr[nm+3*(i-1)+1] != Memr[nm+1] ||
+ Memr[nm+3*(i-1)+2] != Memr[nm+2]) {
+ keepids = true
+ break
+ }
+ }
+ }
+ }
+ if (reject == CRREJECT)
+ lsigma = MAX_REAL
+ case MINMAX:
+ mclip = false
+ case PCLIP:
+ mclip = true
+ case AVSIGCLIP, SIGCLIP:
+ if (doscale1)
+ keepids = true
+ case NONE:
+ mclip = false
+ }
+
+ if (out[4] != NULL)
+ keepids = true
+
+ if (grow >= 1.) {
+ keepids = true
+ call salloc (work, npts * nimages, TY_INT)
+ }
+ pms = NULL
+
+ if (keepids) {
+ do i = 1, nimages
+ call salloc (id[i], npts, TY_INT)
+ }
+
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatai (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ if (mclip)
+ call ic_mccdclipi (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ else
+ call ic_accdclipi (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ case MINMAX:
+ call ic_mmi (d, id, n, npts)
+ case PCLIP:
+ call ic_pclipi (d, id, n, nimages, npts, Memr[outdata])
+ case SIGCLIP:
+ if (mclip)
+ call ic_msigclipi (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ else
+ call ic_asigclipi (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ case AVSIGCLIP:
+ if (mclip)
+ call ic_mavsigclipi (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ else
+ call ic_aavsigclipi (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ }
+
+ if (pms == NULL || nkeep > 0) {
+ if (docombine) {
+ switch (combine) {
+ case AVERAGE:
+ call ic_averagei (d, id, n, wts, npts, YES,
+ Memr[outdata])
+ case MEDIAN:
+ call ic_mediani (d, n, npts, YES, Memr[outdata])
+ }
+ }
+ }
+
+ if (grow >= 1.)
+ call ic_grow (out, Meml[v2], id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (pms == NULL) {
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigmai (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+ }
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ if (pms != NULL) {
+ if (nkeep > 0) {
+ call imstats (out[1], IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call imunmap (out[1])
+ iferr (buf = immap (Memc[fname], READ_WRITE, 0)) {
+ switch (errcode()) {
+ case SYS_FXFOPNOEXTNV:
+ call imgcluster (Memc[fname], Memc[fname], SZ_FNAME)
+ ext = ext + 1
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext)
+ iferr (buf = immap (Memc[imname], READ_WRITE, 0)) {
+ buf = NULL
+ ext = 0
+ }
+ repeat {
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext+1)
+ iferr (outdata = immap (Memc[imname],READ_WRITE,0))
+ break
+ if (buf != NULL)
+ call imunmap (buf)
+ buf = outdata
+ ext = ext + 1
+ }
+ default:
+ call erract (EA_ERROR)
+ }
+ }
+ out[1] = buf
+ }
+
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatai (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ call ic_growi (Meml[v2], d, id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (nkeep > 0) {
+ do i = 1, npts {
+ if (n[i] < nkeep) {
+ Meml[v1+1] = Meml[v1+1] - 1
+ if (imgnlr (out[1], buf, Meml[v1]) == EOF)
+ ;
+ call amovr (Memr[buf], Memr[outdata], npts)
+ break
+ }
+ }
+ }
+
+ switch (combine) {
+ case AVERAGE:
+ call ic_averagei (d, id, n, wts, npts, NO, Memr[outdata])
+ case MEDIAN:
+ call ic_mediani (d, n, npts, NO, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigmai (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ do i = 1, nimages
+ call pm_close (Memi[pms+i-1])
+ call mfree (pms, TY_POINTER)
+ }
+
+ call sfree (sp)
+end
+
+procedure icombiner (in, out, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output images
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, npts, fd, stropen(), errcode(), imstati()
+pointer sp, d, id, n, m, lflag, scales, zeros, wts, dbuf
+pointer buf, imgl1r(), impl1i()
+errchk stropen, imgl1r, impl1i
+pointer impl1r()
+errchk impl1r
+
+include "../icombine.com"
+
+begin
+ npts = IM_LEN(out[1],1)
+
+ # Allocate memory.
+ call smark (sp)
+ call salloc (dbuf, nimages, TY_POINTER)
+ call salloc (d, nimages, TY_POINTER)
+ call salloc (id, nimages, TY_POINTER)
+ call salloc (n, npts, TY_INT)
+ call salloc (m, nimages, TY_POINTER)
+ call salloc (lflag, nimages, TY_INT)
+ call salloc (scales, nimages, TY_REAL)
+ call salloc (zeros, nimages, TY_REAL)
+ call salloc (wts, nimages, TY_REAL)
+ call amovki (D_ALL, Memi[lflag], nimages)
+
+ # If not aligned or growing create data buffers of output length
+ # otherwise use the IMIO buffers.
+
+ if (!aligned || grow >= 1.) {
+ do i = 1, nimages
+ call salloc (Memi[dbuf+i-1], npts, TY_REAL)
+ } else
+ call amovki (NULL, Memi[dbuf], nimages)
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ } else {
+ # Reserve FD for string operations.
+ fd = stropen (str, 1, NEW_FILE)
+
+ # Do I/O to the images.
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ buf = impl1r (out[1])
+ call aclrr (Memr[buf], npts)
+ if (out[3] != NULL) {
+ buf = impl1r (out[3])
+ call aclrr (Memr[buf], npts)
+ }
+ if (out[2] != NULL) {
+ buf = impl1i (out[2])
+ call aclri (Memi[buf], npts)
+ }
+
+ do i = 1, nimages {
+ call imseti (in[i], IM_BUFSIZE, bufsize)
+ iferr (buf = imgl1r (in[i])) {
+ switch (errcode()) {
+ case SYS_MFULL:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ case SYS_FTOOMANYFILES, SYS_IKIOPIX:
+ if (imstati (in[i], IM_CLOSEFD) == YES) {
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ do j = i-2, nimages
+ call imseti (in[j], IM_CLOSEFD, YES)
+ buf = imgl1r (in[i])
+ default:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ }
+ }
+
+ call strclose (fd)
+ }
+
+ call ic_combiner (in, out, Memi[dbuf], Memi[d], Memi[id], Memi[n],
+ Memi[m], Memi[lflag], offsets, Memr[scales], Memr[zeros],
+ Memr[wts], nimages, npts)
+end
+
+
+# IC_COMBINE -- Combine images.
+
+procedure ic_combiner (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, wts, nimages, npts)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output image
+pointer dbuf[nimages] # Data buffers for nonaligned images
+pointer d[nimages] # Data pointers
+pointer id[nimages] # Image index ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Line flags
+int offsets[nimages,ARB] # Input image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+real wts[nimages] # Combining weights
+int nimages # Number of input images
+int npts # Number of points per output line
+
+int i, ext, ctor(), ic_qsort(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nm, pms
+pointer immap(), impnli()
+pointer impnlr(), imgnlr
+errchk immap, ic_scale, imgetr, ic_grow, ic_growr, ic_rmasks
+extern ic_qsort
+
+include "../icombine.com"
+data ext/0/
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (v3, IM_MAXDIM, TY_LONG)
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+
+ call ic_scale (in, out, offsets, scales, zeros, wts, nimages)
+
+ # Set combine parameters
+ switch (combine) {
+ case AVERAGE:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Set rejection algorithm specific parameters
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ call salloc (nm, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nm+3*(i-1)+2] = r
+ }
+ }
+ if (!keepids) {
+ if (doscale1)
+ keepids = true
+ else {
+ do i = 2, nimages {
+ if (Memr[nm+3*(i-1)] != Memr[nm] ||
+ Memr[nm+3*(i-1)+1] != Memr[nm+1] ||
+ Memr[nm+3*(i-1)+2] != Memr[nm+2]) {
+ keepids = true
+ break
+ }
+ }
+ }
+ }
+ if (reject == CRREJECT)
+ lsigma = MAX_REAL
+ case MINMAX:
+ mclip = false
+ case PCLIP:
+ mclip = true
+ case AVSIGCLIP, SIGCLIP:
+ if (doscale1)
+ keepids = true
+ case NONE:
+ mclip = false
+ }
+
+ if (out[4] != NULL)
+ keepids = true
+
+ if (grow >= 1.) {
+ keepids = true
+ call salloc (work, npts * nimages, TY_INT)
+ }
+ pms = NULL
+
+ if (keepids) {
+ do i = 1, nimages
+ call salloc (id[i], npts, TY_INT)
+ }
+
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatar (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ if (mclip)
+ call ic_mccdclipr (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ else
+ call ic_accdclipr (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ case MINMAX:
+ call ic_mmr (d, id, n, npts)
+ case PCLIP:
+ call ic_pclipr (d, id, n, nimages, npts, Memr[outdata])
+ case SIGCLIP:
+ if (mclip)
+ call ic_msigclipr (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ else
+ call ic_asigclipr (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ case AVSIGCLIP:
+ if (mclip)
+ call ic_mavsigclipr (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ else
+ call ic_aavsigclipr (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ }
+
+ if (pms == NULL || nkeep > 0) {
+ if (docombine) {
+ switch (combine) {
+ case AVERAGE:
+ call ic_averager (d, id, n, wts, npts, YES,
+ Memr[outdata])
+ case MEDIAN:
+ call ic_medianr (d, n, npts, YES, Memr[outdata])
+ }
+ }
+ }
+
+ if (grow >= 1.)
+ call ic_grow (out, Meml[v2], id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (pms == NULL) {
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigmar (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+ }
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ if (pms != NULL) {
+ if (nkeep > 0) {
+ call imstats (out[1], IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call imunmap (out[1])
+ iferr (buf = immap (Memc[fname], READ_WRITE, 0)) {
+ switch (errcode()) {
+ case SYS_FXFOPNOEXTNV:
+ call imgcluster (Memc[fname], Memc[fname], SZ_FNAME)
+ ext = ext + 1
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext)
+ iferr (buf = immap (Memc[imname], READ_WRITE, 0)) {
+ buf = NULL
+ ext = 0
+ }
+ repeat {
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext+1)
+ iferr (outdata = immap (Memc[imname],READ_WRITE,0))
+ break
+ if (buf != NULL)
+ call imunmap (buf)
+ buf = outdata
+ ext = ext + 1
+ }
+ default:
+ call erract (EA_ERROR)
+ }
+ }
+ out[1] = buf
+ }
+
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatar (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ call ic_growr (Meml[v2], d, id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (nkeep > 0) {
+ do i = 1, npts {
+ if (n[i] < nkeep) {
+ Meml[v1+1] = Meml[v1+1] - 1
+ if (imgnlr (out[1], buf, Meml[v1]) == EOF)
+ ;
+ call amovr (Memr[buf], Memr[outdata], npts)
+ break
+ }
+ }
+ }
+
+ switch (combine) {
+ case AVERAGE:
+ call ic_averager (d, id, n, wts, npts, NO, Memr[outdata])
+ case MEDIAN:
+ call ic_medianr (d, n, npts, NO, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigmar (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ do i = 1, nimages
+ call pm_close (Memi[pms+i-1])
+ call mfree (pms, TY_POINTER)
+ }
+
+ call sfree (sp)
+end
+
+procedure icombined (in, out, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output images
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, npts, fd, stropen(), errcode(), imstati()
+pointer sp, d, id, n, m, lflag, scales, zeros, wts, dbuf
+pointer buf, imgl1d(), impl1i()
+errchk stropen, imgl1d, impl1i
+pointer impl1d()
+errchk impl1d
+
+include "../icombine.com"
+
+begin
+ npts = IM_LEN(out[1],1)
+
+ # Allocate memory.
+ call smark (sp)
+ call salloc (dbuf, nimages, TY_POINTER)
+ call salloc (d, nimages, TY_POINTER)
+ call salloc (id, nimages, TY_POINTER)
+ call salloc (n, npts, TY_INT)
+ call salloc (m, nimages, TY_POINTER)
+ call salloc (lflag, nimages, TY_INT)
+ call salloc (scales, nimages, TY_REAL)
+ call salloc (zeros, nimages, TY_REAL)
+ call salloc (wts, nimages, TY_REAL)
+ call amovki (D_ALL, Memi[lflag], nimages)
+
+ # If not aligned or growing create data buffers of output length
+ # otherwise use the IMIO buffers.
+
+ if (!aligned || grow >= 1.) {
+ do i = 1, nimages
+ call salloc (Memi[dbuf+i-1], npts, TY_DOUBLE)
+ } else
+ call amovki (NULL, Memi[dbuf], nimages)
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ } else {
+ # Reserve FD for string operations.
+ fd = stropen (str, 1, NEW_FILE)
+
+ # Do I/O to the images.
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ buf = impl1d (out[1])
+ call aclrd (Memd[buf], npts)
+ if (out[3] != NULL) {
+ buf = impl1d (out[3])
+ call aclrd (Memd[buf], npts)
+ }
+ if (out[2] != NULL) {
+ buf = impl1i (out[2])
+ call aclri (Memi[buf], npts)
+ }
+
+ do i = 1, nimages {
+ call imseti (in[i], IM_BUFSIZE, bufsize)
+ iferr (buf = imgl1d (in[i])) {
+ switch (errcode()) {
+ case SYS_MFULL:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ case SYS_FTOOMANYFILES, SYS_IKIOPIX:
+ if (imstati (in[i], IM_CLOSEFD) == YES) {
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ do j = i-2, nimages
+ call imseti (in[j], IM_CLOSEFD, YES)
+ buf = imgl1d (in[i])
+ default:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ }
+ }
+
+ call strclose (fd)
+ }
+
+ call ic_combined (in, out, Memi[dbuf], Memi[d], Memi[id], Memi[n],
+ Memi[m], Memi[lflag], offsets, Memr[scales], Memr[zeros],
+ Memr[wts], nimages, npts)
+end
+
+
+# IC_COMBINE -- Combine images.
+
+procedure ic_combined (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, wts, nimages, npts)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output image
+pointer dbuf[nimages] # Data buffers for nonaligned images
+pointer d[nimages] # Data pointers
+pointer id[nimages] # Image index ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Line flags
+int offsets[nimages,ARB] # Input image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+real wts[nimages] # Combining weights
+int nimages # Number of input images
+int npts # Number of points per output line
+
+int i, ext, ctor(), ic_qsort(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nm, pms
+pointer immap(), impnli()
+pointer impnld(), imgnld
+errchk immap, ic_scale, imgetr, ic_grow, ic_growd, ic_rmasks
+extern ic_qsort
+
+include "../icombine.com"
+data ext/0/
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (v3, IM_MAXDIM, TY_LONG)
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+
+ call ic_scale (in, out, offsets, scales, zeros, wts, nimages)
+
+ # Set combine parameters
+ switch (combine) {
+ case AVERAGE:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Set rejection algorithm specific parameters
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ call salloc (nm, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nm+3*(i-1)+2] = r
+ }
+ }
+ if (!keepids) {
+ if (doscale1)
+ keepids = true
+ else {
+ do i = 2, nimages {
+ if (Memr[nm+3*(i-1)] != Memr[nm] ||
+ Memr[nm+3*(i-1)+1] != Memr[nm+1] ||
+ Memr[nm+3*(i-1)+2] != Memr[nm+2]) {
+ keepids = true
+ break
+ }
+ }
+ }
+ }
+ if (reject == CRREJECT)
+ lsigma = MAX_REAL
+ case MINMAX:
+ mclip = false
+ case PCLIP:
+ mclip = true
+ case AVSIGCLIP, SIGCLIP:
+ if (doscale1)
+ keepids = true
+ case NONE:
+ mclip = false
+ }
+
+ if (out[4] != NULL)
+ keepids = true
+
+ if (grow >= 1.) {
+ keepids = true
+ call salloc (work, npts * nimages, TY_INT)
+ }
+ pms = NULL
+
+ if (keepids) {
+ do i = 1, nimages
+ call salloc (id[i], npts, TY_INT)
+ }
+
+ while (impnld (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatad (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ if (mclip)
+ call ic_mccdclipd (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memd[outdata])
+ else
+ call ic_accdclipd (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memd[outdata])
+ case MINMAX:
+ call ic_mmd (d, id, n, npts)
+ case PCLIP:
+ call ic_pclipd (d, id, n, nimages, npts, Memd[outdata])
+ case SIGCLIP:
+ if (mclip)
+ call ic_msigclipd (d, id, n, scales, zeros, nimages, npts,
+ Memd[outdata])
+ else
+ call ic_asigclipd (d, id, n, scales, zeros, nimages, npts,
+ Memd[outdata])
+ case AVSIGCLIP:
+ if (mclip)
+ call ic_mavsigclipd (d, id, n, scales, zeros, nimages,
+ npts, Memd[outdata])
+ else
+ call ic_aavsigclipd (d, id, n, scales, zeros, nimages,
+ npts, Memd[outdata])
+ }
+
+ if (pms == NULL || nkeep > 0) {
+ if (docombine) {
+ switch (combine) {
+ case AVERAGE:
+ call ic_averaged (d, id, n, wts, npts, YES,
+ Memd[outdata])
+ case MEDIAN:
+ call ic_mediand (d, n, npts, YES, Memd[outdata])
+ }
+ }
+ }
+
+ if (grow >= 1.)
+ call ic_grow (out, Meml[v2], id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (pms == NULL) {
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnld (out[3], buf, Meml[v1])
+ call ic_sigmad (d, id, n, wts, npts, Memd[outdata],
+ Memd[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+ }
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ if (pms != NULL) {
+ if (nkeep > 0) {
+ call imstats (out[1], IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call imunmap (out[1])
+ iferr (buf = immap (Memc[fname], READ_WRITE, 0)) {
+ switch (errcode()) {
+ case SYS_FXFOPNOEXTNV:
+ call imgcluster (Memc[fname], Memc[fname], SZ_FNAME)
+ ext = ext + 1
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext)
+ iferr (buf = immap (Memc[imname], READ_WRITE, 0)) {
+ buf = NULL
+ ext = 0
+ }
+ repeat {
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext+1)
+ iferr (outdata = immap (Memc[imname],READ_WRITE,0))
+ break
+ if (buf != NULL)
+ call imunmap (buf)
+ buf = outdata
+ ext = ext + 1
+ }
+ default:
+ call erract (EA_ERROR)
+ }
+ }
+ out[1] = buf
+ }
+
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+ while (impnld (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdatad (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ call ic_growd (Meml[v2], d, id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (nkeep > 0) {
+ do i = 1, npts {
+ if (n[i] < nkeep) {
+ Meml[v1+1] = Meml[v1+1] - 1
+ if (imgnld (out[1], buf, Meml[v1]) == EOF)
+ ;
+ call amovd (Memd[buf], Memd[outdata], npts)
+ break
+ }
+ }
+ }
+
+ switch (combine) {
+ case AVERAGE:
+ call ic_averaged (d, id, n, wts, npts, NO, Memd[outdata])
+ case MEDIAN:
+ call ic_mediand (d, n, npts, NO, Memd[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnld (out[3], buf, Meml[v1])
+ call ic_sigmad (d, id, n, wts, npts, Memd[outdata],
+ Memd[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+
+ do i = 1, nimages
+ call pm_close (Memi[pms+i-1])
+ call mfree (pms, TY_POINTER)
+ }
+
+ call sfree (sp)
+end
+
+
+
+# IC_QSORT -- Compare line numbers for GQSORT.
+
+int procedure ic_qsort (arg, i1, i2)
+
+pointer arg
+int i1, i2
+
+begin
+ if (Mems[arg+i1-1] < Mems[arg+i2-1])
+ return (-1)
+ else if (Mems[arg+i1-1] > Mems[arg+i2-1])
+ return (1)
+ else
+ return (0)
+end
diff --git a/pkg/obsolete/imcombine/generic/icpclip.x b/pkg/obsolete/imcombine/generic/icpclip.x
new file mode 100644
index 00000000..237d9686
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icpclip.x
@@ -0,0 +1,878 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 3 # Minimum number for clipping
+
+
+# IC_PCLIP -- Percentile clip
+#
+# 1) Find the median
+# 2) Find the pixel which is the specified order index away
+# 3) Use the data value difference as a sigma and apply clipping
+# 4) Since the median is known return it so it does not have to be recomputed
+
+procedure ic_pclips (d, m, n, nimages, npts, median)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[npts] # Number of good pixels
+int nimages # Number of input images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, n4, n5, nl, nh, nin, maxkeep
+bool even, fp_equalr()
+real sigma, r, s, t
+pointer sp, resid, mp1, mp2
+real med
+
+include "../icombine.com"
+
+begin
+ # There must be at least MINCLIP and more than nkeep pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Set sign of pclip parameter
+ if (pclip < 0)
+ t = -1.
+ else
+ t = 1.
+
+ # If there are no rejected pixels compute certain parameters once.
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0.) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ nin = n1
+ }
+
+ # Now apply clipping.
+ do i = 1, npts {
+ # Compute median.
+ if (dflag == D_MIX) {
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 == 0) {
+ if (combine == MEDIAN)
+ median[i] = blank
+ next
+ }
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ }
+
+ j = i - 1
+ if (even) {
+ med = Mems[d[n2-1]+j]
+ med = (med + Mems[d[n2]+j]) / 2.
+ } else
+ med = Mems[d[n2]+j]
+
+ if (n1 < max (MINCLIP, maxkeep+1)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Define sigma for clipping
+ sigma = t * (Mems[d[n3]+j] - med)
+ if (fp_equalr (sigma, 0.)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Reject pixels and save residuals.
+ # Check if any pixels are clipped.
+ # If so recompute the median and reset the number of good pixels.
+ # Only reorder if needed.
+
+ for (nl=1; nl<=n1; nl=nl+1) {
+ r = (med - Mems[d[nl]+j]) / sigma
+ if (r < lsigma)
+ break
+ Memr[resid+nl] = r
+ }
+ for (nh=n1; nh>=1; nh=nh-1) {
+ r = (Mems[d[nh]+j] - med) / sigma
+ if (r < hsigma)
+ break
+ Memr[resid+nh] = r
+ }
+ n4 = nh - nl + 1
+
+ # If too many pixels are rejected add some back in.
+ # All pixels with the same residual are added.
+ while (n4 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n4 = nh - nl + 1
+ }
+
+ # If any pixels are rejected recompute the median.
+ if (nl > 1 || nh < n1) {
+ n5 = nl + n4 / 2
+ if (mod (n4, 2) == 0) {
+ med = Mems[d[n5-1]+j]
+ med = (med + Mems[d[n5]+j]) / 2.
+ } else
+ med = Mems[d[n5]+j]
+ n[i] = n4
+ }
+ if (combine == MEDIAN)
+ median[i] = med
+
+ # Reorder if pixels only if necessary.
+ if (nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ k = max (nl, n4 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mems[d[l]+j] = Mems[d[k]+j]
+ if (grow >= 1.) {
+ mp1 = m[l] + j
+ mp2 = m[k] + j
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+j] = Memi[m[k]+j]
+ k = k + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mems[d[l]+j] = Mems[d[k]+j]
+ k = k + 1
+ }
+ }
+ }
+ }
+
+ # Check if data flag needs to be reset for rejected pixels.
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag whether the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_PCLIP -- Percentile clip
+#
+# 1) Find the median
+# 2) Find the pixel which is the specified order index away
+# 3) Use the data value difference as a sigma and apply clipping
+# 4) Since the median is known return it so it does not have to be recomputed
+
+procedure ic_pclipi (d, m, n, nimages, npts, median)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[npts] # Number of good pixels
+int nimages # Number of input images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, n4, n5, nl, nh, nin, maxkeep
+bool even, fp_equalr()
+real sigma, r, s, t
+pointer sp, resid, mp1, mp2
+real med
+
+include "../icombine.com"
+
+begin
+ # There must be at least MINCLIP and more than nkeep pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Set sign of pclip parameter
+ if (pclip < 0)
+ t = -1.
+ else
+ t = 1.
+
+ # If there are no rejected pixels compute certain parameters once.
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0.) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ nin = n1
+ }
+
+ # Now apply clipping.
+ do i = 1, npts {
+ # Compute median.
+ if (dflag == D_MIX) {
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 == 0) {
+ if (combine == MEDIAN)
+ median[i] = blank
+ next
+ }
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ }
+
+ j = i - 1
+ if (even) {
+ med = Memi[d[n2-1]+j]
+ med = (med + Memi[d[n2]+j]) / 2.
+ } else
+ med = Memi[d[n2]+j]
+
+ if (n1 < max (MINCLIP, maxkeep+1)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Define sigma for clipping
+ sigma = t * (Memi[d[n3]+j] - med)
+ if (fp_equalr (sigma, 0.)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Reject pixels and save residuals.
+ # Check if any pixels are clipped.
+ # If so recompute the median and reset the number of good pixels.
+ # Only reorder if needed.
+
+ for (nl=1; nl<=n1; nl=nl+1) {
+ r = (med - Memi[d[nl]+j]) / sigma
+ if (r < lsigma)
+ break
+ Memr[resid+nl] = r
+ }
+ for (nh=n1; nh>=1; nh=nh-1) {
+ r = (Memi[d[nh]+j] - med) / sigma
+ if (r < hsigma)
+ break
+ Memr[resid+nh] = r
+ }
+ n4 = nh - nl + 1
+
+ # If too many pixels are rejected add some back in.
+ # All pixels with the same residual are added.
+ while (n4 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n4 = nh - nl + 1
+ }
+
+ # If any pixels are rejected recompute the median.
+ if (nl > 1 || nh < n1) {
+ n5 = nl + n4 / 2
+ if (mod (n4, 2) == 0) {
+ med = Memi[d[n5-1]+j]
+ med = (med + Memi[d[n5]+j]) / 2.
+ } else
+ med = Memi[d[n5]+j]
+ n[i] = n4
+ }
+ if (combine == MEDIAN)
+ median[i] = med
+
+ # Reorder if pixels only if necessary.
+ if (nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ k = max (nl, n4 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memi[d[l]+j] = Memi[d[k]+j]
+ if (grow >= 1.) {
+ mp1 = m[l] + j
+ mp2 = m[k] + j
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+j] = Memi[m[k]+j]
+ k = k + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memi[d[l]+j] = Memi[d[k]+j]
+ k = k + 1
+ }
+ }
+ }
+ }
+
+ # Check if data flag needs to be reset for rejected pixels.
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag whether the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_PCLIP -- Percentile clip
+#
+# 1) Find the median
+# 2) Find the pixel which is the specified order index away
+# 3) Use the data value difference as a sigma and apply clipping
+# 4) Since the median is known return it so it does not have to be recomputed
+
+procedure ic_pclipr (d, m, n, nimages, npts, median)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[npts] # Number of good pixels
+int nimages # Number of input images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, n4, n5, nl, nh, nin, maxkeep
+bool even, fp_equalr()
+real sigma, r, s, t
+pointer sp, resid, mp1, mp2
+real med
+
+include "../icombine.com"
+
+begin
+ # There must be at least MINCLIP and more than nkeep pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Set sign of pclip parameter
+ if (pclip < 0)
+ t = -1.
+ else
+ t = 1.
+
+ # If there are no rejected pixels compute certain parameters once.
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0.) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ nin = n1
+ }
+
+ # Now apply clipping.
+ do i = 1, npts {
+ # Compute median.
+ if (dflag == D_MIX) {
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 == 0) {
+ if (combine == MEDIAN)
+ median[i] = blank
+ next
+ }
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ }
+
+ j = i - 1
+ if (even) {
+ med = Memr[d[n2-1]+j]
+ med = (med + Memr[d[n2]+j]) / 2.
+ } else
+ med = Memr[d[n2]+j]
+
+ if (n1 < max (MINCLIP, maxkeep+1)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Define sigma for clipping
+ sigma = t * (Memr[d[n3]+j] - med)
+ if (fp_equalr (sigma, 0.)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Reject pixels and save residuals.
+ # Check if any pixels are clipped.
+ # If so recompute the median and reset the number of good pixels.
+ # Only reorder if needed.
+
+ for (nl=1; nl<=n1; nl=nl+1) {
+ r = (med - Memr[d[nl]+j]) / sigma
+ if (r < lsigma)
+ break
+ Memr[resid+nl] = r
+ }
+ for (nh=n1; nh>=1; nh=nh-1) {
+ r = (Memr[d[nh]+j] - med) / sigma
+ if (r < hsigma)
+ break
+ Memr[resid+nh] = r
+ }
+ n4 = nh - nl + 1
+
+ # If too many pixels are rejected add some back in.
+ # All pixels with the same residual are added.
+ while (n4 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n4 = nh - nl + 1
+ }
+
+ # If any pixels are rejected recompute the median.
+ if (nl > 1 || nh < n1) {
+ n5 = nl + n4 / 2
+ if (mod (n4, 2) == 0) {
+ med = Memr[d[n5-1]+j]
+ med = (med + Memr[d[n5]+j]) / 2.
+ } else
+ med = Memr[d[n5]+j]
+ n[i] = n4
+ }
+ if (combine == MEDIAN)
+ median[i] = med
+
+ # Reorder if pixels only if necessary.
+ if (nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ k = max (nl, n4 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memr[d[l]+j] = Memr[d[k]+j]
+ if (grow >= 1.) {
+ mp1 = m[l] + j
+ mp2 = m[k] + j
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+j] = Memi[m[k]+j]
+ k = k + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memr[d[l]+j] = Memr[d[k]+j]
+ k = k + 1
+ }
+ }
+ }
+ }
+
+ # Check if data flag needs to be reset for rejected pixels.
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag whether the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_PCLIP -- Percentile clip
+#
+# 1) Find the median
+# 2) Find the pixel which is the specified order index away
+# 3) Use the data value difference as a sigma and apply clipping
+# 4) Since the median is known return it so it does not have to be recomputed
+
+procedure ic_pclipd (d, m, n, nimages, npts, median)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[npts] # Number of good pixels
+int nimages # Number of input images
+int npts # Number of output points per line
+double median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, n4, n5, nl, nh, nin, maxkeep
+bool even, fp_equalr()
+real sigma, r, s, t
+pointer sp, resid, mp1, mp2
+double med
+
+include "../icombine.com"
+
+begin
+ # There must be at least MINCLIP and more than nkeep pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Set sign of pclip parameter
+ if (pclip < 0)
+ t = -1.
+ else
+ t = 1.
+
+ # If there are no rejected pixels compute certain parameters once.
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0.) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ nin = n1
+ }
+
+ # Now apply clipping.
+ do i = 1, npts {
+ # Compute median.
+ if (dflag == D_MIX) {
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 == 0) {
+ if (combine == MEDIAN)
+ median[i] = blank
+ next
+ }
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ }
+
+ j = i - 1
+ if (even) {
+ med = Memd[d[n2-1]+j]
+ med = (med + Memd[d[n2]+j]) / 2.
+ } else
+ med = Memd[d[n2]+j]
+
+ if (n1 < max (MINCLIP, maxkeep+1)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Define sigma for clipping
+ sigma = t * (Memd[d[n3]+j] - med)
+ if (fp_equalr (sigma, 0.)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Reject pixels and save residuals.
+ # Check if any pixels are clipped.
+ # If so recompute the median and reset the number of good pixels.
+ # Only reorder if needed.
+
+ for (nl=1; nl<=n1; nl=nl+1) {
+ r = (med - Memd[d[nl]+j]) / sigma
+ if (r < lsigma)
+ break
+ Memr[resid+nl] = r
+ }
+ for (nh=n1; nh>=1; nh=nh-1) {
+ r = (Memd[d[nh]+j] - med) / sigma
+ if (r < hsigma)
+ break
+ Memr[resid+nh] = r
+ }
+ n4 = nh - nl + 1
+
+ # If too many pixels are rejected add some back in.
+ # All pixels with the same residual are added.
+ while (n4 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n4 = nh - nl + 1
+ }
+
+ # If any pixels are rejected recompute the median.
+ if (nl > 1 || nh < n1) {
+ n5 = nl + n4 / 2
+ if (mod (n4, 2) == 0) {
+ med = Memd[d[n5-1]+j]
+ med = (med + Memd[d[n5]+j]) / 2.
+ } else
+ med = Memd[d[n5]+j]
+ n[i] = n4
+ }
+ if (combine == MEDIAN)
+ median[i] = med
+
+ # Reorder if pixels only if necessary.
+ if (nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ k = max (nl, n4 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memd[d[l]+j] = Memd[d[k]+j]
+ if (grow >= 1.) {
+ mp1 = m[l] + j
+ mp2 = m[k] + j
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+j] = Memi[m[k]+j]
+ k = k + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memd[d[l]+j] = Memd[d[k]+j]
+ k = k + 1
+ }
+ }
+ }
+ }
+
+ # Check if data flag needs to be reset for rejected pixels.
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag whether the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/imcombine/generic/icsclip.x b/pkg/obsolete/imcombine/generic/icsclip.x
new file mode 100644
index 00000000..a0188d72
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icsclip.x
@@ -0,0 +1,1922 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 3 # Mininum number of images for algorithm
+
+
+# IC_ASIGCLIP -- Reject pixels using sigma clipping about the average
+# The initial average rejects the high and low pixels. A correction for
+# different scalings of the images may be made. Weights are not used.
+
+procedure ic_asigclips (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, r, one
+data one /1.0/
+pointer sp, resid, w, wp, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Flag whether returned average needs to be recomputed.
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Save the residuals and the sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Do sigma clipping.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+
+ # If there are not enough pixels simply compute the average.
+ if (n1 < max (3, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Mems[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mems[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ # Compute average with the high and low rejected.
+ low = Mems[d[1]+k]
+ high = Mems[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Mems[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Iteratively reject pixels and compute the final average if needed.
+ # Compact the data and keep track of the image IDs if needed.
+
+ repeat {
+ n2 = n1
+ if (doscale1) {
+ # Compute sigma corrected for scaling.
+ s = 0.
+ wp = w - 1
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Mems[dp1]
+ l = Memi[mp1]
+ r = sqrt (max (one, (a + zeros[l]) / scales[l]))
+ s = s + ((d1 - a) / r) ** 2
+ Memr[wp] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ wp = w - 1
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Mems[dp1]
+ r = (d1 - a) / (s * Memr[wp])
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ Memr[wp] = Memr[w+n1-1]
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } else {
+ # Compute the sigma without scale correction.
+ s = 0.
+ do j = 1, n1
+ s = s + (Mems[d[j]+k] - a) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Mems[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mems[dp1]
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Mems[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mems[dp1]
+ Mems[dp1] = Mems[dp2]
+ Mems[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Mems[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MSIGCLIP -- Reject pixels using sigma clipping about the median
+
+procedure ic_msigclips (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, w, mp1, mp2
+real med, one
+data one /1.0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Save the residuals and sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0)
+ med = (Mems[d[n3-1]+k] + Mems[d[n3]+k]) / 2.
+ else
+ med = Mems[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ # Compute the sigma with scaling correction.
+ s = 0.
+ do j = nl, nh {
+ l = Memi[m[j]+k]
+ r = sqrt (max (one, (med + zeros[l]) / scales[l]))
+ s = s + ((Mems[d[j]+k] - med) / r) ** 2
+ Memr[w+j-1] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Mems[d[nl]+k]) / (s * Memr[w+nl-1])
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Mems[d[nh]+k] - med) / (s * Memr[w+nh-1])
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ # Compute the sigma without scaling correction.
+ s = 0.
+ do j = nl, nh
+ s = s + (Mems[d[j]+k] - med) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Mems[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Mems[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mems[d[l]+k] = Mems[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mems[d[l]+k] = Mems[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_ASIGCLIP -- Reject pixels using sigma clipping about the average
+# The initial average rejects the high and low pixels. A correction for
+# different scalings of the images may be made. Weights are not used.
+
+procedure ic_asigclipi (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, r, one
+data one /1.0/
+pointer sp, resid, w, wp, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Flag whether returned average needs to be recomputed.
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Save the residuals and the sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Do sigma clipping.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+
+ # If there are not enough pixels simply compute the average.
+ if (n1 < max (3, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memi[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memi[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ # Compute average with the high and low rejected.
+ low = Memi[d[1]+k]
+ high = Memi[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memi[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Iteratively reject pixels and compute the final average if needed.
+ # Compact the data and keep track of the image IDs if needed.
+
+ repeat {
+ n2 = n1
+ if (doscale1) {
+ # Compute sigma corrected for scaling.
+ s = 0.
+ wp = w - 1
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Memi[dp1]
+ l = Memi[mp1]
+ r = sqrt (max (one, (a + zeros[l]) / scales[l]))
+ s = s + ((d1 - a) / r) ** 2
+ Memr[wp] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ wp = w - 1
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Memi[dp1]
+ r = (d1 - a) / (s * Memr[wp])
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ Memr[wp] = Memr[w+n1-1]
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } else {
+ # Compute the sigma without scale correction.
+ s = 0.
+ do j = 1, n1
+ s = s + (Memi[d[j]+k] - a) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Memi[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memi[dp1]
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memi[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memi[dp1]
+ Memi[dp1] = Memi[dp2]
+ Memi[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memi[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MSIGCLIP -- Reject pixels using sigma clipping about the median
+
+procedure ic_msigclipi (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, w, mp1, mp2
+real med, one
+data one /1.0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Save the residuals and sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0)
+ med = (Memi[d[n3-1]+k] + Memi[d[n3]+k]) / 2.
+ else
+ med = Memi[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ # Compute the sigma with scaling correction.
+ s = 0.
+ do j = nl, nh {
+ l = Memi[m[j]+k]
+ r = sqrt (max (one, (med + zeros[l]) / scales[l]))
+ s = s + ((Memi[d[j]+k] - med) / r) ** 2
+ Memr[w+j-1] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memi[d[nl]+k]) / (s * Memr[w+nl-1])
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memi[d[nh]+k] - med) / (s * Memr[w+nh-1])
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ # Compute the sigma without scaling correction.
+ s = 0.
+ do j = nl, nh
+ s = s + (Memi[d[j]+k] - med) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memi[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memi[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memi[d[l]+k] = Memi[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memi[d[l]+k] = Memi[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_ASIGCLIP -- Reject pixels using sigma clipping about the average
+# The initial average rejects the high and low pixels. A correction for
+# different scalings of the images may be made. Weights are not used.
+
+procedure ic_asigclipr (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+real d1, low, high, sum, a, s, r, one
+data one /1.0/
+pointer sp, resid, w, wp, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Flag whether returned average needs to be recomputed.
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Save the residuals and the sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Do sigma clipping.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+
+ # If there are not enough pixels simply compute the average.
+ if (n1 < max (3, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memr[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memr[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ # Compute average with the high and low rejected.
+ low = Memr[d[1]+k]
+ high = Memr[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memr[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Iteratively reject pixels and compute the final average if needed.
+ # Compact the data and keep track of the image IDs if needed.
+
+ repeat {
+ n2 = n1
+ if (doscale1) {
+ # Compute sigma corrected for scaling.
+ s = 0.
+ wp = w - 1
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Memr[dp1]
+ l = Memi[mp1]
+ r = sqrt (max (one, (a + zeros[l]) / scales[l]))
+ s = s + ((d1 - a) / r) ** 2
+ Memr[wp] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ wp = w - 1
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Memr[dp1]
+ r = (d1 - a) / (s * Memr[wp])
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ Memr[wp] = Memr[w+n1-1]
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } else {
+ # Compute the sigma without scale correction.
+ s = 0.
+ do j = 1, n1
+ s = s + (Memr[d[j]+k] - a) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Memr[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memr[dp1]
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memr[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memr[dp1]
+ Memr[dp1] = Memr[dp2]
+ Memr[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memr[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MSIGCLIP -- Reject pixels using sigma clipping about the median
+
+procedure ic_msigclipr (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+real median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, w, mp1, mp2
+real med, one
+data one /1.0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Save the residuals and sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0)
+ med = (Memr[d[n3-1]+k] + Memr[d[n3]+k]) / 2.
+ else
+ med = Memr[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ # Compute the sigma with scaling correction.
+ s = 0.
+ do j = nl, nh {
+ l = Memi[m[j]+k]
+ r = sqrt (max (one, (med + zeros[l]) / scales[l]))
+ s = s + ((Memr[d[j]+k] - med) / r) ** 2
+ Memr[w+j-1] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memr[d[nl]+k]) / (s * Memr[w+nl-1])
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memr[d[nh]+k] - med) / (s * Memr[w+nh-1])
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ # Compute the sigma without scaling correction.
+ s = 0.
+ do j = nl, nh
+ s = s + (Memr[d[j]+k] - med) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memr[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memr[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memr[d[l]+k] = Memr[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memr[d[l]+k] = Memr[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+
+# IC_ASIGCLIP -- Reject pixels using sigma clipping about the average
+# The initial average rejects the high and low pixels. A correction for
+# different scalings of the images may be made. Weights are not used.
+
+procedure ic_asigclipd (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+double average[npts] # Average
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+double d1, low, high, sum, a, s, r, one
+data one /1.0D0/
+pointer sp, resid, w, wp, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Flag whether returned average needs to be recomputed.
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Save the residuals and the sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Do sigma clipping.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+
+ # If there are not enough pixels simply compute the average.
+ if (n1 < max (3, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Memd[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memd[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ # Compute average with the high and low rejected.
+ low = Memd[d[1]+k]
+ high = Memd[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Memd[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Iteratively reject pixels and compute the final average if needed.
+ # Compact the data and keep track of the image IDs if needed.
+
+ repeat {
+ n2 = n1
+ if (doscale1) {
+ # Compute sigma corrected for scaling.
+ s = 0.
+ wp = w - 1
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Memd[dp1]
+ l = Memi[mp1]
+ r = sqrt (max (one, (a + zeros[l]) / scales[l]))
+ s = s + ((d1 - a) / r) ** 2
+ Memr[wp] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ wp = w - 1
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Memd[dp1]
+ r = (d1 - a) / (s * Memr[wp])
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ Memr[wp] = Memr[w+n1-1]
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } else {
+ # Compute the sigma without scale correction.
+ s = 0.
+ do j = 1, n1
+ s = s + (Memd[d[j]+k] - a) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Memd[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memd[dp1]
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Memd[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Memd[dp1]
+ Memd[dp1] = Memd[dp2]
+ Memd[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Memd[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MSIGCLIP -- Reject pixels using sigma clipping about the median
+
+procedure ic_msigclipd (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+double median[npts] # Median
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, w, mp1, mp2
+double med, one
+data one /1.0D0/
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Save the residuals and sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0)
+ med = (Memd[d[n3-1]+k] + Memd[d[n3]+k]) / 2.
+ else
+ med = Memd[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ # Compute the sigma with scaling correction.
+ s = 0.
+ do j = nl, nh {
+ l = Memi[m[j]+k]
+ r = sqrt (max (one, (med + zeros[l]) / scales[l]))
+ s = s + ((Memd[d[j]+k] - med) / r) ** 2
+ Memr[w+j-1] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memd[d[nl]+k]) / (s * Memr[w+nl-1])
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memd[d[nh]+k] - med) / (s * Memr[w+nh-1])
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ # Compute the sigma without scaling correction.
+ s = 0.
+ do j = nl, nh
+ s = s + (Memd[d[j]+k] - med) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Memd[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Memd[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Memd[d[l]+k] = Memd[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Memd[d[l]+k] = Memd[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/imcombine/generic/icsigma.x b/pkg/obsolete/imcombine/generic/icsigma.x
new file mode 100644
index 00000000..faf31602
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icsigma.x
@@ -0,0 +1,405 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+
+# IC_SIGMA -- Compute the sigma image line.
+# The estimated sigma includes a correction for the finite population.
+# Weights are used if desired.
+
+procedure ic_sigmas (d, m, n, wts, npts, average, sigma)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+real average[npts] # Average
+real sigma[npts] # Sigma line (returned)
+
+int i, j, k, n1
+real wt, sigcor, sumwt
+real a, sum
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (dowts) {
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Mems[d[1]+k] - a) ** 2 * wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Mems[d[j]+k] - a) ** 2 * wt
+ }
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ } else {
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ sum = (Mems[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Mems[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ do i = 1, npts
+ sigma[i] = blank
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 -1)
+ else
+ sigcor = 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Mems[d[1]+k] - a) ** 2 * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Mems[d[j]+k] - a) ** 2 * wt
+ sumwt = sumwt + wt
+ }
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ a = average[i]
+ sum = (Mems[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Mems[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ }
+ }
+end
+
+# IC_SIGMA -- Compute the sigma image line.
+# The estimated sigma includes a correction for the finite population.
+# Weights are used if desired.
+
+procedure ic_sigmai (d, m, n, wts, npts, average, sigma)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+real average[npts] # Average
+real sigma[npts] # Sigma line (returned)
+
+int i, j, k, n1
+real wt, sigcor, sumwt
+real a, sum
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (dowts) {
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Memi[d[1]+k] - a) ** 2 * wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Memi[d[j]+k] - a) ** 2 * wt
+ }
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ } else {
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ sum = (Memi[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memi[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ do i = 1, npts
+ sigma[i] = blank
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 -1)
+ else
+ sigcor = 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Memi[d[1]+k] - a) ** 2 * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Memi[d[j]+k] - a) ** 2 * wt
+ sumwt = sumwt + wt
+ }
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ a = average[i]
+ sum = (Memi[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memi[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ }
+ }
+end
+
+# IC_SIGMA -- Compute the sigma image line.
+# The estimated sigma includes a correction for the finite population.
+# Weights are used if desired.
+
+procedure ic_sigmar (d, m, n, wts, npts, average, sigma)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+real average[npts] # Average
+real sigma[npts] # Sigma line (returned)
+
+int i, j, k, n1
+real wt, sigcor, sumwt
+real a, sum
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (dowts) {
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Memr[d[1]+k] - a) ** 2 * wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Memr[d[j]+k] - a) ** 2 * wt
+ }
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ } else {
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ sum = (Memr[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memr[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ do i = 1, npts
+ sigma[i] = blank
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 -1)
+ else
+ sigcor = 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Memr[d[1]+k] - a) ** 2 * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Memr[d[j]+k] - a) ** 2 * wt
+ sumwt = sumwt + wt
+ }
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ a = average[i]
+ sum = (Memr[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memr[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ }
+ }
+end
+
+# IC_SIGMA -- Compute the sigma image line.
+# The estimated sigma includes a correction for the finite population.
+# Weights are used if desired.
+
+procedure ic_sigmad (d, m, n, wts, npts, average, sigma)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+double average[npts] # Average
+double sigma[npts] # Sigma line (returned)
+
+int i, j, k, n1
+real wt, sigcor, sumwt
+double a, sum
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (dowts) {
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Memd[d[1]+k] - a) ** 2 * wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Memd[d[j]+k] - a) ** 2 * wt
+ }
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ } else {
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ sum = (Memd[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memd[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ do i = 1, npts
+ sigma[i] = blank
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 -1)
+ else
+ sigcor = 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Memd[d[1]+k] - a) ** 2 * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Memd[d[j]+k] - a) ** 2 * wt
+ sumwt = sumwt + wt
+ }
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ a = average[i]
+ sum = (Memd[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memd[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ }
+ }
+end
diff --git a/pkg/obsolete/imcombine/generic/icsort.x b/pkg/obsolete/imcombine/generic/icsort.x
new file mode 100644
index 00000000..3ec1d27e
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icsort.x
@@ -0,0 +1,1096 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+define LOGPTR 32 # log2(maxpts) (4e9)
+
+
+# IC_SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially.
+
+procedure ic_sorts (a, b, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+short b[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+short pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR]
+define swap {temp=$1;$1=$2;$2=temp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix
+ b[i] = Mems[a[i]+l]
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) # bac
+ b[2] = pivot
+ else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) # acb
+ b[2] = temp3
+ else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ do i = 1, npix
+ b[i] = Mems[a[i]+l]
+
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix
+ Mems[a[i]+l] = b[i]
+ }
+end
+
+
+# IC_2SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially. A second integer set of
+# vectors is sorted.
+
+procedure ic_2sorts (a, b, c, d, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+short b[ARB] # work array
+pointer c[ARB] # pointer to associated integer vectors
+int d[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+short pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR], itemp
+define swap {temp=$1;$1=$2;$2=temp}
+define iswap {itemp=$1;$1=$2;$2=itemp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix {
+ b[i] = Mems[a[i]+l]
+ d[i] = Memi[c[i]+l]
+ }
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) { # bac
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ itemp = d[2]
+ d[2] = d[3]
+ d[3] = d[1]
+ d[1] = itemp
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ iswap (d[1], d[3])
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) { # acb
+ b[2] = temp3
+ iswap (d[2], d[3])
+ } else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ itemp = d[2]
+ d[2] = d[1]
+ d[1] = d[3]
+ d[3] = itemp
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k]); swap (d[j], d[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix {
+ Mems[a[i]+l] = b[i]
+ Memi[c[i]+l] = d[i]
+ }
+ }
+end
+
+# IC_SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially.
+
+procedure ic_sorti (a, b, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+int b[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+int pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR]
+define swap {temp=$1;$1=$2;$2=temp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix
+ b[i] = Memi[a[i]+l]
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) # bac
+ b[2] = pivot
+ else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) # acb
+ b[2] = temp3
+ else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ do i = 1, npix
+ b[i] = Memi[a[i]+l]
+
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix
+ Memi[a[i]+l] = b[i]
+ }
+end
+
+
+# IC_2SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially. A second integer set of
+# vectors is sorted.
+
+procedure ic_2sorti (a, b, c, d, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+int b[ARB] # work array
+pointer c[ARB] # pointer to associated integer vectors
+int d[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+int pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR], itemp
+define swap {temp=$1;$1=$2;$2=temp}
+define iswap {itemp=$1;$1=$2;$2=itemp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix {
+ b[i] = Memi[a[i]+l]
+ d[i] = Memi[c[i]+l]
+ }
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) { # bac
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ itemp = d[2]
+ d[2] = d[3]
+ d[3] = d[1]
+ d[1] = itemp
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ iswap (d[1], d[3])
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) { # acb
+ b[2] = temp3
+ iswap (d[2], d[3])
+ } else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ itemp = d[2]
+ d[2] = d[1]
+ d[1] = d[3]
+ d[3] = itemp
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k]); swap (d[j], d[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix {
+ Memi[a[i]+l] = b[i]
+ Memi[c[i]+l] = d[i]
+ }
+ }
+end
+
+# IC_SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially.
+
+procedure ic_sortr (a, b, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+real b[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+real pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR]
+define swap {temp=$1;$1=$2;$2=temp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix
+ b[i] = Memr[a[i]+l]
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) # bac
+ b[2] = pivot
+ else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) # acb
+ b[2] = temp3
+ else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ do i = 1, npix
+ b[i] = Memr[a[i]+l]
+
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix
+ Memr[a[i]+l] = b[i]
+ }
+end
+
+
+# IC_2SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially. A second integer set of
+# vectors is sorted.
+
+procedure ic_2sortr (a, b, c, d, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+real b[ARB] # work array
+pointer c[ARB] # pointer to associated integer vectors
+int d[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+real pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR], itemp
+define swap {temp=$1;$1=$2;$2=temp}
+define iswap {itemp=$1;$1=$2;$2=itemp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix {
+ b[i] = Memr[a[i]+l]
+ d[i] = Memi[c[i]+l]
+ }
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) { # bac
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ itemp = d[2]
+ d[2] = d[3]
+ d[3] = d[1]
+ d[1] = itemp
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ iswap (d[1], d[3])
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) { # acb
+ b[2] = temp3
+ iswap (d[2], d[3])
+ } else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ itemp = d[2]
+ d[2] = d[1]
+ d[1] = d[3]
+ d[3] = itemp
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k]); swap (d[j], d[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix {
+ Memr[a[i]+l] = b[i]
+ Memi[c[i]+l] = d[i]
+ }
+ }
+end
+
+# IC_SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially.
+
+procedure ic_sortd (a, b, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+double b[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+double pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR]
+define swap {temp=$1;$1=$2;$2=temp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix
+ b[i] = Memd[a[i]+l]
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) # bac
+ b[2] = pivot
+ else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) # acb
+ b[2] = temp3
+ else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ do i = 1, npix
+ b[i] = Memd[a[i]+l]
+
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix
+ Memd[a[i]+l] = b[i]
+ }
+end
+
+
+# IC_2SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially. A second integer set of
+# vectors is sorted.
+
+procedure ic_2sortd (a, b, c, d, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+double b[ARB] # work array
+pointer c[ARB] # pointer to associated integer vectors
+int d[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+double pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR], itemp
+define swap {temp=$1;$1=$2;$2=temp}
+define iswap {itemp=$1;$1=$2;$2=itemp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix {
+ b[i] = Memd[a[i]+l]
+ d[i] = Memi[c[i]+l]
+ }
+
+ # Special cases
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) { # bac
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ itemp = d[2]
+ d[2] = d[3]
+ d[3] = d[1]
+ d[1] = itemp
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ iswap (d[1], d[3])
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) { # acb
+ b[2] = temp3
+ iswap (d[2], d[3])
+ } else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ itemp = d[2]
+ d[2] = d[1]
+ d[1] = d[3]
+ d[3] = itemp
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+
+ # General case
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k]); swap (d[j], d[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ for (i=i+1; b[i] < pivot; i=i+1)
+ ;
+ for (j=j-1; j > i; j=j-1)
+ if (b[j] <= pivot)
+ break
+ if (i < j) { # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix {
+ Memd[a[i]+l] = b[i]
+ Memi[c[i]+l] = d[i]
+ }
+ }
+end
diff --git a/pkg/obsolete/imcombine/generic/icstat.x b/pkg/obsolete/imcombine/generic/icstat.x
new file mode 100644
index 00000000..433f1df5
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/icstat.x
@@ -0,0 +1,880 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+define NMAX 10000 # Maximum number of pixels to sample
+
+
+# IC_STAT -- Compute image statistics within specified section.
+# The image section is relative to a reference image which may be
+# different than the input image and may have an offset. Only a
+# subsample of pixels is used. Masked and thresholded pixels are
+# ignored. Only the desired statistics are computed to increase
+# efficiency.
+
+procedure ic_stats (im, imref, section, offsets, image, nimages,
+ domode, domedian, domean, mode, median, mean)
+
+pointer im # Data image
+pointer imref # Reference image for image section
+char section[ARB] # Image section
+int offsets[nimages,ARB] # Image section offset from data to reference
+int image # Image index (for mask I/O)
+int nimages # Number of images in offsets.
+bool domode, domedian, domean # Statistics to compute
+real mode, median, mean # Statistics
+
+int i, j, ndim, n, nv
+real a
+pointer sp, v1, v2, dv, va, vb
+pointer data, mask, dp, lp, mp, imgnls()
+short ic_modes()
+real asums()
+
+
+include "../icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (dv, IM_MAXDIM, TY_LONG)
+ call salloc (va, IM_MAXDIM, TY_LONG)
+ call salloc (vb, IM_MAXDIM, TY_LONG)
+
+ # Determine the image section parameters. This must be in terms of
+ # the data image pixel coordinates though the section may be specified
+ # in terms of the reference image coordinates. Limit the number of
+ # pixels in each dimension to a maximum.
+
+ ndim = IM_NDIM(im)
+ if (project)
+ ndim = ndim - 1
+ call amovki (1, Memi[v1], IM_MAXDIM)
+ call amovki (1, Memi[va], IM_MAXDIM)
+ call amovki (1, Memi[dv], IM_MAXDIM)
+ call amovi (IM_LEN(imref,1), Memi[vb], ndim)
+ call ic_section (section, Memi[va], Memi[vb], Memi[dv], ndim)
+ if (im != imref)
+ do i = 1, ndim {
+ Memi[va+i-1] = Memi[va+i-1] - offsets[image,i]
+ Memi[vb+i-1] = Memi[vb+i-1] - offsets[image,i]
+ }
+
+ do j = 1, 10 {
+ n = 1
+ do i = 0, ndim-1 {
+ Memi[v1+i] = max (1, min (Memi[va+i], Memi[vb+i]))
+ Memi[v2+i] = min (IM_LEN(im,i+1), max (Memi[va+i], Memi[vb+i]))
+ Memi[dv+i] = j
+ nv = max (1, (Memi[v2+i] - Memi[v1+i]) / Memi[dv+i] + 1)
+ Memi[v2+i] = Memi[v1+i] + (nv - 1) * Memi[dv+i]
+ n = n * nv
+ }
+ if (n < NMAX)
+ break
+ }
+
+ call amovl (Memi[v1], Memi[va], IM_MAXDIM)
+ Memi[va] = 1
+ if (project)
+ Memi[va+ndim] = image
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+
+ # Accumulate the pixel values within the section. Masked pixels and
+ # thresholded pixels are ignored.
+
+ call salloc (data, n, TY_SHORT)
+ dp = data
+ while (imgnls (im, lp, Memi[vb]) != EOF) {
+ call ic_mget1 (im, image, offsets[image,1], Memi[va], mask)
+ lp = lp + Memi[v1] - 1
+ if (dflag == D_ALL) {
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ a = Mems[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Mems[dp] = a
+ dp = dp + 1
+ }
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ Mems[dp] = Mems[lp]
+ dp = dp + 1
+ lp = lp + Memi[dv]
+ }
+ }
+ } else if (dflag == D_MIX) {
+ mp = mask + Memi[v1] - 1
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ a = Mems[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Mems[dp] = a
+ dp = dp + 1
+ }
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ Mems[dp] = Mems[lp]
+ dp = dp + 1
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ }
+ }
+ for (i=2; i<=ndim; i=i+1) {
+ Memi[va+i-1] = Memi[va+i-1] + Memi[dv+i-1]
+ if (Memi[va+i-1] <= Memi[v2+i-1])
+ break
+ Memi[va+i-1] = Memi[v1+i-1]
+ }
+ if (i > ndim)
+ break
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+ }
+
+ n = dp - data
+ if (n < 1) {
+ call sfree (sp)
+ call error (1, "Image section contains no pixels")
+ }
+
+ # Compute only statistics needed.
+ if (domode || domedian) {
+ call asrts (Mems[data], Mems[data], n)
+ mode = ic_modes (Mems[data], n)
+ median = Mems[data+n/2-1]
+ }
+ if (domean)
+ mean = asums (Mems[data], n) / n
+
+ call sfree (sp)
+end
+
+
+define NMIN 10 # Minimum number of pixels for mode calculation
+define ZRANGE 0.8 # Fraction of pixels about median to use
+define ZSTEP 0.01 # Step size for search for mode
+define ZBIN 0.1 # Bin size for mode.
+
+# IC_MODE -- Compute mode of an array. The mode is found by binning
+# with a bin size based on the data range over a fraction of the
+# pixels about the median and a bin step which may be smaller than the
+# bin size. If there are too few points the median is returned.
+# The input array must be sorted.
+
+short procedure ic_modes (a, n)
+
+short a[n] # Data array
+int n # Number of points
+
+int i, j, k, nmax
+real z1, z2, zstep, zbin
+short mode
+bool fp_equalr()
+
+begin
+ if (n < NMIN)
+ return (a[n/2])
+
+ # Compute the mode. The array must be sorted. Consider a
+ # range of values about the median point. Use a bin size which
+ # is ZBIN of the range. Step the bin limits in ZSTEP fraction of
+ # the bin size.
+
+ i = 1 + n * (1. - ZRANGE) / 2.
+ j = 1 + n * (1. + ZRANGE) / 2.
+ z1 = a[i]
+ z2 = a[j]
+ if (fp_equalr (z1, z2)) {
+ mode = z1
+ return (mode)
+ }
+
+ zstep = ZSTEP * (z2 - z1)
+ zbin = ZBIN * (z2 - z1)
+ zstep = max (1., zstep)
+ zbin = max (1., zbin)
+
+ z1 = z1 - zstep
+ k = i
+ nmax = 0
+ repeat {
+ z1 = z1 + zstep
+ z2 = z1 + zbin
+ for (; i < j && a[i] < z1; i=i+1)
+ ;
+ for (; k < j && a[k] < z2; k=k+1)
+ ;
+ if (k - i > nmax) {
+ nmax = k - i
+ mode = a[(i+k)/2]
+ }
+ } until (k >= j)
+
+ return (mode)
+end
+
+# IC_STAT -- Compute image statistics within specified section.
+# The image section is relative to a reference image which may be
+# different than the input image and may have an offset. Only a
+# subsample of pixels is used. Masked and thresholded pixels are
+# ignored. Only the desired statistics are computed to increase
+# efficiency.
+
+procedure ic_stati (im, imref, section, offsets, image, nimages,
+ domode, domedian, domean, mode, median, mean)
+
+pointer im # Data image
+pointer imref # Reference image for image section
+char section[ARB] # Image section
+int offsets[nimages,ARB] # Image section offset from data to reference
+int image # Image index (for mask I/O)
+int nimages # Number of images in offsets.
+bool domode, domedian, domean # Statistics to compute
+real mode, median, mean # Statistics
+
+int i, j, ndim, n, nv
+real a
+pointer sp, v1, v2, dv, va, vb
+pointer data, mask, dp, lp, mp, imgnli()
+int ic_modei()
+real asumi()
+
+
+include "../icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (dv, IM_MAXDIM, TY_LONG)
+ call salloc (va, IM_MAXDIM, TY_LONG)
+ call salloc (vb, IM_MAXDIM, TY_LONG)
+
+ # Determine the image section parameters. This must be in terms of
+ # the data image pixel coordinates though the section may be specified
+ # in terms of the reference image coordinates. Limit the number of
+ # pixels in each dimension to a maximum.
+
+ ndim = IM_NDIM(im)
+ if (project)
+ ndim = ndim - 1
+ call amovki (1, Memi[v1], IM_MAXDIM)
+ call amovki (1, Memi[va], IM_MAXDIM)
+ call amovki (1, Memi[dv], IM_MAXDIM)
+ call amovi (IM_LEN(imref,1), Memi[vb], ndim)
+ call ic_section (section, Memi[va], Memi[vb], Memi[dv], ndim)
+ if (im != imref)
+ do i = 1, ndim {
+ Memi[va+i-1] = Memi[va+i-1] - offsets[image,i]
+ Memi[vb+i-1] = Memi[vb+i-1] - offsets[image,i]
+ }
+
+ do j = 1, 10 {
+ n = 1
+ do i = 0, ndim-1 {
+ Memi[v1+i] = max (1, min (Memi[va+i], Memi[vb+i]))
+ Memi[v2+i] = min (IM_LEN(im,i+1), max (Memi[va+i], Memi[vb+i]))
+ Memi[dv+i] = j
+ nv = max (1, (Memi[v2+i] - Memi[v1+i]) / Memi[dv+i] + 1)
+ Memi[v2+i] = Memi[v1+i] + (nv - 1) * Memi[dv+i]
+ n = n * nv
+ }
+ if (n < NMAX)
+ break
+ }
+
+ call amovl (Memi[v1], Memi[va], IM_MAXDIM)
+ Memi[va] = 1
+ if (project)
+ Memi[va+ndim] = image
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+
+ # Accumulate the pixel values within the section. Masked pixels and
+ # thresholded pixels are ignored.
+
+ call salloc (data, n, TY_INT)
+ dp = data
+ while (imgnli (im, lp, Memi[vb]) != EOF) {
+ call ic_mget1 (im, image, offsets[image,1], Memi[va], mask)
+ lp = lp + Memi[v1] - 1
+ if (dflag == D_ALL) {
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ a = Memi[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Memi[dp] = a
+ dp = dp + 1
+ }
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ Memi[dp] = Memi[lp]
+ dp = dp + 1
+ lp = lp + Memi[dv]
+ }
+ }
+ } else if (dflag == D_MIX) {
+ mp = mask + Memi[v1] - 1
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ a = Memi[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Memi[dp] = a
+ dp = dp + 1
+ }
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ Memi[dp] = Memi[lp]
+ dp = dp + 1
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ }
+ }
+ for (i=2; i<=ndim; i=i+1) {
+ Memi[va+i-1] = Memi[va+i-1] + Memi[dv+i-1]
+ if (Memi[va+i-1] <= Memi[v2+i-1])
+ break
+ Memi[va+i-1] = Memi[v1+i-1]
+ }
+ if (i > ndim)
+ break
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+ }
+
+ n = dp - data
+ if (n < 1) {
+ call sfree (sp)
+ call error (1, "Image section contains no pixels")
+ }
+
+ # Compute only statistics needed.
+ if (domode || domedian) {
+ call asrti (Memi[data], Memi[data], n)
+ mode = ic_modei (Memi[data], n)
+ median = Memi[data+n/2-1]
+ }
+ if (domean)
+ mean = asumi (Memi[data], n) / n
+
+ call sfree (sp)
+end
+
+
+define NMIN 10 # Minimum number of pixels for mode calculation
+define ZRANGE 0.8 # Fraction of pixels about median to use
+define ZSTEP 0.01 # Step size for search for mode
+define ZBIN 0.1 # Bin size for mode.
+
+# IC_MODE -- Compute mode of an array. The mode is found by binning
+# with a bin size based on the data range over a fraction of the
+# pixels about the median and a bin step which may be smaller than the
+# bin size. If there are too few points the median is returned.
+# The input array must be sorted.
+
+int procedure ic_modei (a, n)
+
+int a[n] # Data array
+int n # Number of points
+
+int i, j, k, nmax
+real z1, z2, zstep, zbin
+int mode
+bool fp_equalr()
+
+begin
+ if (n < NMIN)
+ return (a[n/2])
+
+ # Compute the mode. The array must be sorted. Consider a
+ # range of values about the median point. Use a bin size which
+ # is ZBIN of the range. Step the bin limits in ZSTEP fraction of
+ # the bin size.
+
+ i = 1 + n * (1. - ZRANGE) / 2.
+ j = 1 + n * (1. + ZRANGE) / 2.
+ z1 = a[i]
+ z2 = a[j]
+ if (fp_equalr (z1, z2)) {
+ mode = z1
+ return (mode)
+ }
+
+ zstep = ZSTEP * (z2 - z1)
+ zbin = ZBIN * (z2 - z1)
+ zstep = max (1., zstep)
+ zbin = max (1., zbin)
+
+ z1 = z1 - zstep
+ k = i
+ nmax = 0
+ repeat {
+ z1 = z1 + zstep
+ z2 = z1 + zbin
+ for (; i < j && a[i] < z1; i=i+1)
+ ;
+ for (; k < j && a[k] < z2; k=k+1)
+ ;
+ if (k - i > nmax) {
+ nmax = k - i
+ mode = a[(i+k)/2]
+ }
+ } until (k >= j)
+
+ return (mode)
+end
+
+# IC_STAT -- Compute image statistics within specified section.
+# The image section is relative to a reference image which may be
+# different than the input image and may have an offset. Only a
+# subsample of pixels is used. Masked and thresholded pixels are
+# ignored. Only the desired statistics are computed to increase
+# efficiency.
+
+procedure ic_statr (im, imref, section, offsets, image, nimages,
+ domode, domedian, domean, mode, median, mean)
+
+pointer im # Data image
+pointer imref # Reference image for image section
+char section[ARB] # Image section
+int offsets[nimages,ARB] # Image section offset from data to reference
+int image # Image index (for mask I/O)
+int nimages # Number of images in offsets.
+bool domode, domedian, domean # Statistics to compute
+real mode, median, mean # Statistics
+
+int i, j, ndim, n, nv
+real a
+pointer sp, v1, v2, dv, va, vb
+pointer data, mask, dp, lp, mp, imgnlr()
+real ic_moder()
+real asumr()
+
+
+include "../icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (dv, IM_MAXDIM, TY_LONG)
+ call salloc (va, IM_MAXDIM, TY_LONG)
+ call salloc (vb, IM_MAXDIM, TY_LONG)
+
+ # Determine the image section parameters. This must be in terms of
+ # the data image pixel coordinates though the section may be specified
+ # in terms of the reference image coordinates. Limit the number of
+ # pixels in each dimension to a maximum.
+
+ ndim = IM_NDIM(im)
+ if (project)
+ ndim = ndim - 1
+ call amovki (1, Memi[v1], IM_MAXDIM)
+ call amovki (1, Memi[va], IM_MAXDIM)
+ call amovki (1, Memi[dv], IM_MAXDIM)
+ call amovi (IM_LEN(imref,1), Memi[vb], ndim)
+ call ic_section (section, Memi[va], Memi[vb], Memi[dv], ndim)
+ if (im != imref)
+ do i = 1, ndim {
+ Memi[va+i-1] = Memi[va+i-1] - offsets[image,i]
+ Memi[vb+i-1] = Memi[vb+i-1] - offsets[image,i]
+ }
+
+ do j = 1, 10 {
+ n = 1
+ do i = 0, ndim-1 {
+ Memi[v1+i] = max (1, min (Memi[va+i], Memi[vb+i]))
+ Memi[v2+i] = min (IM_LEN(im,i+1), max (Memi[va+i], Memi[vb+i]))
+ Memi[dv+i] = j
+ nv = max (1, (Memi[v2+i] - Memi[v1+i]) / Memi[dv+i] + 1)
+ Memi[v2+i] = Memi[v1+i] + (nv - 1) * Memi[dv+i]
+ n = n * nv
+ }
+ if (n < NMAX)
+ break
+ }
+
+ call amovl (Memi[v1], Memi[va], IM_MAXDIM)
+ Memi[va] = 1
+ if (project)
+ Memi[va+ndim] = image
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+
+ # Accumulate the pixel values within the section. Masked pixels and
+ # thresholded pixels are ignored.
+
+ call salloc (data, n, TY_REAL)
+ dp = data
+ while (imgnlr (im, lp, Memi[vb]) != EOF) {
+ call ic_mget1 (im, image, offsets[image,1], Memi[va], mask)
+ lp = lp + Memi[v1] - 1
+ if (dflag == D_ALL) {
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ a = Memr[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Memr[dp] = a
+ dp = dp + 1
+ }
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ Memr[dp] = Memr[lp]
+ dp = dp + 1
+ lp = lp + Memi[dv]
+ }
+ }
+ } else if (dflag == D_MIX) {
+ mp = mask + Memi[v1] - 1
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ a = Memr[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Memr[dp] = a
+ dp = dp + 1
+ }
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ Memr[dp] = Memr[lp]
+ dp = dp + 1
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ }
+ }
+ for (i=2; i<=ndim; i=i+1) {
+ Memi[va+i-1] = Memi[va+i-1] + Memi[dv+i-1]
+ if (Memi[va+i-1] <= Memi[v2+i-1])
+ break
+ Memi[va+i-1] = Memi[v1+i-1]
+ }
+ if (i > ndim)
+ break
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+ }
+
+ n = dp - data
+ if (n < 1) {
+ call sfree (sp)
+ call error (1, "Image section contains no pixels")
+ }
+
+ # Compute only statistics needed.
+ if (domode || domedian) {
+ call asrtr (Memr[data], Memr[data], n)
+ mode = ic_moder (Memr[data], n)
+ median = Memr[data+n/2-1]
+ }
+ if (domean)
+ mean = asumr (Memr[data], n) / n
+
+ call sfree (sp)
+end
+
+
+define NMIN 10 # Minimum number of pixels for mode calculation
+define ZRANGE 0.8 # Fraction of pixels about median to use
+define ZSTEP 0.01 # Step size for search for mode
+define ZBIN 0.1 # Bin size for mode.
+
+# IC_MODE -- Compute mode of an array. The mode is found by binning
+# with a bin size based on the data range over a fraction of the
+# pixels about the median and a bin step which may be smaller than the
+# bin size. If there are too few points the median is returned.
+# The input array must be sorted.
+
+real procedure ic_moder (a, n)
+
+real a[n] # Data array
+int n # Number of points
+
+int i, j, k, nmax
+real z1, z2, zstep, zbin
+real mode
+bool fp_equalr()
+
+begin
+ if (n < NMIN)
+ return (a[n/2])
+
+ # Compute the mode. The array must be sorted. Consider a
+ # range of values about the median point. Use a bin size which
+ # is ZBIN of the range. Step the bin limits in ZSTEP fraction of
+ # the bin size.
+
+ i = 1 + n * (1. - ZRANGE) / 2.
+ j = 1 + n * (1. + ZRANGE) / 2.
+ z1 = a[i]
+ z2 = a[j]
+ if (fp_equalr (z1, z2)) {
+ mode = z1
+ return (mode)
+ }
+
+ zstep = ZSTEP * (z2 - z1)
+ zbin = ZBIN * (z2 - z1)
+
+ z1 = z1 - zstep
+ k = i
+ nmax = 0
+ repeat {
+ z1 = z1 + zstep
+ z2 = z1 + zbin
+ for (; i < j && a[i] < z1; i=i+1)
+ ;
+ for (; k < j && a[k] < z2; k=k+1)
+ ;
+ if (k - i > nmax) {
+ nmax = k - i
+ mode = a[(i+k)/2]
+ }
+ } until (k >= j)
+
+ return (mode)
+end
+
+# IC_STAT -- Compute image statistics within specified section.
+# The image section is relative to a reference image which may be
+# different than the input image and may have an offset. Only a
+# subsample of pixels is used. Masked and thresholded pixels are
+# ignored. Only the desired statistics are computed to increase
+# efficiency.
+
+procedure ic_statd (im, imref, section, offsets, image, nimages,
+ domode, domedian, domean, mode, median, mean)
+
+pointer im # Data image
+pointer imref # Reference image for image section
+char section[ARB] # Image section
+int offsets[nimages,ARB] # Image section offset from data to reference
+int image # Image index (for mask I/O)
+int nimages # Number of images in offsets.
+bool domode, domedian, domean # Statistics to compute
+real mode, median, mean # Statistics
+
+int i, j, ndim, n, nv
+real a
+pointer sp, v1, v2, dv, va, vb
+pointer data, mask, dp, lp, mp, imgnld()
+double ic_moded()
+double asumd()
+
+
+include "../icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (dv, IM_MAXDIM, TY_LONG)
+ call salloc (va, IM_MAXDIM, TY_LONG)
+ call salloc (vb, IM_MAXDIM, TY_LONG)
+
+ # Determine the image section parameters. This must be in terms of
+ # the data image pixel coordinates though the section may be specified
+ # in terms of the reference image coordinates. Limit the number of
+ # pixels in each dimension to a maximum.
+
+ ndim = IM_NDIM(im)
+ if (project)
+ ndim = ndim - 1
+ call amovki (1, Memi[v1], IM_MAXDIM)
+ call amovki (1, Memi[va], IM_MAXDIM)
+ call amovki (1, Memi[dv], IM_MAXDIM)
+ call amovi (IM_LEN(imref,1), Memi[vb], ndim)
+ call ic_section (section, Memi[va], Memi[vb], Memi[dv], ndim)
+ if (im != imref)
+ do i = 1, ndim {
+ Memi[va+i-1] = Memi[va+i-1] - offsets[image,i]
+ Memi[vb+i-1] = Memi[vb+i-1] - offsets[image,i]
+ }
+
+ do j = 1, 10 {
+ n = 1
+ do i = 0, ndim-1 {
+ Memi[v1+i] = max (1, min (Memi[va+i], Memi[vb+i]))
+ Memi[v2+i] = min (IM_LEN(im,i+1), max (Memi[va+i], Memi[vb+i]))
+ Memi[dv+i] = j
+ nv = max (1, (Memi[v2+i] - Memi[v1+i]) / Memi[dv+i] + 1)
+ Memi[v2+i] = Memi[v1+i] + (nv - 1) * Memi[dv+i]
+ n = n * nv
+ }
+ if (n < NMAX)
+ break
+ }
+
+ call amovl (Memi[v1], Memi[va], IM_MAXDIM)
+ Memi[va] = 1
+ if (project)
+ Memi[va+ndim] = image
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+
+ # Accumulate the pixel values within the section. Masked pixels and
+ # thresholded pixels are ignored.
+
+ call salloc (data, n, TY_DOUBLE)
+ dp = data
+ while (imgnld (im, lp, Memi[vb]) != EOF) {
+ call ic_mget1 (im, image, offsets[image,1], Memi[va], mask)
+ lp = lp + Memi[v1] - 1
+ if (dflag == D_ALL) {
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ a = Memd[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Memd[dp] = a
+ dp = dp + 1
+ }
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ Memd[dp] = Memd[lp]
+ dp = dp + 1
+ lp = lp + Memi[dv]
+ }
+ }
+ } else if (dflag == D_MIX) {
+ mp = mask + Memi[v1] - 1
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ a = Memd[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Memd[dp] = a
+ dp = dp + 1
+ }
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ Memd[dp] = Memd[lp]
+ dp = dp + 1
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ }
+ }
+ for (i=2; i<=ndim; i=i+1) {
+ Memi[va+i-1] = Memi[va+i-1] + Memi[dv+i-1]
+ if (Memi[va+i-1] <= Memi[v2+i-1])
+ break
+ Memi[va+i-1] = Memi[v1+i-1]
+ }
+ if (i > ndim)
+ break
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+ }
+
+ n = dp - data
+ if (n < 1) {
+ call sfree (sp)
+ call error (1, "Image section contains no pixels")
+ }
+
+ # Compute only statistics needed.
+ if (domode || domedian) {
+ call asrtd (Memd[data], Memd[data], n)
+ mode = ic_moded (Memd[data], n)
+ median = Memd[data+n/2-1]
+ }
+ if (domean)
+ mean = asumd (Memd[data], n) / n
+
+ call sfree (sp)
+end
+
+
+define NMIN 10 # Minimum number of pixels for mode calculation
+define ZRANGE 0.8 # Fraction of pixels about median to use
+define ZSTEP 0.01 # Step size for search for mode
+define ZBIN 0.1 # Bin size for mode.
+
+# IC_MODE -- Compute mode of an array. The mode is found by binning
+# with a bin size based on the data range over a fraction of the
+# pixels about the median and a bin step which may be smaller than the
+# bin size. If there are too few points the median is returned.
+# The input array must be sorted.
+
+double procedure ic_moded (a, n)
+
+double a[n] # Data array
+int n # Number of points
+
+int i, j, k, nmax
+real z1, z2, zstep, zbin
+double mode
+bool fp_equalr()
+
+begin
+ if (n < NMIN)
+ return (a[n/2])
+
+ # Compute the mode. The array must be sorted. Consider a
+ # range of values about the median point. Use a bin size which
+ # is ZBIN of the range. Step the bin limits in ZSTEP fraction of
+ # the bin size.
+
+ i = 1 + n * (1. - ZRANGE) / 2.
+ j = 1 + n * (1. + ZRANGE) / 2.
+ z1 = a[i]
+ z2 = a[j]
+ if (fp_equalr (z1, z2)) {
+ mode = z1
+ return (mode)
+ }
+
+ zstep = ZSTEP * (z2 - z1)
+ zbin = ZBIN * (z2 - z1)
+
+ z1 = z1 - zstep
+ k = i
+ nmax = 0
+ repeat {
+ z1 = z1 + zstep
+ z2 = z1 + zbin
+ for (; i < j && a[i] < z1; i=i+1)
+ ;
+ for (; k < j && a[k] < z2; k=k+1)
+ ;
+ if (k - i > nmax) {
+ nmax = k - i
+ mode = a[(i+k)/2]
+ }
+ } until (k >= j)
+
+ return (mode)
+end
+
diff --git a/pkg/obsolete/imcombine/generic/mkpkg b/pkg/obsolete/imcombine/generic/mkpkg
new file mode 100644
index 00000000..8e80222b
--- /dev/null
+++ b/pkg/obsolete/imcombine/generic/mkpkg
@@ -0,0 +1,23 @@
+# Make IMCOMBINE.
+
+$checkout libpkg.a ../../../../
+$update libpkg.a
+$checkin libpkg.a ../../../../
+$exit
+
+libpkg.a:
+ icaclip.x ../icombine.com ../icombine.h
+ icaverage.x ../icombine.com ../icombine.h <imhdr.h>
+ iccclip.x ../icombine.com ../icombine.h
+ icgdata.x ../icombine.com ../icombine.h <imhdr.h> <mach.h>
+ icgrow.x ../icombine.com ../icombine.h <imhdr.h> <pmset.h>
+ icmedian.x ../icombine.com ../icombine.h
+ icmm.x ../icombine.com ../icombine.h
+ icombine.x ../icombine.com ../icombine.h <error.h> <imhdr.h>\
+ <imset.h> <mach.h> <pmset.h> <syserr.h>
+ icpclip.x ../icombine.com ../icombine.h
+ icsclip.x ../icombine.com ../icombine.h
+ icsigma.x ../icombine.com ../icombine.h <imhdr.h>
+ icsort.x
+ icstat.x ../icombine.com ../icombine.h <imhdr.h>
+ ;
diff --git a/pkg/obsolete/imcombine/icaclip.gx b/pkg/obsolete/imcombine/icaclip.gx
new file mode 100644
index 00000000..677e561c
--- /dev/null
+++ b/pkg/obsolete/imcombine/icaclip.gx
@@ -0,0 +1,573 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 3 # Minimum number of images for this algorithm
+
+$for (sird)
+# IC_AAVSIGCLIP -- Reject pixels using an average sigma about the average
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_aavsigclip$t (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+$if (datatype == sil)
+real average[npts] # Average
+$else
+PIXEL average[npts] # Average
+$endif
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+$if (datatype == sil)
+real d1, low, high, sum, a, s, s1, r, one
+data one /1.0/
+$else
+PIXEL d1, low, high, sum, a, s, s1, r, one
+data one /1$f/
+$endif
+pointer sp, sums, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (sums, npts, TY_REAL)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Since the unweighted average is computed here possibly skip combining
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Compute the unweighted average with the high and low rejected and
+ # the poisson scaled average sigma. There must be at least three
+ # pixels at each point to define the average and contributions to
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ nin = n[1]
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3)
+ next
+
+ # Unweighted average with the high and low rejected
+ low = Mem$t[d[1]+k]
+ high = Mem$t[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Mem$t[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Mem$t[dp1]
+ l = Memi[mp1]
+ s1 = max (one, (a + zeros[l]) / scales[l])
+ s = s + (d1 - a) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, a)
+ do j = 1, n1
+ s = s + (Mem$t[d[j]+k] - a) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the average and sum for later.
+ average[i] = a
+ Memr[sums+k] = sum
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+
+ # Reject pixels and compute the final average (if needed).
+ # There must be at least three pixels at each point for rejection.
+ # Iteratively scale the mean sigma and reject pixels
+ # Compact the data and keep track of the image IDs if needed.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (2, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Mem$t[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mem$t[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ a = average[i]
+ sum = Memr[sums+k]
+
+ repeat {
+ n2 = n1
+ if (s > 0.) {
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ d1 = Mem$t[dp1]
+ l = Memi[mp1]
+ s1 = s * sqrt (max (one, (a+zeros[l]) / scales[l]))
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ s1 = s * sqrt (max (one, a))
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Mem$t[dp1]
+ r = (d1 - a) / s1
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mem$t[dp1]
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Mem$t[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mem$t[dp1]
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Mem$t[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MAVSIGCLIP -- Reject pixels using an average sigma about the median
+# The average sigma is normalized by the expected poisson sigma.
+
+procedure ic_mavsigclip$t (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+$if (datatype == sil)
+real median[npts] # Median
+$else
+PIXEL median[npts] # Median
+$endif
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+pointer sp, resid, mp1, mp2
+$if (datatype == sil)
+real med, low, high, r, s, s1, one
+data one /1.0/
+$else
+PIXEL med, low, high, r, s, s1, one
+data one /1$f/
+$endif
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute the poisson scaled average sigma about the median.
+ # There must be at least three pixels at each point to define
+ # the mean sigma. Corrections for differences in the image
+ # scale factors are selected by the doscale1 flag.
+
+ s = 0.
+ n2 = 0
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 < 3) {
+ if (n1 == 0)
+ median[i] = blank
+ else if (n1 == 1)
+ median[i] = Mem$t[d[1]+k]
+ else {
+ low = Mem$t[d[1]+k]
+ high = Mem$t[d[2]+k]
+ median[i] = (low + high) / 2.
+ }
+ next
+ }
+
+ # Median
+ n3 = 1 + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Mem$t[d[n3-1]+k]
+ high = Mem$t[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Mem$t[d[n3]+k]
+
+ # Poisson scaled sigma accumulation
+ if (doscale1) {
+ do j = 1, n1 {
+ l = Memi[m[j]+k]
+ s1 = max (one, (med + zeros[l]) / scales[l])
+ s = s + (Mem$t[d[j]+k] - med) ** 2 / s1
+ }
+ } else {
+ s1 = max (one, med)
+ do j = 1, n1
+ s = s + (Mem$t[d[j]+k] - med) ** 2 / s1
+ }
+ n2 = n2 + n1
+
+ # Save the median for later.
+ median[i] = med
+ }
+
+ # Here is the final sigma.
+ if (n2 > 1)
+ s = sqrt (s / (n2 - 1))
+ else
+ return
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 < max (3, maxkeep+1))
+ next
+ nl = 1
+ nh = n1
+ med = median[i]
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 >= max (MINCLIP, maxkeep+1) && s > 0.) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (med - Mem$t[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s1 = s * sqrt (max (one, (med+zeros[l])/scales[l]))
+ r = (Mem$t[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ s1 = s * sqrt (max (one, med))
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Mem$t[d[nl]+k]) / s1
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Mem$t[d[nh]+k] - med) / s1
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Mem$t[d[n3-1]+k]
+ high = Mem$t[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Mem$t[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many are rejected add some back in.
+ # Pixels with equal residuals are added together.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+
+ # Recompute median
+ if (n1 < n2) {
+ if (n1 > 0) {
+ n3 = nl + n1 / 2
+ if (mod (n1, 2) == 0) {
+ low = Mem$t[d[n3-1]+k]
+ high = Mem$t[d[n3]+k]
+ med = (low + high) / 2.
+ } else
+ med = Mem$t[d[n3]+k]
+ } else
+ med = blank
+ }
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mem$t[d[l]+k] = Mem$t[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mem$t[d[l]+k] = Mem$t[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icaverage.gx b/pkg/obsolete/imcombine/icaverage.gx
new file mode 100644
index 00000000..505f4577
--- /dev/null
+++ b/pkg/obsolete/imcombine/icaverage.gx
@@ -0,0 +1,97 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+$for (sird)
+# IC_AVERAGE -- Compute the average image line.
+# Options include a weight average.
+
+procedure ic_average$t (d, m, n, wts, npts, doblank, average)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+int doblank # Set blank values?
+$if (datatype == sil)
+real average[npts] # Average (returned)
+$else
+PIXEL average[npts] # Average (returned)
+$endif
+
+int i, j, k
+real sumwt, wt
+$if (datatype == sil)
+real sum
+$else
+PIXEL sum
+$endif
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average without checking the
+ # number of points and using the fact that the weights are normalized.
+ # If all the data has been excluded set the average to the blank value
+ # if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts) {
+ do i = 1, npts {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Mem$t[d[1]+k] * wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Mem$t[d[j]+k] * wt
+ }
+ average[i] = sum
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ sum = Mem$t[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Mem$t[d[j]+k]
+ average[i] = sum / n[i]
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Mem$t[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n[i] {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Mem$t[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ average[i] = sum / sumwt
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ if (n[i] > 0) {
+ k = i - 1
+ sum = Mem$t[d[1]+k]
+ do j = 2, n[i]
+ sum = sum + Mem$t[d[j]+k]
+ average[i] = sum / n[i]
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/iccclip.gx b/pkg/obsolete/imcombine/iccclip.gx
new file mode 100644
index 00000000..609b3448
--- /dev/null
+++ b/pkg/obsolete/imcombine/iccclip.gx
@@ -0,0 +1,471 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 2 # Mininum number of images for algorithm
+
+$for (sird)
+# IC_ACCDCLIP -- Reject pixels using CCD noise parameters about the average
+
+procedure ic_accdclip$t (d, m, n, scales, zeros, nm, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model parameters
+int nimages # Number of images
+int npts # Number of output points per line
+$if (datatype == sil)
+real average[npts] # Average
+$else
+PIXEL average[npts] # Average
+$endif
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+$if (datatype == sil)
+real d1, low, high, sum, a, s, r, zero
+data zero /0.0/
+$else
+PIXEL d1, low, high, sum, a, s, r, zero
+data zero /0$f/
+$endif
+pointer sp, resid, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are no pixels go on to the combining. Since the unweighted
+ # average is computed here possibly skip the combining later.
+
+ # There must be at least max (1, nkeep) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ } else if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # There must be at least two pixels for rejection. The initial
+ # average is the low/high rejected average except in the case of
+ # just two pixels. The rejections are iterated and the average
+ # is recomputed. Corrections for scaling may be performed.
+ # Depending on other flags the image IDs may also need to be adjusted.
+
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 <= max (MINCLIP-1, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Mem$t[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mem$t[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ repeat {
+ if (n1 == 2) {
+ sum = Mem$t[d[1]+k]
+ sum = sum + Mem$t[d[2]+k]
+ a = sum / 2
+ } else {
+ low = Mem$t[d[1]+k]
+ high = Mem$t[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Mem$t[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+ }
+ n2 = n1
+ if (doscale1) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+
+ l = Memi[mp1]
+ s = scales[l]
+ d1 = max (zero, s * (a + zeros[l]))
+ s = sqrt (nm[1,l] + d1/nm[2,l] + (d1*nm[3,l])**2) / s
+
+ d1 = Mem$t[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ mp2 = m[n1] + k
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, a)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (j=1; j<=n1; j=j+1) {
+ if (keepids) {
+ l = Memi[m[j]+k]
+ s = max (zero, a)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ dp1 = d[j] + k
+ d1 = Mem$t[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs(r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mem$t[dp1]
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Mem$t[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mem$t[dp1]
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Mem$t[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+ }
+
+ n[i] = n1
+ if (!docombine)
+ if (n1 > 0)
+ average[i] = sum / n1
+ else
+ average[i] = blank
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_CCDCLIP -- Reject pixels using CCD noise parameters about the median
+
+procedure ic_mccdclip$t (d, m, n, scales, zeros, nm, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real nm[3,nimages] # Noise model
+int nimages # Number of images
+int npts # Number of output points per line
+$if (datatype == sil)
+real median[npts] # Median
+$else
+PIXEL median[npts] # Median
+$endif
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, mp1, mp2
+$if (datatype == sil)
+real med, zero
+data zero /0.0/
+$else
+PIXEL med, zero
+data zero /0$f/
+$endif
+
+include "../icombine.com"
+
+begin
+ # There must be at least max (MINCLIP, nkeep+1) pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0) {
+ med = Mem$t[d[n3-1]+k]
+ med = (med + Mem$t[d[n3]+k]) / 2.
+ } else
+ med = Mem$t[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ for (; nl <= n2; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (med - Mem$t[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ l = Memi[m[nh]+k]
+ s = scales[l]
+ r = max (zero, s * (med + zeros[l]))
+ s = sqrt (nm[1,l] + r/nm[2,l] + (r*nm[3,l])**2) / s
+ r = (Mem$t[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ } else {
+ if (!keepids) {
+ s = max (zero, med)
+ s = sqrt (nm[1,1] + s/nm[2,1] + (s*nm[3,1])**2)
+ }
+ for (; nl <= n2; nl = nl + 1) {
+ if (keepids) {
+ l = Memi[m[nl]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (med - Mem$t[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ if (keepids) {
+ l = Memi[m[nh]+k]
+ s = max (zero, med)
+ s = sqrt (nm[1,l] + s/nm[2,l] + (s*nm[3,l])**2)
+ }
+ r = (Mem$t[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mem$t[d[l]+k] = Mem$t[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mem$t[d[l]+k] = Mem$t[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median is computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icgdata.gx b/pkg/obsolete/imcombine/icgdata.gx
new file mode 100644
index 00000000..ce71a3eb
--- /dev/null
+++ b/pkg/obsolete/imcombine/icgdata.gx
@@ -0,0 +1,235 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+
+$for (sird)
+# IC_GDATA -- Get line of image and mask data and apply threshold and scaling.
+# Entirely empty lines are excluded. The data are compacted within the
+# input data buffers. If it is required, the connection to the original
+# image index is kept in the returned m data pointers.
+
+procedure ic_gdata$t (in, out, dbuf, d, id, n, m, lflag, offsets, scales,
+ zeros, nimages, npts, v1, v2)
+
+pointer in[nimages] # Input images
+pointer out[3] # Output images
+pointer dbuf[nimages] # Data buffers
+pointer d[nimages] # Data pointers
+pointer id[nimages] # ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Empty mask flags
+int offsets[nimages,ARB] # Image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+int nimages # Number of input images
+int npts # NUmber of output points per line
+long v1[ARB], v2[ARB] # Line vectors
+
+int i, j, k, l, ndim, nused
+real a, b
+pointer buf, dp, ip, mp, imgnl$t()
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ ndim = IM_NDIM(out[1])
+ do i = 1, nimages {
+ if (lflag[i] == D_NONE)
+ next
+ if (dbuf[i] == NULL) {
+ call amovl (v1, v2, IM_MAXDIM)
+ if (project)
+ v2[ndim+1] = i
+ j = imgnl$t (in[i], d[i], v2)
+ } else {
+ v2[1] = v1[1]
+ do j = 2, ndim
+ v2[j] = v1[j] - offsets[i,j]
+ if (project)
+ v2[ndim+1] = i
+ j = imgnl$t (in[i], buf, v2)
+ call amov$t (Mem$t[buf], Mem$t[dbuf[i]+offsets[i,1]],
+ IM_LEN(in[i],1))
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ dp = d[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ a = Mem$t[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ a = Mem$t[dp]
+ if (a < lthresh || a > hthresh) {
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+
+ # Check for completely empty lines
+ if (lflag[i] == D_MIX) {
+ lflag[i] = D_NONE
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ lflag[i] = D_MIX
+ break
+ }
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply scaling (avoiding masked pixels which might overflow?)
+ if (doscale) {
+ if (dflag == D_ALL) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ do j = 1, npts {
+ Mem$t[dp] = Mem$t[dp] / a + b
+ dp = dp + 1
+ }
+ }
+ } else if (dflag == D_MIX) {
+ do i = 1, nimages {
+ dp = d[i]
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ do j = 1, npts {
+ Mem$t[dp] = Mem$t[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0)
+ Mem$t[dp] = Mem$t[dp] / a + b
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+ }
+
+ # Sort pointers to exclude unused images.
+ # Use the lflag array to keep track of the image index.
+
+ if (dflag == D_ALL)
+ nused = nimages
+ else {
+ nused = 0
+ do i = 1, nimages
+ if (lflag[i] != D_NONE) {
+ nused = nused + 1
+ d[nused] = d[i]
+ m[nused] = m[i]
+ lflag[nused] = i
+ }
+ if (nused == 0)
+ dflag = D_NONE
+ }
+
+ # Compact data to remove bad pixels
+ # Keep track of the image indices if needed
+ # If growing mark the end of the included image indices with zero
+
+ if (dflag == D_ALL) {
+ call amovki (nused, n, npts)
+ if (keepids)
+ do i = 1, nimages
+ call amovki (i, Memi[id[i]], npts)
+ } else if (dflag == D_NONE)
+ call aclri (n, npts)
+ else {
+ call aclri (n, npts)
+ if (keepids) {
+ do i = 1, nused {
+ l = lflag[i]
+ dp = d[i]
+ ip = id[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ Mem$t[d[k]+j-1] = Mem$t[dp]
+ Memi[id[k]+j-1] = l
+ } else
+ Memi[ip] = l
+ }
+ dp = dp + 1
+ ip = ip + 1
+ mp = mp + 1
+ }
+ }
+ if (grow >= 1.) {
+ do j = 1, npts {
+ do i = n[j]+1, nimages
+ Memi[id[i]+j-1] = 0
+ }
+ }
+ } else {
+ do i = 1, nused {
+ dp = d[i]
+ mp = m[i]
+ do j = 1, npts {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i)
+ Mem$t[d[k]+j-1] = Mem$t[dp]
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nimages, TY_PIXEL)
+ if (keepids) {
+ call malloc (ip, nimages, TY_INT)
+ call ic_2sort$t (d, Mem$t[dp], id, Memi[ip], n, npts)
+ call mfree (ip, TY_INT)
+ } else
+ call ic_sort$t (d, Mem$t[dp], n, npts)
+ call mfree (dp, TY_PIXEL)
+ }
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icgrow.gx b/pkg/obsolete/imcombine/icgrow.gx
new file mode 100644
index 00000000..8b28aec5
--- /dev/null
+++ b/pkg/obsolete/imcombine/icgrow.gx
@@ -0,0 +1,123 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <pmset.h>
+include "../icombine.h"
+
+# IC_GROW -- Mark neigbors of rejected pixels.
+# The rejected pixels (original plus grown) are saved in pixel masks.
+
+procedure ic_grow (out, v, m, n, buf, nimages, npts, pms)
+
+pointer out # Output image pointer
+long v[ARB] # Output vector
+pointer m[ARB] # Image id pointers
+int n[ARB] # Number of good pixels
+int buf[npts,nimages] # Working buffer
+int nimages # Number of images
+int npts # Number of output points per line
+pointer pms # Pointer to array of pixel masks
+
+int i, j, k, l, line, nl, rop, igrow, nset, or()
+real grow2, i2
+pointer mp, pm, pm_newmask()
+errchk pm_newmask()
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE || grow == 0.)
+ return
+
+ line = v[2]
+ nl = IM_LEN(out,2)
+ rop = or (PIX_SRC, PIX_DST)
+
+ igrow = grow
+ grow2 = grow**2
+ do l = 0, igrow {
+ i2 = grow2 - l * l
+ call aclri (buf, npts*nimages)
+ nset = 0
+ do j = 1, npts {
+ do k = n[j]+1, nimages {
+ mp = Memi[m[k]+j-1]
+ if (mp == 0)
+ next
+ do i = 0, igrow {
+ if (i**2 > i2)
+ next
+ if (j > i)
+ buf[j-i,mp] = 1
+ if (j+i <= npts)
+ buf[j+i,mp] = 1
+ nset = nset + 1
+ }
+ }
+ }
+ if (nset == 0)
+ return
+
+ if (pms == NULL) {
+ call malloc (pms, nimages, TY_POINTER)
+ do i = 1, nimages
+ Memi[pms+i-1] = pm_newmask (out, 1)
+ }
+ do i = 1, nimages {
+ pm = Memi[pms+i-1]
+ v[2] = line - l
+ if (v[2] > 0)
+ call pmplpi (pm, v, buf[1,i], 1, npts, rop)
+ v[2] = line + l
+ if (v[2] <= nl)
+ call pmplpi (pm, v, buf[1,i], 1, npts, rop)
+ }
+ }
+ v[2] = line
+end
+
+
+$for (sird)
+# IC_GROW$T -- Reject pixels.
+
+procedure ic_grow$t (v, d, m, n, buf, nimages, npts, pms)
+
+long v[ARB] # Output vector
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[ARB] # Number of good pixels
+int buf[ARB] # Buffer of npts
+int nimages # Number of images
+int npts # Number of output points per line
+pointer pms # Pointer to array of pixel masks
+
+int i, j, k
+pointer pm
+bool pl_linenotempty()
+
+include "../icombine.com"
+
+begin
+ do k = 1, nimages {
+ pm = Memi[pms+k-1]
+ if (!pl_linenotempty (pm, v))
+ next
+ call pmglpi (pm, v, buf, 1, npts, PIX_SRC)
+ do i = 1, npts {
+ if (buf[i] == 0)
+ next
+ for (j = 1; j <= n[i]; j = j + 1) {
+ if (Memi[m[j]+i-1] == k) {
+ if (j < n[i]) {
+ Mem$t[d[j]+i-1] = Mem$t[d[n[i]]+i-1]
+ Memi[m[j]+i-1] = Memi[m[n[i]]+i-1]
+ }
+ n[i] = n[i] - 1
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+ }
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icimstack.x b/pkg/obsolete/imcombine/icimstack.x
new file mode 100644
index 00000000..f3f6eaa5
--- /dev/null
+++ b/pkg/obsolete/imcombine/icimstack.x
@@ -0,0 +1,129 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <imhdr.h>
+
+
+# IC_IMSTACK -- Stack images into a single image of higher dimension.
+
+procedure ic_imstack (list, output)
+
+int list #I List of images
+char output #I Name of output image
+
+int i, j, npix
+long line_in[IM_MAXDIM], line_out[IM_MAXDIM]
+pointer sp, input, key, in, out, buf_in, buf_out, ptr
+
+int imtgetim(), imtlen()
+int imgnls(), imgnli(), imgnll(), imgnlr(), imgnld(), imgnlx()
+int impnls(), impnli(), impnll(), impnlr(), impnld(), impnlx()
+pointer immap()
+errchk immap
+
+begin
+ call smark (sp)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+
+ iferr {
+ # Add each input image to the output image.
+ out = NULL
+ i = 0
+ while (imtgetim (list, Memc[input], SZ_FNAME) != EOF) {
+
+ i = i + 1
+ in = NULL
+ ptr = immap (Memc[input], READ_ONLY, 0)
+ in = ptr
+
+ # For the first input image map the output image as a copy
+ # and increment the dimension. Set the output line counter.
+
+ if (i == 1) {
+ ptr = immap (output, NEW_COPY, in)
+ out = ptr
+ IM_NDIM(out) = IM_NDIM(out) + 1
+ IM_LEN(out, IM_NDIM(out)) = imtlen (list)
+ npix = IM_LEN(out, 1)
+ call amovkl (long(1), line_out, IM_MAXDIM)
+ }
+
+ # Check next input image for consistency with the output image.
+ if (IM_NDIM(in) != IM_NDIM(out) - 1)
+ call error (0, "Input images not consistent")
+ do j = 1, IM_NDIM(in) {
+ if (IM_LEN(in, j) != IM_LEN(out, j))
+ call error (0, "Input images not consistent")
+ }
+
+ call sprintf (Memc[key], SZ_FNAME, "stck%04d")
+ call pargi (i)
+ call imastr (out, Memc[key], Memc[input])
+
+ # Copy the input lines from the image to the next lines of
+ # the output image. Switch on the output data type to optimize
+ # IMIO.
+
+ call amovkl (long(1), line_in, IM_MAXDIM)
+ switch (IM_PIXTYPE (out)) {
+ case TY_SHORT:
+ while (imgnls (in, buf_in, line_in) != EOF) {
+ if (impnls (out, buf_out, line_out) == EOF)
+ call error (0, "Error writing output image")
+ call amovs (Mems[buf_in], Mems[buf_out], npix)
+ }
+ case TY_INT:
+ while (imgnli (in, buf_in, line_in) != EOF) {
+ if (impnli (out, buf_out, line_out) == EOF)
+ call error (0, "Error writing output image")
+ call amovi (Memi[buf_in], Memi[buf_out], npix)
+ }
+ case TY_USHORT, TY_LONG:
+ while (imgnll (in, buf_in, line_in) != EOF) {
+ if (impnll (out, buf_out, line_out) == EOF)
+ call error (0, "Error writing output image")
+ call amovl (Meml[buf_in], Meml[buf_out], npix)
+ }
+ case TY_REAL:
+ while (imgnlr (in, buf_in, line_in) != EOF) {
+ if (impnlr (out, buf_out, line_out) == EOF)
+ call error (0, "Error writing output image")
+ call amovr (Memr[buf_in], Memr[buf_out], npix)
+ }
+ case TY_DOUBLE:
+ while (imgnld (in, buf_in, line_in) != EOF) {
+ if (impnld (out, buf_out, line_out) == EOF)
+ call error (0, "Error writing output image")
+ call amovd (Memd[buf_in], Memd[buf_out], npix)
+ }
+ case TY_COMPLEX:
+ while (imgnlx (in, buf_in, line_in) != EOF) {
+ if (impnlx (out, buf_out, line_out) == EOF)
+ call error (0, "Error writing output image")
+ call amovx (Memx[buf_in], Memx[buf_out], npix)
+ }
+ default:
+ while (imgnlr (in, buf_in, line_in) != EOF) {
+ if (impnlr (out, buf_out, line_out) == EOF)
+ call error (0, "Error writing output image")
+ call amovr (Memr[buf_in], Memr[buf_out], npix)
+ }
+ }
+ call imunmap (in)
+ }
+ } then {
+ if (out != NULL) {
+ call imunmap (out)
+ call imdelete (out)
+ }
+ if (in != NULL)
+ call imunmap (in)
+ call sfree (sp)
+ call erract (EA_ERROR)
+ }
+
+ # Finish up.
+ call imunmap (out)
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/imcombine/iclog.x b/pkg/obsolete/imcombine/iclog.x
new file mode 100644
index 00000000..f373e9e4
--- /dev/null
+++ b/pkg/obsolete/imcombine/iclog.x
@@ -0,0 +1,384 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <imset.h>
+include <mach.h>
+include "icombine.h"
+
+# IC_LOG -- Output log information is a log file has been specfied.
+
+procedure ic_log (in, out, ncombine, exptime, sname, zname, wname,
+ mode, median, mean, scales, zeros, wts, offsets, nimages,
+ dozero, nout, expname, exposure)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output images
+int ncombine[nimages] # Number of previous combined images
+real exptime[nimages] # Exposure times
+char sname[ARB] # Scale name
+char zname[ARB] # Zero name
+char wname[ARB] # Weight name
+real mode[nimages] # Modes
+real median[nimages] # Medians
+real mean[nimages] # Means
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero or sky levels
+real wts[nimages] # Weights
+int offsets[nimages,ARB] # Image offsets
+int nimages # Number of images
+bool dozero # Zero flag
+int nout # Number of images combined in output
+char expname[ARB] # Exposure name
+real exposure # Output exposure
+
+int i, j, stack, ctor()
+real rval, imgetr()
+long clktime()
+bool prncombine, prexptime, prmode, prmedian, prmean, prmask
+bool prrdn, prgain, prsn
+pointer sp, fname, key
+errchk imgetr
+
+include "icmask.com"
+include "icombine.com"
+
+begin
+ if (logfd == NULL)
+ return
+
+ call smark (sp)
+ call salloc (fname, SZ_LINE, TY_CHAR)
+
+ stack = NO
+ if (project) {
+ ifnoerr (call imgstr (in[1], "stck0001", Memc[fname], SZ_LINE))
+ stack = YES
+ }
+ if (stack == YES)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+
+ # Time stamp the log and print parameter information.
+
+ call cnvdate (clktime(0), Memc[fname], SZ_LINE)
+ call fprintf (logfd, "\n%s: IMCOMBINE\n")
+ call pargstr (Memc[fname])
+ switch (combine) {
+ case AVERAGE:
+ call fprintf (logfd, " combine = average, ")
+ case MEDIAN:
+ call fprintf (logfd, " combine = median, ")
+ }
+ call fprintf (logfd, "scale = %s, zero = %s, weight = %s\n")
+ call pargstr (sname)
+ call pargstr (zname)
+ call pargstr (wname)
+
+ switch (reject) {
+ case MINMAX:
+ call fprintf (logfd, " reject = minmax, nlow = %d, nhigh = %d\n")
+ call pargi (nint (flow * nimages))
+ call pargi (nint (fhigh * nimages))
+ case CCDCLIP:
+ call fprintf (logfd, " reject = ccdclip, mclip = %b, nkeep = %d\n")
+ call pargb (mclip)
+ call pargi (nkeep)
+ call fprintf (logfd,
+ " rdnoise = %s, gain = %s, snoise = %s, sigma = %g, hsigma = %g\n")
+ call pargstr (Memc[rdnoise])
+ call pargstr (Memc[gain])
+ call pargstr (Memc[snoise])
+ call pargr (lsigma)
+ call pargr (hsigma)
+ case CRREJECT:
+ call fprintf (logfd,
+ " reject = crreject, mclip = %b, nkeep = %d\n")
+ call pargb (mclip)
+ call pargi (nkeep)
+ call fprintf (logfd,
+ " rdnoise = %s, gain = %s, snoise = %s, hsigma = %g\n")
+ call pargstr (Memc[rdnoise])
+ call pargstr (Memc[gain])
+ call pargstr (Memc[snoise])
+ call pargr (hsigma)
+ case PCLIP:
+ call fprintf (logfd, " reject = pclip, nkeep = %d\n")
+ call pargi (nkeep)
+ call fprintf (logfd, " pclip = %g, lsigma = %g, hsigma = %g\n")
+ call pargr (pclip)
+ call pargr (lsigma)
+ call pargr (hsigma)
+ case SIGCLIP:
+ call fprintf (logfd, " reject = sigclip, mclip = %b, nkeep = %d\n")
+ call pargb (mclip)
+ call pargi (nkeep)
+ call fprintf (logfd, " lsigma = %g, hsigma = %g\n")
+ call pargr (lsigma)
+ call pargr (hsigma)
+ case AVSIGCLIP:
+ call fprintf (logfd,
+ " reject = avsigclip, mclip = %b, nkeep = %d\n")
+ call pargb (mclip)
+ call pargi (nkeep)
+ call fprintf (logfd, " lsigma = %g, hsigma = %g\n")
+ call pargr (lsigma)
+ call pargr (hsigma)
+ }
+ if (reject != NONE && grow >= 1.) {
+ call fprintf (logfd, " grow = %g\n")
+ call pargr (grow)
+ }
+ if (dothresh) {
+ if (lthresh > -MAX_REAL && hthresh < MAX_REAL) {
+ call fprintf (logfd, " lthreshold = %g, hthreshold = %g\n")
+ call pargr (lthresh)
+ call pargr (hthresh)
+ } else if (lthresh > -MAX_REAL) {
+ call fprintf (logfd, " lthreshold = %g\n")
+ call pargr (lthresh)
+ } else {
+ call fprintf (logfd, " hthreshold = %g\n")
+ call pargr (hthresh)
+ }
+ }
+ call fprintf (logfd, " blank = %g\n")
+ call pargr (blank)
+ call clgstr ("statsec", Memc[fname], SZ_LINE)
+ if (Memc[fname] != EOS) {
+ call fprintf (logfd, " statsec = %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ if (mtype != M_NONE) {
+ switch (mtype) {
+ case M_BOOLEAN, M_GOODVAL:
+ call fprintf (logfd, " masktype = goodval, maskval = %d\n")
+ call pargi (mvalue)
+ case M_BADVAL:
+ call fprintf (logfd, " masktype = badval, maskval = %d\n")
+ call pargi (mvalue)
+ case M_GOODBITS:
+ call fprintf (logfd, " masktype = goodbits, maskval = %d\n")
+ call pargi (mvalue)
+ case M_BADBITS:
+ call fprintf (logfd, " masktype = badbits, maskval = %d\n")
+ call pargi (mvalue)
+ }
+ }
+
+ # Print information pertaining to individual images as a set of
+ # columns with the image name being the first column. Determine
+ # what information is relevant and print the appropriate header.
+
+ prncombine = false
+ prexptime = false
+ prmode = false
+ prmedian = false
+ prmean = false
+ prmask = false
+ prrdn = false
+ prgain = false
+ prsn = false
+ do i = 1, nimages {
+ if (ncombine[i] != ncombine[1])
+ prncombine = true
+ if (exptime[i] != exptime[1])
+ prexptime = true
+ if (mode[i] != mode[1])
+ prmode = true
+ if (median[i] != median[1])
+ prmedian = true
+ if (mean[i] != mean[1])
+ prmean = true
+ if (mtype != M_NONE && Memi[pms+i-1] != NULL)
+ prmask = true
+ if (reject == CCDCLIP || reject == CRREJECT) {
+ j = 1
+ if (ctor (Memc[rdnoise], j, rval) == 0)
+ prrdn = true
+ j = 1
+ if (ctor (Memc[gain], j, rval) == 0)
+ prgain = true
+ j = 1
+ if (ctor (Memc[snoise], j, rval) == 0)
+ prsn = true
+ }
+ }
+
+ call fprintf (logfd, " %20s ")
+ call pargstr ("Images")
+ if (prncombine) {
+ call fprintf (logfd, " %6s")
+ call pargstr ("N")
+ }
+ if (prexptime) {
+ call fprintf (logfd, " %6s")
+ call pargstr ("Exp")
+ }
+ if (prmode) {
+ call fprintf (logfd, " %7s")
+ call pargstr ("Mode")
+ }
+ if (prmedian) {
+ call fprintf (logfd, " %7s")
+ call pargstr ("Median")
+ }
+ if (prmean) {
+ call fprintf (logfd, " %7s")
+ call pargstr ("Mean")
+ }
+ if (prrdn) {
+ call fprintf (logfd, " %7s")
+ call pargstr ("Rdnoise")
+ }
+ if (prgain) {
+ call fprintf (logfd, " %6s")
+ call pargstr ("Gain")
+ }
+ if (prsn) {
+ call fprintf (logfd, " %6s")
+ call pargstr ("Snoise")
+ }
+ if (doscale) {
+ call fprintf (logfd, " %6s")
+ call pargstr ("Scale")
+ }
+ if (dozero) {
+ call fprintf (logfd, " %7s")
+ call pargstr ("Zero")
+ }
+ if (dowts) {
+ call fprintf (logfd, " %6s")
+ call pargstr ("Weight")
+ }
+ if (!aligned) {
+ call fprintf (logfd, " %9s")
+ call pargstr ("Offsets")
+ }
+ if (prmask) {
+ call fprintf (logfd, " %s")
+ call pargstr ("Maskfile")
+ }
+ call fprintf (logfd, "\n")
+
+ do i = 1, nimages {
+ if (stack == YES) {
+ call sprintf (Memc[key], SZ_FNAME, "stck%04d")
+ call pargi (i)
+ ifnoerr (call imgstr (in[i], Memc[key], Memc[fname], SZ_LINE)) {
+ call fprintf (logfd, " %21s")
+ call pargstr (Memc[fname])
+ } else {
+ call imstats (in[i], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " %16s[%3d]")
+ call pargstr (Memc[fname])
+ call pargi (i)
+ }
+ } else if (project) {
+ call imstats (in[i], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " %16s[%3d]")
+ call pargstr (Memc[fname])
+ call pargi (i)
+ } else {
+ call imstats (in[i], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " %21s")
+ call pargstr (Memc[fname])
+ }
+ if (prncombine) {
+ call fprintf (logfd, " %6d")
+ call pargi (ncombine[i])
+ }
+ if (prexptime) {
+ call fprintf (logfd, " %6.1f")
+ call pargr (exptime[i])
+ }
+ if (prmode) {
+ call fprintf (logfd, " %7.5g")
+ call pargr (mode[i])
+ }
+ if (prmedian) {
+ call fprintf (logfd, " %7.5g")
+ call pargr (median[i])
+ }
+ if (prmean) {
+ call fprintf (logfd, " %7.5g")
+ call pargr (mean[i])
+ }
+ if (prrdn) {
+ rval = imgetr (in[i], Memc[rdnoise])
+ call fprintf (logfd, " %7g")
+ call pargr (rval)
+ }
+ if (prgain) {
+ rval = imgetr (in[i], Memc[gain])
+ call fprintf (logfd, " %6g")
+ call pargr (rval)
+ }
+ if (prsn) {
+ rval = imgetr (in[i], Memc[snoise])
+ call fprintf (logfd, " %6g")
+ call pargr (rval)
+ }
+ if (doscale) {
+ call fprintf (logfd, " %6.3f")
+ call pargr (1./scales[i])
+ }
+ if (dozero) {
+ call fprintf (logfd, " %7.5g")
+ call pargr (-zeros[i])
+ }
+ if (dowts) {
+ call fprintf (logfd, " %6.3f")
+ call pargr (wts[i])
+ }
+ if (!aligned) {
+ if (IM_NDIM(out[1]) == 1) {
+ call fprintf (logfd, " %9d")
+ call pargi (offsets[i,1])
+ } else {
+ do j = 1, IM_NDIM(out[1]) {
+ call fprintf (logfd, " %4d")
+ call pargi (offsets[i,j])
+ }
+ }
+ }
+ if (prmask && Memi[pms+i-1] != NULL) {
+ call imgstr (in[i], "BPM", Memc[fname], SZ_LINE)
+ call fprintf (logfd, " %s")
+ call pargstr (Memc[fname])
+ }
+ call fprintf (logfd, "\n")
+ }
+
+ # Log information about the output images.
+ call imstats (out[1], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, "\n Output image = %s, ncombine = %d")
+ call pargstr (Memc[fname])
+ call pargi (nout)
+ if (expname[1] != EOS) {
+ call fprintf (logfd, ", %s = %g")
+ call pargstr (expname)
+ call pargr (exposure)
+ }
+ call fprintf (logfd, "\n")
+
+ if (out[4] != NULL) {
+ call imstats (out[4], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " Rejection mask = %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ if (out[2] != NULL) {
+ call imstats (out[2], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " Pixel list image = %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ if (out[3] != NULL) {
+ call imstats (out[3], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " Sigma image = %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ call flush (logfd)
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/imcombine/icmask.com b/pkg/obsolete/imcombine/icmask.com
new file mode 100644
index 00000000..baba6f6a
--- /dev/null
+++ b/pkg/obsolete/imcombine/icmask.com
@@ -0,0 +1,8 @@
+# IMCMASK -- Common for IMCOMBINE mask interface.
+
+int mtype # Mask type
+int mvalue # Mask value
+pointer bufs # Pointer to data line buffers
+pointer pms # Pointer to array of PMIO pointers
+
+common /imcmask/ mtype, mvalue, bufs, pms
diff --git a/pkg/obsolete/imcombine/icmask.x b/pkg/obsolete/imcombine/icmask.x
new file mode 100644
index 00000000..9aeec395
--- /dev/null
+++ b/pkg/obsolete/imcombine/icmask.x
@@ -0,0 +1,314 @@
+include <imhdr.h>
+include <pmset.h>
+include "icombine.h"
+
+# IC_MASK -- ICOMBINE mask interface
+#
+# IC_MOPEN -- Open masks
+# IC_MCLOSE -- Close the mask interface
+# IC_MGET -- Get lines of mask pixels for all the images
+# IC_MGET1 -- Get a line of mask pixels for the specified image
+
+
+# IC_MOPEN -- Open masks.
+# Parse and interpret the mask selection parameters.
+
+procedure ic_mopen (in, out, nimages)
+
+pointer in[nimages] #I Input images
+pointer out[3] #I Output images
+int nimages #I Number of images
+
+int i, npix, npms, clgwrd()
+real clgetr()
+pointer sp, fname, title, pm, pm_open()
+bool invert, pm_empty()
+errchk calloc, pm_open, pm_loadf
+
+include "icmask.com"
+include "icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (title, SZ_FNAME, TY_CHAR)
+
+ # Determine the mask parameters and allocate memory.
+ # The mask buffers are initialize to all excluded so that
+ # output points outside the input data are always excluded
+ # and don't need to be set on a line-by-line basis.
+
+ mtype = clgwrd ("masktype", Memc[title], SZ_FNAME, MASKTYPES)
+ mvalue = clgetr ("maskvalue")
+ npix = IM_LEN(out[1],1)
+ call calloc (pms, nimages, TY_POINTER)
+ call calloc (bufs, nimages, TY_POINTER)
+ do i = 1, nimages {
+ call malloc (Memi[bufs+i-1], npix, TY_INT)
+ call amovki (1, Memi[Memi[bufs+i-1]], npix)
+ }
+
+ # Check for special cases. The BOOLEAN type is used when only
+ # zero and nonzero are significant; i.e. the actual mask values are
+ # not important. The invert flag is used to indicate that
+ # empty masks are all bad rather the all good.
+
+ if (mtype == 0)
+ mtype = M_NONE
+ if (mtype == M_BADBITS && mvalue == 0)
+ mtype = M_NONE
+ if (mvalue == 0 && (mtype == M_GOODVAL || mtype == M_GOODBITS))
+ mtype = M_BOOLEAN
+ if ((mtype == M_BADVAL && mvalue == 0) ||
+ (mtype == M_GOODVAL && mvalue != 0) ||
+ (mtype == M_GOODBITS && mvalue == 0))
+ invert = true
+ else
+ invert = false
+
+ # If mask images are to be used, get the mask name from the image
+ # header and open it saving the descriptor in the pms array.
+ # Empty masks (all good) are treated as if there was no mask image.
+
+ npms = 0
+ do i = 1, nimages {
+ if (mtype != M_NONE) {
+ ifnoerr (call imgstr (in[i], "BPM", Memc[fname], SZ_FNAME)) {
+ pm = pm_open (NULL)
+ call pm_loadf (pm, Memc[fname], Memc[title], SZ_FNAME)
+ call pm_seti (pm, P_REFIM, in[i])
+ if (pm_empty (pm) && !invert)
+ call pm_close (pm)
+ else {
+ if (project) {
+ npms = nimages
+ call amovki (pm, Memi[pms], nimages)
+ } else {
+ npms = npms + 1
+ Memi[pms+i-1] = pm
+ }
+ }
+ if (project)
+ break
+ }
+ }
+ }
+
+ # If no mask images are found and the mask parameters imply that
+ # good values are 0 then use the special case of no masks.
+
+ if (npms == 0) {
+ if (!invert)
+ mtype = M_NONE
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MCLOSE -- Close the mask interface.
+
+procedure ic_mclose (nimages)
+
+int nimages # Number of images
+
+int i
+include "icmask.com"
+include "icombine.com"
+
+begin
+ do i = 1, nimages
+ call mfree (Memi[bufs+i-1], TY_INT)
+ do i = 1, nimages {
+ if (Memi[pms+i-1] != NULL)
+ call pm_close (Memi[pms+i-1])
+ if (project)
+ break
+ }
+ call mfree (pms, TY_POINTER)
+ call mfree (bufs, TY_POINTER)
+end
+
+
+# IC_MGET -- Get lines of mask pixels in the output coordinate system.
+# This converts the mask format to an array where zero is good and nonzero
+# is bad. This has special cases for optimization.
+
+procedure ic_mget (in, out, offsets, v1, v2, m, lflag, nimages)
+
+pointer in[nimages] # Input image pointers
+pointer out[3] # Output image pointer
+int offsets[nimages,ARB] # Offsets to output image
+long v1[IM_MAXDIM] # Data vector desired in output image
+long v2[IM_MAXDIM] # Data vector in input image
+pointer m[nimages] # Pointer to mask pointers
+int lflag[nimages] # Line flags
+int nimages # Number of images
+
+int i, j, ndim, nout, npix
+pointer buf, pm
+bool pm_linenotempty()
+errchk pm_glpi
+
+include "icmask.com"
+include "icombine.com"
+
+begin
+ # Determine if masks are needed at all. Note that the threshold
+ # is applied by simulating mask values so the mask pointers have to
+ # be set.
+
+ if (mtype == M_NONE && aligned && !dothresh) {
+ dflag = D_ALL
+ return
+ }
+
+ # Set the mask pointers and line flags and apply offsets if needed.
+
+ ndim = IM_NDIM(out[1])
+ nout = IM_LEN(out[1],1)
+ do i = 1, nimages {
+ npix = IM_LEN(in[i],1)
+ j = offsets[i,1]
+ m[i] = Memi[bufs+i-1]
+ buf = Memi[bufs+i-1] + j
+ pm = Memi[pms+i-1]
+ if (npix == nout)
+ lflag[i] = D_ALL
+ else
+ lflag[i] = D_MIX
+
+ v2[1] = v1[1]
+ do j = 2, ndim {
+ v2[j] = v1[j] - offsets[i,j]
+ if (v2[j] < 1 || v2[j] > IM_LEN(in[i],j)) {
+ lflag[i] = D_NONE
+ break
+ }
+ }
+ if (project)
+ v2[ndim+1] = i
+
+ if (lflag[i] == D_NONE)
+ next
+
+ if (pm == NULL) {
+ call aclri (Memi[buf], npix)
+ next
+ }
+
+ # Do mask I/O and convert to appropriate values in order of
+ # expected usage.
+
+ if (pm_linenotempty (pm, v2)) {
+ call pm_glpi (pm, v2, Memi[buf], 32, npix, 0)
+
+ if (mtype == M_BOOLEAN)
+ ;
+ else if (mtype == M_BADBITS)
+ call aandki (Memi[buf], mvalue, Memi[buf], npix)
+ else if (mtype == M_BADVAL)
+ call abeqki (Memi[buf], mvalue, Memi[buf], npix)
+ else if (mtype == M_GOODBITS) {
+ call aandki (Memi[buf], mvalue, Memi[buf], npix)
+ call abeqki (Memi[buf], 0, Memi[buf], npix)
+ } else if (mtype == M_GOODVAL)
+ call abneki (Memi[buf], mvalue, Memi[buf], npix)
+
+ lflag[i] = D_NONE
+ do j = 1, npix
+ if (Memi[buf+j-1] == 0) {
+ lflag[i] = D_MIX
+ break
+ }
+ } else {
+ if (mtype == M_BOOLEAN || mtype == M_BADBITS) {
+ call aclri (Memi[buf], npix)
+ } else if ((mtype == M_BADVAL && mvalue != 0) ||
+ (mtype == M_GOODVAL && mvalue == 0)) {
+ call aclri (Memi[buf], npix)
+ } else {
+ call amovki (1, Memi[buf], npix)
+ lflag[i] = D_NONE
+ }
+ }
+ }
+
+ # Set overall data flag
+ dflag = lflag[1]
+ do i = 2, nimages {
+ if (lflag[i] != dflag) {
+ dflag = D_MIX
+ break
+ }
+ }
+end
+
+
+# IC_MGET1 -- Get line of mask pixels from a specified image.
+# This is used by the IC_STAT procedure. This procedure converts the
+# stored mask format to an array where zero is good and nonzero is bad.
+# The data vector and returned mask array are in the input image pixel system.
+
+procedure ic_mget1 (in, image, offset, v, m)
+
+pointer in # Input image pointer
+int image # Image index
+int offset # Column offset
+long v[IM_MAXDIM] # Data vector desired
+pointer m # Pointer to mask
+
+int i, npix
+pointer buf, pm
+bool pm_linenotempty()
+errchk pm_glpi
+
+include "icmask.com"
+include "icombine.com"
+
+begin
+ dflag = D_ALL
+ if (mtype == M_NONE)
+ return
+
+ npix = IM_LEN(in,1)
+ m = Memi[bufs+image-1] + offset
+ pm = Memi[pms+image-1]
+ if (pm == NULL)
+ return
+
+ # Do mask I/O and convert to appropriate values in order of
+ # expected usage.
+
+ buf = m
+ if (pm_linenotempty (pm, v)) {
+ call pm_glpi (pm, v, Memi[buf], 32, npix, 0)
+
+ if (mtype == M_BOOLEAN)
+ ;
+ else if (mtype == M_BADBITS)
+ call aandki (Memi[buf], mvalue, Memi[buf], npix)
+ else if (mtype == M_BADVAL)
+ call abeqki (Memi[buf], mvalue, Memi[buf], npix)
+ else if (mtype == M_GOODBITS) {
+ call aandki (Memi[buf], mvalue, Memi[buf], npix)
+ call abeqki (Memi[buf], 0, Memi[buf], npix)
+ } else if (mtype == M_GOODVAL)
+ call abneki (Memi[buf], mvalue, Memi[buf], npix)
+
+ dflag = D_NONE
+ do i = 1, npix
+ if (Memi[buf+i-1] == 0) {
+ dflag = D_MIX
+ break
+ }
+ } else {
+ if (mtype == M_BOOLEAN || mtype == M_BADBITS) {
+ ;
+ } else if ((mtype == M_BADVAL && mvalue != 0) ||
+ (mtype == M_GOODVAL && mvalue == 0)) {
+ ;
+ } else
+ dflag = D_NONE
+ }
+end
diff --git a/pkg/obsolete/imcombine/icmedian.gx b/pkg/obsolete/imcombine/icmedian.gx
new file mode 100644
index 00000000..b70f4302
--- /dev/null
+++ b/pkg/obsolete/imcombine/icmedian.gx
@@ -0,0 +1,180 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+$for (sird)
+# IC_MEDIAN -- Median of lines
+
+procedure ic_median$t (d, n, npts, doblank, median)
+
+pointer d[ARB] # Input data line pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+int doblank # Set blank values?
+$if (datatype == sil)
+real median[npts] # Median
+$else
+PIXEL median[npts] # Median
+$endif
+
+int i, j1, j2, j3, k, n1
+bool even
+$if (datatype == silx)
+real val1, val2, val3
+$else
+PIXEL val1, val2, val3
+$endif
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # Check for previous sorting
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ even = (mod (n1, 2) == 0)
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ do i = 1, npts {
+ k = i - 1
+ if (even) {
+ val1 = Mem$t[d[j1]+k]
+ val2 = Mem$t[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Mem$t[d[j1]+k]
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod (n1, 2) == 0) {
+ j2 = n1 / 2
+ val1 = Mem$t[d[j1]+k]
+ val2 = Mem$t[d[j2]+k]
+ median[i] = (val1 + val2) / 2.
+ } else
+ median[i] = Mem$t[d[j1]+k]
+ } else if (doblank == YES)
+ median[i] = blank
+ }
+ }
+ return
+ }
+
+ # Repeatedly exchange the extreme values until there are three
+ # or fewer pixels.
+
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ while (n1 > 3) {
+ j1 = 1
+ j2 = 1
+ $if (datatype == x)
+ val1 = abs (Mem$t[d[j1]+k])
+ $else
+ val1 = Mem$t[d[j1]+k]
+ $endif
+ val2 = val1
+ do j3 = 2, n1 {
+ $if (datatype == x)
+ val3 = abs (Mem$t[d[j3]+k])
+ $else
+ val3 = Mem$t[d[j3]+k]
+ $endif
+ if (val3 > val1) {
+ j1 = j3
+ val1 = val3
+ } else if (val3 < val2) {
+ j2 = j3
+ val2 = val3
+ }
+ }
+ j3 = n1 - 1
+ if (j1 < j3 && j2 < j3) {
+ Mem$t[d[j1]+k] = val3
+ Mem$t[d[j2]+k] = Mem$t[d[j3]+k]
+ Mem$t[d[j3]+k] = val1
+ Mem$t[d[n1]+k] = val2
+ } else if (j1 < j3) {
+ if (j2 == j3) {
+ Mem$t[d[j1]+k] = val3
+ Mem$t[d[n1]+k] = val1
+ } else {
+ Mem$t[d[j1]+k] = Mem$t[d[j3]+k]
+ Mem$t[d[j3]+k] = val1
+ }
+ } else if (j2 < j3) {
+ if (j1 == j3) {
+ Mem$t[d[j2]+k] = val3
+ Mem$t[d[n1]+k] = val2
+ } else {
+ Mem$t[d[j2]+k] = Mem$t[d[j3]+k]
+ Mem$t[d[j3]+k] = val2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ if (n1 == 3) {
+ $if (datatype == x)
+ val1 = abs (Mem$t[d[1]+k])
+ val2 = abs (Mem$t[d[2]+k])
+ val3 = abs (Mem$t[d[3]+k])
+ if (val1 < val2) {
+ if (val2 < val3) # abc
+ median[i] = Mem$t[d[2]+k]
+ else if (val1 < val3) # acb
+ median[i] = Mem$t[d[3]+k]
+ else # cab
+ median[i] = Mem$t[d[1]+k]
+ } else {
+ if (val2 > val3) # cba
+ median[i] = Mem$t[d[2]+k]
+ else if (val1 > val3) # bca
+ median[i] = Mem$t[d[3]+k]
+ else # bac
+ median[i] = Mem$t[d[1]+k]
+ }
+ $else
+ val1 = Mem$t[d[1]+k]
+ val2 = Mem$t[d[2]+k]
+ val3 = Mem$t[d[3]+k]
+ if (val1 < val2) {
+ if (val2 < val3) # abc
+ median[i] = val2
+ else if (val1 < val3) # acb
+ median[i] = val3
+ else # cab
+ median[i] = val1
+ } else {
+ if (val2 > val3) # cba
+ median[i] = val2
+ else if (val1 > val3) # bca
+ median[i] = val3
+ else # bac
+ median[i] = val1
+ }
+ $endif
+ } else if (n1 == 2) {
+ val1 = Mem$t[d[1]+k]
+ val2 = Mem$t[d[2]+k]
+ median[i] = (val1 + val2) / 2
+ } else if (n1 == 1)
+ median[i] = Mem$t[d[1]+k]
+ else if (doblank == YES)
+ median[i] = blank
+ }
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icmm.gx b/pkg/obsolete/imcombine/icmm.gx
new file mode 100644
index 00000000..10236b92
--- /dev/null
+++ b/pkg/obsolete/imcombine/icmm.gx
@@ -0,0 +1,181 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+$for (sird)
+# IC_MM -- Reject a specified number of high and low pixels
+
+procedure ic_mm$t (d, m, n, npts)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of good pixels
+int npts # Number of output points per line
+
+int n1, ncombine, npairs, nlow, nhigh, np
+int i, i1, j, jmax, jmin
+pointer k, kmax, kmin
+PIXEL d1, d2, dmin, dmax
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_NONE)
+ return
+
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = n1 - nlow - nhigh
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ do i = 1, npts {
+ i1 = i - 1
+ n1 = n[i]
+ if (dflag == D_MIX) {
+ nlow = flow * n1 + 0.001
+ nhigh = fhigh * n1 + 0.001
+ ncombine = max (ncombine, n1 - nlow - nhigh)
+ npairs = min (nlow, nhigh)
+ nlow = nlow - npairs
+ nhigh = nhigh - npairs
+ }
+
+ # Reject the npairs low and high points.
+ do np = 1, npairs {
+ k = d[1] + i1
+ $if (datatype == x)
+ d1 = abs (Mem$t[k])
+ $else
+ d1 = Mem$t[k]
+ $endif
+ dmax = d1; dmin = d1; jmax = 1; jmin = 1; kmax = k; kmin = k
+ do j = 2, n1 {
+ d2 = d1
+ k = d[j] + i1
+ $if (datatype == x)
+ d1 = abs (Mem$t[k])
+ $else
+ d1 = Mem$t[k]
+ $endif
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ } else if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ j = n1 - 1
+ if (keepids) {
+ if (jmax < j) {
+ if (jmin != j) {
+ Mem$t[kmax] = d2
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ } else {
+ Mem$t[kmax] = d1
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Mem$t[kmin] = d1
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ } else {
+ Mem$t[kmin] = d2
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ }
+ }
+ } else {
+ if (jmax < j) {
+ if (jmin != j)
+ Mem$t[kmax] = d2
+ else
+ Mem$t[kmax] = d1
+ }
+ if (jmin < j) {
+ if (jmax != n1)
+ Mem$t[kmin] = d1
+ else
+ Mem$t[kmin] = d2
+ }
+ }
+ n1 = n1 - 2
+ }
+
+ # Reject the excess low points.
+ do np = 1, nlow {
+ k = d[1] + i1
+ $if (datatype == x)
+ d1 = abs (Mem$t[k])
+ $else
+ d1 = Mem$t[k]
+ $endif
+ dmin = d1; jmin = 1; kmin = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ $if (datatype == x)
+ d1 = abs (Mem$t[k])
+ $else
+ d1 = Mem$t[k]
+ $endif
+ if (d1 < dmin) {
+ dmin = d1; jmin = j; kmin = k
+ }
+ }
+ if (keepids) {
+ if (jmin < n1) {
+ Mem$t[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmin < n1)
+ Mem$t[kmin] = d1
+ }
+ n1 = n1 - 1
+ }
+
+ # Reject the excess high points.
+ do np = 1, nhigh {
+ k = d[1] + i1
+ $if (datatype == x)
+ d1 = abs (Mem$t[k])
+ $else
+ d1 = Mem$t[k]
+ $endif
+ dmax = d1; jmax = 1; kmax = k
+ do j = 2, n1 {
+ k = d[j] + i1
+ $if (datatype == x)
+ d1 = abs (Mem$t[k])
+ $else
+ d1 = Mem$t[k]
+ $endif
+ if (d1 > dmax) {
+ dmax = d1; jmax = j; kmax = k
+ }
+ }
+ if (keepids) {
+ if (jmax < n1) {
+ Mem$t[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ } else {
+ if (jmax < n1)
+ Mem$t[kmax] = d1
+ }
+ n1 = n1 - 1
+ }
+ n[i] = n1
+ }
+
+ if (dflag == D_ALL && npairs + nlow + nhigh > 0)
+ dflag = D_MIX
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icombine.com b/pkg/obsolete/imcombine/icombine.com
new file mode 100644
index 00000000..f0d3b467
--- /dev/null
+++ b/pkg/obsolete/imcombine/icombine.com
@@ -0,0 +1,38 @@
+# ICOMBINE Common
+
+int combine # Combine algorithm
+int reject # Rejection algorithm
+bool project # Combine across the highest dimension?
+real blank # Blank value
+pointer rdnoise # CCD read noise
+pointer gain # CCD gain
+pointer snoise # CCD sensitivity noise
+real lthresh # Low threshold
+real hthresh # High threshold
+int nkeep # Minimum to keep
+real lsigma # Low sigma cutoff
+real hsigma # High sigma cutoff
+real pclip # Number or fraction of pixels from median
+real flow # Fraction of low pixels to reject
+real fhigh # Fraction of high pixels to reject
+real grow # Grow radius
+bool mclip # Use median in sigma clipping?
+real sigscale # Sigma scaling tolerance
+int logfd # Log file descriptor
+
+# These flags allow special conditions to be optimized.
+
+int dflag # Data flag (D_ALL, D_NONE, D_MIX)
+bool aligned # Are the images aligned?
+bool doscale # Do the images have to be scaled?
+bool doscale1 # Do the sigma calculations have to be scaled?
+bool dothresh # Check pixels outside specified thresholds?
+bool dowts # Does the final average have to be weighted?
+bool keepids # Keep track of the image indices?
+bool docombine # Call the combine procedure?
+bool sort # Sort data?
+
+common /imccom/ combine, reject, blank, rdnoise, gain, snoise, lsigma, hsigma,
+ lthresh, hthresh, nkeep, pclip, flow, fhigh, grow, logfd,
+ dflag, sigscale, project, mclip, aligned, doscale, doscale1,
+ dothresh, dowts, keepids, docombine, sort
diff --git a/pkg/obsolete/imcombine/icombine.gx b/pkg/obsolete/imcombine/icombine.gx
new file mode 100644
index 00000000..9cb4cb24
--- /dev/null
+++ b/pkg/obsolete/imcombine/icombine.gx
@@ -0,0 +1,580 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <imset.h>
+include <pmset.h>
+include <error.h>
+include <syserr.h>
+include <mach.h>
+include "../icombine.h"
+
+
+# ICOMBINE -- Combine images
+#
+# The memory and open file descriptor limits are checked and an attempt
+# to recover is made either by setting the image pixel files to be
+# closed after I/O or by notifying the calling program that memory
+# ran out and the IMIO buffer size should be reduced. After the checks
+# a procedure for the selected combine option is called.
+# Because there may be several failure modes when reaching the file
+# limits we first assume an error is due to the file limit, except for
+# out of memory, and close some pixel files. If the error then repeats
+# on accessing the pixels the error is passed back.
+
+$for (sird)
+procedure icombine$t (in, out, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output images
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, npts, fd, stropen(), errcode(), imstati()
+pointer sp, d, id, n, m, lflag, scales, zeros, wts, dbuf
+pointer buf, imgl1$t(), impl1i()
+errchk stropen, imgl1$t, impl1i
+$if (datatype == sil)
+pointer impl1r()
+errchk impl1r
+$else
+pointer impl1$t()
+errchk impl1$t
+$endif
+
+include "../icombine.com"
+
+begin
+ npts = IM_LEN(out[1],1)
+
+ # Allocate memory.
+ call smark (sp)
+ call salloc (dbuf, nimages, TY_POINTER)
+ call salloc (d, nimages, TY_POINTER)
+ call salloc (id, nimages, TY_POINTER)
+ call salloc (n, npts, TY_INT)
+ call salloc (m, nimages, TY_POINTER)
+ call salloc (lflag, nimages, TY_INT)
+ call salloc (scales, nimages, TY_REAL)
+ call salloc (zeros, nimages, TY_REAL)
+ call salloc (wts, nimages, TY_REAL)
+ call amovki (D_ALL, Memi[lflag], nimages)
+
+ # If not aligned or growing create data buffers of output length
+ # otherwise use the IMIO buffers.
+
+ if (!aligned || grow >= 1.) {
+ do i = 1, nimages
+ call salloc (Memi[dbuf+i-1], npts, TY_PIXEL)
+ } else
+ call amovki (NULL, Memi[dbuf], nimages)
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ } else {
+ # Reserve FD for string operations.
+ fd = stropen (str, 1, NEW_FILE)
+
+ # Do I/O to the images.
+ do i = 1, 3 {
+ if (out[i] != NULL)
+ call imseti (out[i], IM_BUFSIZE, bufsize)
+ }
+ $if (datatype == sil)
+ buf = impl1r (out[1])
+ call aclrr (Memr[buf], npts)
+ if (out[3] != NULL) {
+ buf = impl1r (out[3])
+ call aclrr (Memr[buf], npts)
+ }
+ $else
+ buf = impl1$t (out[1])
+ call aclr$t (Mem$t[buf], npts)
+ if (out[3] != NULL) {
+ buf = impl1$t (out[3])
+ call aclr$t (Mem$t[buf], npts)
+ }
+ $endif
+ if (out[2] != NULL) {
+ buf = impl1i (out[2])
+ call aclri (Memi[buf], npts)
+ }
+
+ do i = 1, nimages {
+ call imseti (in[i], IM_BUFSIZE, bufsize)
+ iferr (buf = imgl1$t (in[i])) {
+ switch (errcode()) {
+ case SYS_MFULL:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ case SYS_FTOOMANYFILES, SYS_IKIOPIX:
+ if (imstati (in[i], IM_CLOSEFD) == YES) {
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ do j = i-2, nimages
+ call imseti (in[j], IM_CLOSEFD, YES)
+ buf = imgl1$t (in[i])
+ default:
+ call sfree (sp)
+ call strclose (fd)
+ call erract (EA_ERROR)
+ }
+ }
+ }
+
+ call strclose (fd)
+ }
+
+ call ic_combine$t (in, out, Memi[dbuf], Memi[d], Memi[id], Memi[n],
+ Memi[m], Memi[lflag], offsets, Memr[scales], Memr[zeros],
+ Memr[wts], nimages, npts)
+end
+
+
+# IC_COMBINE -- Combine images.
+
+procedure ic_combine$t (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, wts, nimages, npts)
+
+pointer in[nimages] # Input images
+pointer out[4] # Output image
+pointer dbuf[nimages] # Data buffers for nonaligned images
+pointer d[nimages] # Data pointers
+pointer id[nimages] # Image index ID pointers
+int n[npts] # Number of good pixels
+pointer m[nimages] # Mask pointers
+int lflag[nimages] # Line flags
+int offsets[nimages,ARB] # Input image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero offset factors
+real wts[nimages] # Combining weights
+int nimages # Number of input images
+int npts # Number of points per output line
+
+int i, ext, ctor(), ic_qsort(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nm, pms
+pointer immap(), impnli()
+$if (datatype == sil)
+pointer impnlr(), imgnlr()
+$else
+pointer impnl$t(), imgnl$t
+$endif
+errchk immap, ic_scale, imgetr, ic_grow, ic_grow$t, ic_rmasks
+extern ic_qsort
+
+include "../icombine.com"
+data ext/0/
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (imname, SZ_FNAME, TY_CHAR)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (v3, IM_MAXDIM, TY_LONG)
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+
+ call ic_scale (in, out, offsets, scales, zeros, wts, nimages)
+
+ # Set combine parameters
+ switch (combine) {
+ case AVERAGE:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Set rejection algorithm specific parameters
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ call salloc (nm, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nm+3*(i-1)+1] = r
+ Memr[nm+3*(i-1)] =
+ max ((Memr[nm+3*(i-1)] / r) ** 2, 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nm+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nm+3*(i-1)+2] = r
+ }
+ }
+ if (!keepids) {
+ if (doscale1)
+ keepids = true
+ else {
+ do i = 2, nimages {
+ if (Memr[nm+3*(i-1)] != Memr[nm] ||
+ Memr[nm+3*(i-1)+1] != Memr[nm+1] ||
+ Memr[nm+3*(i-1)+2] != Memr[nm+2]) {
+ keepids = true
+ break
+ }
+ }
+ }
+ }
+ if (reject == CRREJECT)
+ lsigma = MAX_REAL
+ case MINMAX:
+ mclip = false
+ case PCLIP:
+ mclip = true
+ case AVSIGCLIP, SIGCLIP:
+ if (doscale1)
+ keepids = true
+ case NONE:
+ mclip = false
+ }
+
+ if (out[4] != NULL)
+ keepids = true
+
+ if (grow >= 1.) {
+ keepids = true
+ call salloc (work, npts * nimages, TY_INT)
+ }
+ pms = NULL
+
+ if (keepids) {
+ do i = 1, nimages
+ call salloc (id[i], npts, TY_INT)
+ }
+
+ $if (datatype == sil)
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdata$t (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ if (mclip)
+ call ic_mccdclip$t (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ else
+ call ic_accdclip$t (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Memr[outdata])
+ case MINMAX:
+ call ic_mm$t (d, id, n, npts)
+ case PCLIP:
+ call ic_pclip$t (d, id, n, nimages, npts, Memr[outdata])
+ case SIGCLIP:
+ if (mclip)
+ call ic_msigclip$t (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ else
+ call ic_asigclip$t (d, id, n, scales, zeros, nimages, npts,
+ Memr[outdata])
+ case AVSIGCLIP:
+ if (mclip)
+ call ic_mavsigclip$t (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ else
+ call ic_aavsigclip$t (d, id, n, scales, zeros, nimages,
+ npts, Memr[outdata])
+ }
+
+ if (pms == NULL || nkeep > 0) {
+ if (docombine) {
+ switch (combine) {
+ case AVERAGE:
+ call ic_average$t (d, id, n, wts, npts, YES,
+ Memr[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, YES, Memr[outdata])
+ }
+ }
+ }
+
+ if (grow >= 1.)
+ call ic_grow (out, Meml[v2], id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (pms == NULL) {
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigma$t (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+ }
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+ $else
+ while (impnl$t (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdata$t (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ switch (reject) {
+ case CCDCLIP, CRREJECT:
+ if (mclip)
+ call ic_mccdclip$t (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Mem$t[outdata])
+ else
+ call ic_accdclip$t (d, id, n, scales, zeros, Memr[nm],
+ nimages, npts, Mem$t[outdata])
+ case MINMAX:
+ call ic_mm$t (d, id, n, npts)
+ case PCLIP:
+ call ic_pclip$t (d, id, n, nimages, npts, Mem$t[outdata])
+ case SIGCLIP:
+ if (mclip)
+ call ic_msigclip$t (d, id, n, scales, zeros, nimages, npts,
+ Mem$t[outdata])
+ else
+ call ic_asigclip$t (d, id, n, scales, zeros, nimages, npts,
+ Mem$t[outdata])
+ case AVSIGCLIP:
+ if (mclip)
+ call ic_mavsigclip$t (d, id, n, scales, zeros, nimages,
+ npts, Mem$t[outdata])
+ else
+ call ic_aavsigclip$t (d, id, n, scales, zeros, nimages,
+ npts, Mem$t[outdata])
+ }
+
+ if (pms == NULL || nkeep > 0) {
+ if (docombine) {
+ switch (combine) {
+ case AVERAGE:
+ call ic_average$t (d, id, n, wts, npts, YES,
+ Mem$t[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, YES, Mem$t[outdata])
+ }
+ }
+ }
+
+ if (grow >= 1.)
+ call ic_grow (out, Meml[v2], id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (pms == NULL) {
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnl$t (out[3], buf, Meml[v1])
+ call ic_sigma$t (d, id, n, wts, npts, Mem$t[outdata],
+ Mem$t[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+ }
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+ $endif
+
+ if (pms != NULL) {
+ if (nkeep > 0) {
+ call imstats (out[1], IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call imunmap (out[1])
+ iferr (buf = immap (Memc[fname], READ_WRITE, 0)) {
+ switch (errcode()) {
+ case SYS_FXFOPNOEXTNV:
+ call imgcluster (Memc[fname], Memc[fname], SZ_FNAME)
+ ext = ext + 1
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext)
+ iferr (buf = immap (Memc[imname], READ_WRITE, 0)) {
+ buf = NULL
+ ext = 0
+ }
+ repeat {
+ call sprintf (Memc[imname], SZ_FNAME, "%s[%d]")
+ call pargstr (Memc[fname])
+ call pargi (ext+1)
+ iferr (outdata = immap (Memc[imname],READ_WRITE,0))
+ break
+ if (buf != NULL)
+ call imunmap (buf)
+ buf = outdata
+ ext = ext + 1
+ }
+ default:
+ call erract (EA_ERROR)
+ }
+ }
+ out[1] = buf
+ }
+
+ call amovkl (long(1), Meml[v1], IM_MAXDIM)
+ call amovkl (long(1), Meml[v2], IM_MAXDIM)
+ call amovkl (long(1), Meml[v3], IM_MAXDIM)
+ $if (datatype == sil)
+ while (impnlr (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdata$t (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ call ic_grow$t (Meml[v2], d, id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (nkeep > 0) {
+ do i = 1, npts {
+ if (n[i] < nkeep) {
+ Meml[v1+1] = Meml[v1+1] - 1
+ if (imgnlr (out[1], buf, Meml[v1]) == EOF)
+ ;
+ call amovr (Memr[buf], Memr[outdata], npts)
+ break
+ }
+ }
+ }
+
+ switch (combine) {
+ case AVERAGE:
+ call ic_average$t (d, id, n, wts, npts, NO, Memr[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, NO, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnlr (out[3], buf, Meml[v1])
+ call ic_sigma$t (d, id, n, wts, npts, Memr[outdata],
+ Memr[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+ $else
+ while (impnl$t (out[1], outdata, Meml[v1]) != EOF) {
+ call ic_gdata$t (in, out, dbuf, d, id, n, m, lflag, offsets,
+ scales, zeros, nimages, npts, Meml[v2], Meml[v3])
+
+ call ic_grow$t (Meml[v2], d, id, n, Memi[work], nimages, npts,
+ pms)
+
+ if (nkeep > 0) {
+ do i = 1, npts {
+ if (n[i] < nkeep) {
+ Meml[v1+1] = Meml[v1+1] - 1
+ if (imgnl$t (out[1], buf, Meml[v1]) == EOF)
+ ;
+ call amov$t (Mem$t[buf], Mem$t[outdata], npts)
+ break
+ }
+ }
+ }
+
+ switch (combine) {
+ case AVERAGE:
+ call ic_average$t (d, id, n, wts, npts, NO, Mem$t[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, NO, Mem$t[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[3] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnl$t (out[3], buf, Meml[v1])
+ call ic_sigma$t (d, id, n, wts, npts, Mem$t[outdata],
+ Mem$t[buf])
+ }
+
+ if (out[4] != NULL)
+ call ic_rmasks (out[4], Meml[v2], id, nimages, n, npts)
+
+ call amovl (Meml[v1], Meml[v2], IM_MAXDIM)
+ }
+ $endif
+
+ do i = 1, nimages
+ call pm_close (Memi[pms+i-1])
+ call mfree (pms, TY_POINTER)
+ }
+
+ call sfree (sp)
+end
+$endfor
+
+
+# IC_QSORT -- Compare line numbers for GQSORT.
+
+int procedure ic_qsort (arg, i1, i2)
+
+pointer arg
+int i1, i2
+
+begin
+ if (Mems[arg+i1-1] < Mems[arg+i2-1])
+ return (-1)
+ else if (Mems[arg+i1-1] > Mems[arg+i2-1])
+ return (1)
+ else
+ return (0)
+end
diff --git a/pkg/obsolete/imcombine/icombine.h b/pkg/obsolete/imcombine/icombine.h
new file mode 100644
index 00000000..13b77117
--- /dev/null
+++ b/pkg/obsolete/imcombine/icombine.h
@@ -0,0 +1,52 @@
+# ICOMBINE Definitions
+
+# Memory management parameters;
+define DEFBUFSIZE 65536 # default IMIO buffer size
+define FUDGE 0.8 # fudge factor
+
+# Rejection options:
+define REJECT "|none|ccdclip|crreject|minmax|pclip|sigclip|avsigclip|"
+define NONE 1 # No rejection algorithm
+define CCDCLIP 2 # CCD noise function clipping
+define CRREJECT 3 # CCD noise function clipping
+define MINMAX 4 # Minmax rejection
+define PCLIP 5 # Percentile clip
+define SIGCLIP 6 # Sigma clip
+define AVSIGCLIP 7 # Sigma clip with average poisson sigma
+
+# Combine options:
+define COMBINE "|average|median|"
+define AVERAGE 1
+define MEDIAN 2
+
+# Scaling options:
+define STYPES "|none|mode|median|mean|exposure|"
+define ZTYPES "|none|mode|median|mean|"
+define WTYPES "|none|mode|median|mean|exposure|"
+define S_NONE 1
+define S_MODE 2
+define S_MEDIAN 3
+define S_MEAN 4
+define S_EXPOSURE 5
+define S_FILE 6
+define S_KEYWORD 7
+define S_SECTION "|input|output|overlap|"
+define S_INPUT 1
+define S_OUTPUT 2
+define S_OVERLAP 3
+
+# Mask options
+define MASKTYPES "|none|goodvalue|badvalue|goodbits|badbits|"
+define M_NONE 1 # Don't use mask images
+define M_GOODVAL 2 # Value selecting good pixels
+define M_BADVAL 3 # Value selecting bad pixels
+define M_GOODBITS 4 # Bits selecting good pixels
+define M_BADBITS 5 # Bits selecting bad pixels
+define M_BOOLEAN -1 # Ignore mask values
+
+# Data flag
+define D_ALL 0 # All pixels are good
+define D_NONE 1 # All pixels are bad or rejected
+define D_MIX 2 # Mixture of good and bad pixels
+
+define TOL 0.001 # Tolerance for equal residuals
diff --git a/pkg/obsolete/imcombine/icpclip.gx b/pkg/obsolete/imcombine/icpclip.gx
new file mode 100644
index 00000000..f0c76369
--- /dev/null
+++ b/pkg/obsolete/imcombine/icpclip.gx
@@ -0,0 +1,233 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 3 # Minimum number for clipping
+
+$for (sird)
+# IC_PCLIP -- Percentile clip
+#
+# 1) Find the median
+# 2) Find the pixel which is the specified order index away
+# 3) Use the data value difference as a sigma and apply clipping
+# 4) Since the median is known return it so it does not have to be recomputed
+
+procedure ic_pclip$t (d, m, n, nimages, npts, median)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image id pointers
+int n[npts] # Number of good pixels
+int nimages # Number of input images
+int npts # Number of output points per line
+$if (datatype == sil)
+real median[npts] # Median
+$else
+PIXEL median[npts] # Median
+$endif
+
+int i, j, k, l, id, n1, n2, n3, n4, n5, nl, nh, nin, maxkeep
+bool even, fp_equalr()
+real sigma, r, s, t
+pointer sp, resid, mp1, mp2
+$if (datatype == sil)
+real med
+$else
+PIXEL med
+$endif
+
+include "../icombine.com"
+
+begin
+ # There must be at least MINCLIP and more than nkeep pixels.
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+
+ # Set sign of pclip parameter
+ if (pclip < 0)
+ t = -1.
+ else
+ t = 1.
+
+ # If there are no rejected pixels compute certain parameters once.
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0.) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ nin = n1
+ }
+
+ # Now apply clipping.
+ do i = 1, npts {
+ # Compute median.
+ if (dflag == D_MIX) {
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ if (n1 == 0) {
+ if (combine == MEDIAN)
+ median[i] = blank
+ next
+ }
+ n2 = 1 + n1 / 2
+ even = (mod (n1, 2) == 0)
+ if (pclip < 0) {
+ if (even)
+ n3 = max (1, nint (n2 - 1 + pclip))
+ else
+ n3 = max (1, nint (n2 + pclip))
+ } else
+ n3 = min (n1, nint (n2 + pclip))
+ }
+
+ j = i - 1
+ if (even) {
+ med = Mem$t[d[n2-1]+j]
+ med = (med + Mem$t[d[n2]+j]) / 2.
+ } else
+ med = Mem$t[d[n2]+j]
+
+ if (n1 < max (MINCLIP, maxkeep+1)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Define sigma for clipping
+ sigma = t * (Mem$t[d[n3]+j] - med)
+ if (fp_equalr (sigma, 0.)) {
+ if (combine == MEDIAN)
+ median[i] = med
+ next
+ }
+
+ # Reject pixels and save residuals.
+ # Check if any pixels are clipped.
+ # If so recompute the median and reset the number of good pixels.
+ # Only reorder if needed.
+
+ for (nl=1; nl<=n1; nl=nl+1) {
+ r = (med - Mem$t[d[nl]+j]) / sigma
+ if (r < lsigma)
+ break
+ Memr[resid+nl] = r
+ }
+ for (nh=n1; nh>=1; nh=nh-1) {
+ r = (Mem$t[d[nh]+j] - med) / sigma
+ if (r < hsigma)
+ break
+ Memr[resid+nh] = r
+ }
+ n4 = nh - nl + 1
+
+ # If too many pixels are rejected add some back in.
+ # All pixels with the same residual are added.
+ while (n4 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n4 = nh - nl + 1
+ }
+
+ # If any pixels are rejected recompute the median.
+ if (nl > 1 || nh < n1) {
+ n5 = nl + n4 / 2
+ if (mod (n4, 2) == 0) {
+ med = Mem$t[d[n5-1]+j]
+ med = (med + Mem$t[d[n5]+j]) / 2.
+ } else
+ med = Mem$t[d[n5]+j]
+ n[i] = n4
+ }
+ if (combine == MEDIAN)
+ median[i] = med
+
+ # Reorder if pixels only if necessary.
+ if (nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ k = max (nl, n4 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mem$t[d[l]+j] = Mem$t[d[k]+j]
+ if (grow >= 1.) {
+ mp1 = m[l] + j
+ mp2 = m[k] + j
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+j] = Memi[m[k]+j]
+ k = k + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mem$t[d[l]+j] = Mem$t[d[k]+j]
+ k = k + 1
+ }
+ }
+ }
+ }
+
+ # Check if data flag needs to be reset for rejected pixels.
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag whether the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icrmasks.x b/pkg/obsolete/imcombine/icrmasks.x
new file mode 100644
index 00000000..8b9a0c3d
--- /dev/null
+++ b/pkg/obsolete/imcombine/icrmasks.x
@@ -0,0 +1,41 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+
+
+# IC_RMASKS -- Set pixels for rejection mask.
+
+procedure ic_rmasks (pm, v, id, nimages, n, npts)
+
+pointer pm #I Pixel mask
+long v[ARB] #I Output vector (input)
+pointer id[nimages] #I Image id pointers
+int nimages #I Number of images
+int n[npts] #I Number of good pixels
+int npts #I Number of output points per line
+
+int i, j, k, ndim, impnls()
+long v1[IM_MAXDIM]
+pointer buf
+
+begin
+ ndim = IM_NDIM(pm)
+ do k = 1, nimages {
+ call amovl (v, v1, ndim-1)
+ v1[ndim] = k
+ i = impnls (pm, buf, v1)
+ do j = 1, npts {
+ if (n[j] == nimages)
+ Mems[buf+j-1] = 0
+ else {
+ Mems[buf+j-1] = 1
+ do i = 1, n[j] {
+ if (Memi[id[i]+j-1] == k) {
+ Mems[buf+j-1] = 0
+ break
+ }
+ }
+ }
+ }
+ }
+end
diff --git a/pkg/obsolete/imcombine/icscale.x b/pkg/obsolete/imcombine/icscale.x
new file mode 100644
index 00000000..5f4194e6
--- /dev/null
+++ b/pkg/obsolete/imcombine/icscale.x
@@ -0,0 +1,358 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <imset.h>
+include <error.h>
+include "icombine.h"
+
+# IC_SCALE -- Get the scale factors for the images.
+# 1. This procedure does CLIO to determine the type of scaling desired.
+# 2. The output header parameters for exposure time and NCOMBINE are set.
+
+procedure ic_scale (in, out, offsets, scales, zeros, wts, nimages)
+
+pointer in[nimages] # Input images
+pointer out[3] # Output images
+int offsets[nimages,ARB] # Image offsets
+real scales[nimages] # Scale factors
+real zeros[nimages] # Zero or sky levels
+real wts[nimages] # Weights
+int nimages # Number of images
+
+int stype, ztype, wtype
+int i, j, k, l, nout
+real mode, median, mean, exposure, zmean
+pointer sp, ncombine, exptime, modes, medians, means, expname
+pointer section, str, sname, zname, wname, imref
+bool domode, domedian, domean, dozero, snorm, znorm, wflag
+
+int imgeti(), strdic(), ic_gscale()
+real imgetr(), asumr(), asumi()
+errchk ic_gscale, ic_statr
+
+include "icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (ncombine, nimages, TY_INT)
+ call salloc (exptime, nimages, TY_REAL)
+ call salloc (modes, nimages, TY_REAL)
+ call salloc (medians, nimages, TY_REAL)
+ call salloc (means, nimages, TY_REAL)
+ call salloc (expname, SZ_FNAME, TY_CHAR)
+ call salloc (section, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (sname, SZ_FNAME, TY_CHAR)
+ call salloc (zname, SZ_FNAME, TY_CHAR)
+ call salloc (wname, SZ_FNAME, TY_CHAR)
+
+ # Set the defaults.
+ call amovki (1, Memi[ncombine], nimages)
+ call amovkr (0., Memr[exptime], nimages)
+ call amovkr (INDEF, Memr[modes], nimages)
+ call amovkr (INDEF, Memr[medians], nimages)
+ call amovkr (INDEF, Memr[means], nimages)
+ call amovkr (1., scales, nimages)
+ call amovkr (0., zeros, nimages)
+ call amovkr (1., wts, nimages)
+
+ # Get the number of images previously combined and the exposure times.
+ # The default combine number is 1 and the default exposure is 0.
+
+ call clgstr ("expname", Memc[expname], SZ_FNAME)
+ do i = 1, nimages {
+ iferr (Memi[ncombine+i-1] = imgeti (in[i], "ncombine"))
+ Memi[ncombine+i-1] = 1
+ if (Memc[expname] != EOS) {
+ iferr (Memr[exptime+i-1] = imgetr (in[i], Memc[expname]))
+ Memr[exptime+i-1] = 0.
+ }
+ if (project) {
+ call amovki (Memi[ncombine], Memi[ncombine], nimages)
+ call amovkr (Memr[exptime], Memr[exptime], nimages)
+ break
+ }
+ }
+
+ # Set scaling factors.
+
+ stype = ic_gscale ("scale", Memc[sname], STYPES, in, Memr[exptime],
+ scales, nimages)
+ ztype = ic_gscale ("zero", Memc[zname], ZTYPES, in, Memr[exptime],
+ zeros, nimages)
+ wtype = ic_gscale ("weight", Memc[wname], WTYPES, in, Memr[exptime],
+ wts, nimages)
+
+ # Get image statistics only if needed.
+ domode = ((stype==S_MODE)||(ztype==S_MODE)||(wtype==S_MODE))
+ domedian = ((stype==S_MEDIAN)||(ztype==S_MEDIAN)||(wtype==S_MEDIAN))
+ domean = ((stype==S_MEAN)||(ztype==S_MEAN)||(wtype==S_MEAN))
+ if (domode || domedian || domean) {
+ Memc[section] = EOS
+ Memc[str] = EOS
+ call clgstr ("statsec", Memc[section], SZ_FNAME)
+ call sscan (Memc[section])
+ call gargwrd (Memc[section], SZ_FNAME)
+ call gargwrd (Memc[str], SZ_LINE)
+
+ i = strdic (Memc[section], Memc[section], SZ_FNAME, S_SECTION)
+ switch (i) {
+ case S_INPUT:
+ call strcpy (Memc[str], Memc[section], SZ_FNAME)
+ imref = NULL
+ case S_OUTPUT:
+ call strcpy (Memc[str], Memc[section], SZ_FNAME)
+ imref = out[1]
+ case S_OVERLAP:
+ call strcpy ("[", Memc[section], SZ_FNAME)
+ do i = 1, IM_NDIM(out[1]) {
+ k = offsets[1,i] + 1
+ l = offsets[1,i] + IM_LEN(in[1],i)
+ do j = 2, nimages {
+ k = max (k, offsets[j,i]+1)
+ l = min (l, offsets[j,i]+IM_LEN(in[j],i))
+ }
+ if (i < IM_NDIM(out[1]))
+ call sprintf (Memc[str], SZ_LINE, "%d:%d,")
+ else
+ call sprintf (Memc[str], SZ_LINE, "%d:%d]")
+ call pargi (k)
+ call pargi (l)
+ call strcat (Memc[str], Memc[section], SZ_FNAME)
+ }
+ imref = out[1]
+ default:
+ imref = NULL
+ }
+
+ do i = 1, nimages {
+ if (imref != out[1])
+ imref = in[i]
+ call ic_statr (in[i], imref, Memc[section], offsets,
+ i, nimages, domode, domedian, domean, mode, median, mean)
+ if (domode) {
+ Memr[modes+i-1] = mode
+ if (stype == S_MODE)
+ scales[i] = mode
+ if (ztype == S_MODE)
+ zeros[i] = mode
+ if (wtype == S_MODE)
+ wts[i] = mode
+ }
+ if (domedian) {
+ Memr[medians+i-1] = median
+ if (stype == S_MEDIAN)
+ scales[i] = median
+ if (ztype == S_MEDIAN)
+ zeros[i] = median
+ if (wtype == S_MEDIAN)
+ wts[i] = median
+ }
+ if (domean) {
+ Memr[means+i-1] = mean
+ if (stype == S_MEAN)
+ scales[i] = mean
+ if (ztype == S_MEAN)
+ zeros[i] = mean
+ if (wtype == S_MEAN)
+ wts[i] = mean
+ }
+ }
+ }
+
+ do i = 1, nimages
+ if (scales[i] <= 0.) {
+ call eprintf ("WARNING: Negative scale factors")
+ call eprintf (" -- ignoring scaling\n")
+ call amovkr (1., scales, nimages)
+ break
+ }
+
+ # Convert to relative factors if needed.
+ snorm = (stype == S_FILE || stype == S_KEYWORD)
+ znorm = (ztype == S_FILE || ztype == S_KEYWORD)
+ wflag = (wtype == S_FILE || wtype == S_KEYWORD)
+ if (snorm)
+ call arcpr (1., scales, scales, nimages)
+ else {
+ mean = asumr (scales, nimages) / nimages
+ call adivkr (scales, mean, scales, nimages)
+ }
+ call adivr (zeros, scales, zeros, nimages)
+ zmean = asumr (zeros, nimages) / nimages
+
+ if (wtype != S_NONE) {
+ do i = 1, nimages {
+ if (wts[i] <= 0.) {
+ call eprintf ("WARNING: Negative weights")
+ call eprintf (" -- using only NCOMBINE weights\n")
+ do j = 1, nimages
+ wts[j] = Memi[ncombine+j-1]
+ break
+ }
+ if (ztype == S_NONE || znorm || wflag)
+ wts[i] = Memi[ncombine+i-1] * wts[i]
+ else {
+ if (zeros[i] <= 0.) {
+ call eprintf ("WARNING: Negative zero offsets")
+ call eprintf (" -- ignoring zero weight adjustments\n")
+ do j = 1, nimages
+ wts[j] = Memi[ncombine+j-1] * wts[j]
+ break
+ }
+ wts[i] = Memi[ncombine+i-1] * wts[i] * zmean / zeros[i]
+ }
+ }
+ }
+
+ if (znorm)
+ call anegr (zeros, zeros, nimages)
+ else {
+ # Because of finite arithmetic it is possible for the zero offsets
+ # to be nonzero even when they are all equal. Just for the sake of
+ # a nice log set the zero offsets in this case.
+
+ call asubkr (zeros, zmean, zeros, nimages)
+ for (i=2; (i<=nimages)&&(zeros[i]==zeros[1]); i=i+1)
+ ;
+ if (i > nimages)
+ call aclrr (zeros, nimages)
+ }
+ mean = asumr (wts, nimages)
+ call adivkr (wts, mean, wts, nimages)
+
+ # Set flags for scaling, zero offsets, sigma scaling, weights.
+ # Sigma scaling may be suppressed if the scales or zeros are
+ # different by a specified tolerance.
+
+ doscale = false
+ dozero = false
+ doscale1 = false
+ dowts = false
+ do i = 2, nimages {
+ if (snorm || scales[i] != scales[1])
+ doscale = true
+ if (znorm || zeros[i] != zeros[1])
+ dozero = true
+ if (wts[i] != wts[1])
+ dowts = true
+ }
+ if (doscale && sigscale != 0.) {
+ do i = 1, nimages {
+ if (abs (scales[i] - 1) > sigscale) {
+ doscale1 = true
+ break
+ }
+ }
+ if (!doscale1 && zmean > 0) {
+ do i = 1, nimages {
+ if (abs (zeros[i] / zmean) > sigscale) {
+ doscale1 = true
+ break
+ }
+ }
+ }
+ }
+
+ # Set the output header parameters.
+ nout = asumi (Memi[ncombine], nimages)
+ call imaddi (out[1], "ncombine", nout)
+ if (Memc[expname] != EOS) {
+ exposure = 0.
+ do i = 1, nimages
+ exposure = exposure + wts[i] * Memr[exptime+i-1] / scales[i]
+ call imaddr (out[1], Memc[expname], exposure)
+ } else
+ exposure = INDEF
+ if (out[2] != NULL) {
+ call imstats (out[2], IM_IMAGENAME, Memc[str], SZ_FNAME)
+ call imastr (out[1], "BPM", Memc[str])
+ }
+ ifnoerr (mode = imgetr (out[1], "CCDMEAN"))
+ call imdelf (out[1], "CCDMEAN")
+
+ # Start the log here since much of the info is only available here.
+ call ic_log (in, out, Memi[ncombine], Memr[exptime], Memc[sname],
+ Memc[zname], Memc[wname], Memr[modes], Memr[medians], Memr[means],
+ scales, zeros, wts, offsets, nimages, dozero, nout,
+ Memc[expname], exposure)
+
+ doscale = (doscale || dozero)
+
+ call sfree (sp)
+end
+
+
+# IC_GSCALE -- Get scale values as directed by CL parameter
+# The values can be one of those in the dictionary, from a file specified
+# with a @ prefix, or from an image header keyword specified by a ! prefix.
+
+int procedure ic_gscale (param, name, dic, in, exptime, values, nimages)
+
+char param[ARB] #I CL parameter name
+char name[SZ_FNAME] #O Parameter value
+char dic[ARB] #I Dictionary string
+pointer in[nimages] #I IMIO pointers
+real exptime[nimages] #I Exposure times
+real values[nimages] #O Values
+int nimages #I Number of images
+
+int type #O Type of value
+
+int fd, i, nowhite(), open(), fscan(), nscan(), strdic()
+real rval, imgetr()
+pointer errstr
+errchk open, imgetr()
+
+include "icombine.com"
+
+begin
+ call clgstr (param, name, SZ_FNAME)
+ if (nowhite (name, name, SZ_FNAME) == 0)
+ type = S_NONE
+ else if (name[1] == '@') {
+ type = S_FILE
+ fd = open (name[2], READ_ONLY, TEXT_FILE)
+ i = 0
+ while (fscan (fd) != EOF) {
+ call gargr (rval)
+ if (nscan() != 1)
+ next
+ if (i == nimages) {
+ call eprintf (
+ "Warning: Ignoring additional %s values in %s\n")
+ call pargstr (param)
+ call pargstr (name[2])
+ break
+ }
+ i = i + 1
+ values[i] = rval
+ }
+ call close (fd)
+ if (i < nimages) {
+ call salloc (errstr, SZ_LINE, TY_CHAR)
+ call sprintf (errstr, SZ_FNAME, "Insufficient %s values in %s")
+ call pargstr (param)
+ call pargstr (name[2])
+ call error (1, errstr)
+ }
+ } else if (name[1] == '!') {
+ type = S_KEYWORD
+ do i = 1, nimages {
+ values[i] = imgetr (in[i], name[2])
+ if (project) {
+ call amovkr (values, values, nimages)
+ break
+ }
+ }
+ } else {
+ type = strdic (name, name, SZ_FNAME, dic)
+ if (type == 0)
+ call error (1, "Unknown scale, zero, or weight type")
+ if (type==S_EXPOSURE)
+ do i = 1, nimages
+ values[i] = max (0.001, exptime[i])
+ }
+
+ return (type)
+end
diff --git a/pkg/obsolete/imcombine/icsclip.gx b/pkg/obsolete/imcombine/icsclip.gx
new file mode 100644
index 00000000..1b1c5de9
--- /dev/null
+++ b/pkg/obsolete/imcombine/icsclip.gx
@@ -0,0 +1,504 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../icombine.h"
+
+define MINCLIP 3 # Mininum number of images for algorithm
+
+$for (sird)
+# IC_ASIGCLIP -- Reject pixels using sigma clipping about the average
+# The initial average rejects the high and low pixels. A correction for
+# different scalings of the images may be made. Weights are not used.
+
+procedure ic_asigclip$t (d, m, n, scales, zeros, nimages, npts, average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+$if (datatype == sil)
+real average[npts] # Average
+$else
+PIXEL average[npts] # Average
+$endif
+
+int i, j, k, l, jj, n1, n2, nin, nk, maxkeep
+$if (datatype == sil)
+real d1, low, high, sum, a, s, r, one
+data one /1.0/
+$else
+PIXEL d1, low, high, sum, a, s, r, one
+data one /1$f/
+$endif
+pointer sp, resid, w, wp, dp1, dp2, mp1, mp2
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Flag whether returned average needs to be recomputed.
+ if (dowts || combine != AVERAGE)
+ docombine = true
+ else
+ docombine = false
+
+ # Save the residuals and the sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Do sigma clipping.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+
+ # If there are not enough pixels simply compute the average.
+ if (n1 < max (3, maxkeep)) {
+ if (!docombine) {
+ if (n1 == 0)
+ average[i] = blank
+ else {
+ sum = Mem$t[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mem$t[d[j]+k]
+ average[i] = sum / n1
+ }
+ }
+ next
+ }
+
+ # Compute average with the high and low rejected.
+ low = Mem$t[d[1]+k]
+ high = Mem$t[d[2]+k]
+ if (low > high) {
+ d1 = low
+ low = high
+ high = d1
+ }
+ sum = 0.
+ do j = 3, n1 {
+ d1 = Mem$t[d[j]+k]
+ if (d1 < low) {
+ sum = sum + low
+ low = d1
+ } else if (d1 > high) {
+ sum = sum + high
+ high = d1
+ } else
+ sum = sum + d1
+ }
+ a = sum / (n1 - 2)
+ sum = sum + low + high
+
+ # Iteratively reject pixels and compute the final average if needed.
+ # Compact the data and keep track of the image IDs if needed.
+
+ repeat {
+ n2 = n1
+ if (doscale1) {
+ # Compute sigma corrected for scaling.
+ s = 0.
+ wp = w - 1
+ do j = 1, n1 {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Mem$t[dp1]
+ l = Memi[mp1]
+ r = sqrt (max (one, (a + zeros[l]) / scales[l]))
+ s = s + ((d1 - a) / r) ** 2
+ Memr[wp] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ wp = w - 1
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ wp = wp + 1
+
+ d1 = Mem$t[dp1]
+ r = (d1 - a) / (s * Memr[wp])
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ Memr[wp] = Memr[w+n1-1]
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ } else {
+ # Compute the sigma without scale correction.
+ s = 0.
+ do j = 1, n1
+ s = s + (Mem$t[d[j]+k] - a) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels. Save the residuals and data values.
+ if (s > 0.) {
+ for (j=1; j<=n1; j=j+1) {
+ dp1 = d[j] + k
+ d1 = Mem$t[dp1]
+ r = (d1 - a) / s
+ if (r < -lsigma || r > hsigma) {
+ Memr[resid+n1] = abs (r)
+ if (j < n1) {
+ dp2 = d[n1] + k
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[n1] + k
+ l = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = l
+ }
+ j = j - 1
+ }
+ sum = sum - d1
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ } until (n1 == n2 || n1 <= max (2, maxkeep))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ if (n1 < maxkeep) {
+ nk = maxkeep
+ if (doscale1) {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ mp1 = m[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mem$t[dp1]
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ sum = sum + Mem$t[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ } else {
+ for (j=n1+1; j<=nk; j=j+1) {
+ dp1 = d[j] + k
+ r = Memr[resid+j]
+ jj = 0
+ do l = j+1, n2 {
+ s = Memr[resid+l]
+ if (s < r + TOL) {
+ if (s > r - TOL)
+ jj = jj + 1
+ else {
+ jj = 0
+ Memr[resid+l] = r
+ r = s
+ dp2 = d[l] + k
+ d1 = Mem$t[dp1]
+ Mem$t[dp1] = Mem$t[dp2]
+ Mem$t[dp2] = d1
+ if (keepids) {
+ mp1 = m[j] + k
+ mp2 = m[l] + k
+ s = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = s
+ }
+ }
+ }
+ }
+ sum = sum + Mem$t[dp1]
+ n1 = n1 + 1
+ nk = max (nk, j+jj)
+ }
+ }
+
+ # Recompute the average.
+ if (n1 > 1)
+ a = sum / n1
+ }
+
+ # Save the average if needed.
+ n[i] = n1
+ if (!docombine) {
+ if (n1 > 0)
+ average[i] = a
+ else
+ average[i] = blank
+ }
+ }
+
+ # Check if the data flag has to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# IC_MSIGCLIP -- Reject pixels using sigma clipping about the median
+
+procedure ic_msigclip$t (d, m, n, scales, zeros, nimages, npts, median)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image id pointers
+int n[npts] # Number of good pixels
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+int nimages # Number of images
+int npts # Number of output points per line
+$if (datatype == sil)
+real median[npts] # Median
+$else
+PIXEL median[npts] # Median
+$endif
+
+int i, j, k, l, id, n1, n2, n3, nl, nh, nin, maxkeep
+real r, s
+pointer sp, resid, w, mp1, mp2
+$if (datatype == sil)
+real med, one
+data one /1.0/
+$else
+PIXEL med, one
+data one /1$f/
+$endif
+
+include "../icombine.com"
+
+begin
+ # If there are insufficient pixels go on to the combining
+ if (nkeep < 0)
+ maxkeep = max (0, nimages + nkeep)
+ else
+ maxkeep = min (nimages, nkeep)
+ if (nimages < max (MINCLIP, maxkeep+1) || dflag == D_NONE) {
+ docombine = true
+ return
+ }
+
+ # Save the residuals and sigma scaling corrections if needed.
+ call smark (sp)
+ call salloc (resid, nimages+1, TY_REAL)
+ if (doscale1)
+ call salloc (w, nimages, TY_REAL)
+
+ # Compute median and sigma and iteratively clip.
+ nin = n[1]
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (nkeep < 0)
+ maxkeep = max (0, n1 + nkeep)
+ else
+ maxkeep = min (n1, nkeep)
+ nl = 1
+ nh = n1
+
+ repeat {
+ n2 = n1
+ n3 = nl + n1 / 2
+
+ if (n1 == 0)
+ med = blank
+ else if (mod (n1, 2) == 0)
+ med = (Mem$t[d[n3-1]+k] + Mem$t[d[n3]+k]) / 2.
+ else
+ med = Mem$t[d[n3]+k]
+
+ if (n1 >= max (MINCLIP, maxkeep+1)) {
+ if (doscale1) {
+ # Compute the sigma with scaling correction.
+ s = 0.
+ do j = nl, nh {
+ l = Memi[m[j]+k]
+ r = sqrt (max (one, (med + zeros[l]) / scales[l]))
+ s = s + ((Mem$t[d[j]+k] - med) / r) ** 2
+ Memr[w+j-1] = r
+ }
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Mem$t[d[nl]+k]) / (s * Memr[w+nl-1])
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Mem$t[d[nh]+k] - med) / (s * Memr[w+nh-1])
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ } else {
+ # Compute the sigma without scaling correction.
+ s = 0.
+ do j = nl, nh
+ s = s + (Mem$t[d[j]+k] - med) ** 2
+ s = sqrt (s / (n1 - 1))
+
+ # Reject pixels and save the residuals.
+ if (s > 0.) {
+ for (; nl <= n2; nl = nl + 1) {
+ r = (med - Mem$t[d[nl]+k]) / s
+ if (r <= lsigma)
+ break
+ Memr[resid+nl] = r
+ n1 = n1 - 1
+ }
+ for (; nh >= nl; nh = nh - 1) {
+ r = (Mem$t[d[nh]+k] - med) / s
+ if (r <= hsigma)
+ break
+ Memr[resid+nh] = r
+ n1 = n1 - 1
+ }
+ }
+ }
+ }
+ } until (n1 == n2 || n1 < max (MINCLIP, maxkeep+1))
+
+ # If too many pixels are rejected add some back.
+ # All pixels with equal residuals are added back.
+ while (n1 < maxkeep) {
+ if (nl == 1)
+ nh = nh + 1
+ else if (nh == n[i])
+ nl = nl - 1
+ else {
+ r = Memr[resid+nl-1]
+ s = Memr[resid+nh+1]
+ if (r < s) {
+ nl = nl - 1
+ r = r + TOL
+ if (s <= r)
+ nh = nh + 1
+ if (nl > 1) {
+ if (Memr[resid+nl-1] <= r)
+ nl = nl - 1
+ }
+ } else {
+ nh = nh + 1
+ s = s + TOL
+ if (r <= s)
+ nl = nl - 1
+ if (nh < n2) {
+ if (Memr[resid+nh+1] <= s)
+ nh = nh + 1
+ }
+ }
+ }
+ n1 = nh - nl + 1
+ }
+
+ # Only set median and reorder if needed
+ n[i] = n1
+ if (n1 > 0 && nl > 1 && (combine != MEDIAN || grow >= 1.)) {
+ j = max (nl, n1 + 1)
+ if (keepids) {
+ do l = 1, min (n1, nl-1) {
+ Mem$t[d[l]+k] = Mem$t[d[j]+k]
+ if (grow >= 1.) {
+ mp1 = m[l] + k
+ mp2 = m[j] + k
+ id = Memi[mp1]
+ Memi[mp1] = Memi[mp2]
+ Memi[mp2] = id
+ } else
+ Memi[m[l]+k] = Memi[m[j]+k]
+ j = j + 1
+ }
+ } else {
+ do l = 1, min (n1, nl - 1) {
+ Mem$t[d[l]+k] = Mem$t[d[j]+k]
+ j = j + 1
+ }
+ }
+ }
+
+ if (combine == MEDIAN)
+ median[i] = med
+ }
+
+ # Check if data flag needs to be reset for rejected pixels
+ if (dflag == D_ALL) {
+ do i = 1, npts {
+ if (n[i] != nin) {
+ dflag = D_MIX
+ break
+ }
+ }
+ }
+
+ # Flag that the median has been computed.
+ if (combine == MEDIAN)
+ docombine = false
+ else
+ docombine = true
+
+ call sfree (sp)
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icsection.x b/pkg/obsolete/imcombine/icsection.x
new file mode 100644
index 00000000..746c1f51
--- /dev/null
+++ b/pkg/obsolete/imcombine/icsection.x
@@ -0,0 +1,94 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctype.h>
+
+# IC_SECTION -- Parse an 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 ic_section (section, x1, x2, xs, ndim)
+
+char section[ARB] # Image section
+int x1[ndim] # Starting pixel
+int x2[ndim] # Ending pixel
+int xs[ndim] # Step
+int ndim # Number of dimensions
+
+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, ndim {
+ while (IS_WHITE(section[ip]))
+ ip = ip + 1
+ if (section[ip] == ']')
+ break
+
+ # Default values
+ a = x1[i]
+ b = x2[i]
+ c = xs[i]
+
+ # 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
+
+ x1[i] = a
+ x2[i] = b
+ xs[i] = 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/pkg/obsolete/imcombine/icsetout.x b/pkg/obsolete/imcombine/icsetout.x
new file mode 100644
index 00000000..cdb69b43
--- /dev/null
+++ b/pkg/obsolete/imcombine/icsetout.x
@@ -0,0 +1,273 @@
+include <imhdr.h>
+include <imset.h>
+include <mwset.h>
+
+define OFFTYPES "|none|wcs|world|physical|grid|"
+define FILE 0
+define NONE 1
+define WCS 2
+define WORLD 3
+define PHYSICAL 4
+define GRID 5
+
+# IC_SETOUT -- Set output image size and offsets of input images.
+
+procedure ic_setout (in, out, offsets, nimages)
+
+pointer in[nimages] # Input images
+pointer out[3] # Output images
+int offsets[nimages,ARB] # Offsets
+int nimages # Number of images
+
+int i, j, indim, outdim, mwdim, a, b, amin, bmax, fd, offtype
+real val
+bool reloff, flip, streq(), fp_equald()
+pointer sp, str, fname
+pointer pref, lref, wref, cd, ltm, coord, shift, axno, axval, section
+pointer mw, ct, mw_openim(), mw_sctran(), immap()
+int open(), fscan(), nscan(), mw_stati(), strlen(), strdic()
+errchk mw_openim, mw_sctran, mw_ctrand, open, immap
+
+include "icombine.com"
+define newscan_ 10
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (lref, IM_MAXDIM, TY_DOUBLE)
+ call salloc (wref, IM_MAXDIM, TY_DOUBLE)
+ call salloc (cd, IM_MAXDIM*IM_MAXDIM, TY_DOUBLE)
+ call salloc (coord, IM_MAXDIM, TY_DOUBLE)
+ call salloc (shift, IM_MAXDIM, TY_REAL)
+ call salloc (axno, IM_MAXDIM, TY_INT)
+ call salloc (axval, IM_MAXDIM, TY_INT)
+
+ # Check and set the image dimensionality.
+ indim = IM_NDIM(in[1])
+ outdim = IM_NDIM(out[1])
+ if (project) {
+ outdim = indim - 1
+ IM_NDIM(out[1]) = outdim
+ } else {
+ do i = 1, nimages
+ if (IM_NDIM(in[i]) != outdim) {
+ call sfree (sp)
+ call error (1, "Image dimensions are not the same")
+ }
+ }
+
+ # Set the reference point to that of the first image.
+ mw = mw_openim (in[1])
+ mwdim = mw_stati (mw, MW_NPHYSDIM)
+ call mw_gwtermd (mw, Memd[lref], Memd[wref], Memd[cd], mwdim)
+ if (project)
+ Memd[lref+outdim] = 1
+
+ # Parse the user offset string. If "none" then there are no offsets.
+ # If "world" or "wcs" then set the offsets based on the world WCS.
+ # If "physical" then set the offsets based on the physical WCS.
+ # If "grid" then set the offsets based on the input grid parameters.
+ # If a file scan it.
+
+ call clgstr ("offsets", Memc[fname], SZ_FNAME)
+ call sscan (Memc[fname])
+ call gargwrd (Memc[fname], SZ_FNAME)
+ if (nscan() == 0)
+ offtype = NONE
+ else {
+ offtype = strdic (Memc[fname], Memc[str], SZ_FNAME, OFFTYPES)
+ if (offtype > 0 && !streq (Memc[fname], Memc[str]))
+ offtype = 0
+ }
+ if (offtype == 0)
+ offtype = FILE
+
+ switch (offtype) {
+ case NONE:
+ call aclri (offsets, outdim*nimages)
+ reloff = true
+ case WORLD, WCS:
+ do j = 1, outdim
+ offsets[1,j] = 0
+ if (project) {
+ ct = mw_sctran (mw, "world", "logical", 0)
+ do i = 2, nimages {
+ Memd[wref+outdim] = i
+ call mw_ctrand (ct, Memd[wref], Memd[coord], indim)
+ do j = 1, outdim
+ offsets[i,j] = nint (Memd[lref+j-1] - Memd[coord+j-1])
+ }
+ call mw_ctfree (ct)
+ call mw_close (mw)
+ } else {
+ do i = 2, nimages {
+ call mw_close (mw)
+ mw = mw_openim (in[i])
+ ct = mw_sctran (mw, "world", "logical", 0)
+ call mw_ctrand (ct, Memd[wref], Memd[coord], indim)
+ do j = 1, outdim
+ offsets[i,j] = nint (Memd[lref+j-1] - Memd[coord+j-1])
+ call mw_ctfree (ct)
+ }
+ }
+ reloff = true
+ case PHYSICAL:
+ call salloc (pref, IM_MAXDIM, TY_DOUBLE)
+ call salloc (ltm, IM_MAXDIM*IM_MAXDIM, TY_DOUBLE)
+ call salloc (section, SZ_FNAME, TY_CHAR)
+
+ call mw_gltermd (mw, Memd[ltm], Memd[coord], indim)
+ do i = 2, nimages {
+ call mw_close (mw)
+ mw = mw_openim (in[i])
+ call mw_gltermd (mw, Memd[cd], Memd[coord], indim)
+ call strcpy ("[", Memc[section], SZ_FNAME)
+ flip = false
+ do j = 0, indim*indim-1, indim+1 {
+ if (Memd[ltm+j] * Memd[cd+j] >= 0.)
+ call strcat ("*,", Memc[section], SZ_FNAME)
+ else {
+ call strcat ("-*,", Memc[section], SZ_FNAME)
+ flip = true
+ }
+ }
+ Memc[section+strlen(Memc[section])-1] = ']'
+ if (flip) {
+ call imstats (in[i], IM_IMAGENAME, Memc[fname], SZ_FNAME)
+ call strcat (Memc[section], Memc[fname], SZ_FNAME)
+ call imunmap (in[i])
+ in[i] = immap (Memc[fname], READ_ONLY, TY_CHAR)
+ call mw_close (mw)
+ mw = mw_openim (in[i])
+ call mw_gltermd (mw, Memd[cd], Memd[coord], indim)
+ do j = 0, indim*indim-1
+ if (!fp_equald (Memd[ltm+j], Memd[cd+j]))
+ call error (1,
+ "Cannot match physical coordinates")
+ }
+ }
+
+ call mw_close (mw)
+ mw = mw_openim (in[1])
+ ct = mw_sctran (mw, "logical", "physical", 0)
+ call mw_ctrand (ct, Memd[lref], Memd[pref], indim)
+ call mw_ctfree (ct)
+ do j = 1, outdim
+ offsets[1,j] = 0
+ if (project) {
+ ct = mw_sctran (mw, "physical", "logical", 0)
+ do i = 2, nimages {
+ Memd[pref+outdim] = i
+ call mw_ctrand (ct, Memd[pref], Memd[coord], indim)
+ do j = 1, outdim
+ offsets[i,j] = nint (Memd[lref+j-1] - Memd[coord+j-1])
+ }
+ call mw_ctfree (ct)
+ call mw_close (mw)
+ } else {
+ do i = 2, nimages {
+ call mw_close (mw)
+ mw = mw_openim (in[i])
+ ct = mw_sctran (mw, "physical", "logical", 0)
+ call mw_ctrand (ct, Memd[pref], Memd[coord], indim)
+ do j = 1, outdim
+ offsets[i,j] = nint (Memd[lref+j-1] - Memd[coord+j-1])
+ call mw_ctfree (ct)
+ }
+ }
+ reloff = true
+ case GRID:
+ amin = 1
+ do j = 1, outdim {
+ call gargi (a)
+ call gargi (b)
+ if (nscan() < 1+2*j)
+ break
+ do i = 1, nimages
+ offsets[i,j] = mod ((i-1)/amin, a) * b
+ amin = amin * a
+ }
+ reloff = true
+ case FILE:
+ reloff = true
+ fd = open (Memc[fname], READ_ONLY, TEXT_FILE)
+ do i = 1, nimages {
+newscan_ if (fscan (fd) == EOF)
+ call error (1, "IMCOMBINE: Offset list too short")
+ call gargwrd (Memc[fname], SZ_FNAME)
+ if (Memc[fname] == '#') {
+ call gargwrd (Memc[fname], SZ_FNAME)
+ call strlwr (Memc[fname])
+ if (streq (Memc[fname], "absolute"))
+ reloff = false
+ else if (streq (Memc[fname], "relative"))
+ reloff = true
+ goto newscan_
+ }
+ call reset_scan ()
+ do j = 1, outdim {
+ call gargr (val)
+ offsets[i,j] = nint (val)
+ }
+ if (nscan() < outdim)
+ call error (1, "IMCOMBINE: Error in offset list")
+ }
+ call close (fd)
+ }
+
+ # Set the output image size and the aligned flag
+ aligned = true
+ do j = 1, outdim {
+ a = offsets[1,j]
+ b = IM_LEN(in[1],j) + a
+ amin = a
+ bmax = b
+ do i = 2, nimages {
+ a = offsets[i,j]
+ b = IM_LEN(in[i],j) + a
+ if (a != amin || b != bmax || !reloff)
+ aligned = false
+ amin = min (a, amin)
+ bmax = max (b, bmax)
+ }
+ IM_LEN(out[1],j) = bmax
+ if (reloff || amin < 0) {
+ do i = 1, nimages
+ offsets[i,j] = offsets[i,j] - amin
+ IM_LEN(out[1],j) = IM_LEN(out[1],j) - amin
+ }
+ }
+
+ # Update the WCS.
+ if (project || !aligned || !reloff) {
+ call mw_close (mw)
+ mw = mw_openim (out[1])
+ if (!aligned || !reloff) {
+ call mw_gltermd (mw, Memd[cd], Memd[lref], indim)
+ do i = 1, indim
+ Memd[lref+i-1] = Memd[lref+i-1] + offsets[1,i]
+ call mw_sltermd (mw, Memd[cd], Memd[lref], indim)
+ }
+ if (project) {
+ # Apply dimensional reduction.
+ i = mw_stati (mw, MW_NPHYSDIM)
+ call mw_gaxmap (mw, Memi[axno], Memi[axval], i)
+ do j = 0, i-1 {
+ if (Memi[axno+j] <= outdim) {
+ next
+ } else if (Memi[axno+j] > outdim+1) {
+ Memi[axno+j] = Memi[axno+j] - 1
+ } else {
+ Memi[axno+j] = 0
+ Memi[axval+j] = 0
+ }
+ }
+ call mw_saxmap (mw, Memi[axno], Memi[axval], i)
+ }
+ call mw_saveim (mw, out)
+ }
+ call mw_close (mw)
+
+ call sfree (sp)
+end
diff --git a/pkg/obsolete/imcombine/icsigma.gx b/pkg/obsolete/imcombine/icsigma.gx
new file mode 100644
index 00000000..81e536c4
--- /dev/null
+++ b/pkg/obsolete/imcombine/icsigma.gx
@@ -0,0 +1,115 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+$for (sird)
+# IC_SIGMA -- Compute the sigma image line.
+# The estimated sigma includes a correction for the finite population.
+# Weights are used if desired.
+
+procedure ic_sigma$t (d, m, n, wts, npts, average, sigma)
+
+pointer d[ARB] # Data pointers
+pointer m[ARB] # Image ID pointers
+int n[npts] # Number of points
+real wts[ARB] # Weights
+int npts # Number of output points per line
+$if (datatype == sil)
+real average[npts] # Average
+real sigma[npts] # Sigma line (returned)
+$else
+PIXEL average[npts] # Average
+PIXEL sigma[npts] # Sigma line (returned)
+$endif
+
+int i, j, k, n1
+real wt, sigcor, sumwt
+$if (datatype == sil)
+real a, sum
+$else
+PIXEL a, sum
+$endif
+
+include "../icombine.com"
+
+begin
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ if (dowts) {
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Mem$t[d[1]+k] - a) ** 2 * wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Mem$t[d[j]+k] - a) ** 2 * wt
+ }
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ } else {
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ do i = 1, npts {
+ k = i - 1
+ a = average[i]
+ sum = (Mem$t[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Mem$t[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ do i = 1, npts
+ sigma[i] = blank
+ } else {
+ if (dowts) {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = real (n1) / real (n1 -1)
+ else
+ sigcor = 1
+ a = average[i]
+ wt = wts[Memi[m[1]+k]]
+ sum = (Mem$t[d[1]+k] - a) ** 2 * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (Mem$t[d[j]+k] - a) ** 2 * wt
+ sumwt = sumwt + wt
+ }
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = n[i]
+ if (n1 > 0) {
+ k = i - 1
+ if (n1 > 1)
+ sigcor = 1. / real (n1 - 1)
+ else
+ sigcor = 1.
+ a = average[i]
+ sum = (Mem$t[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Mem$t[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum * sigcor)
+ } else
+ sigma[i] = blank
+ }
+ }
+ }
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icsort.gx b/pkg/obsolete/imcombine/icsort.gx
new file mode 100644
index 00000000..e124da15
--- /dev/null
+++ b/pkg/obsolete/imcombine/icsort.gx
@@ -0,0 +1,386 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+define LOGPTR 32 # log2(maxpts) (4e9)
+
+$for (sird)
+# IC_SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially.
+
+procedure ic_sort$t (a, b, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+PIXEL b[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+PIXEL pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR]
+define swap {temp=$1;$1=$2;$2=temp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix
+ b[i] = Mem$t[a[i]+l]
+
+ # Special cases
+ $if (datatype == x)
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (abs (temp) < abs (pivot)) {
+ b[1] = temp
+ b[2] = pivot
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (abs (temp) < abs (pivot)) { # bac|bca|cba
+ if (abs (temp) < abs (temp3)) { # bac|bca
+ b[1] = temp
+ if (abs (pivot) < abs (temp3)) # bac
+ b[2] = pivot
+ else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ }
+ } else if (abs (temp3) < abs (temp)) { # acb|cab
+ b[3] = temp
+ if (abs (pivot) < abs (temp3)) # acb
+ b[2] = temp3
+ else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+ $else
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) # bac
+ b[2] = pivot
+ else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) # acb
+ b[2] = temp3
+ else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+ $endif
+
+ # General case
+ do i = 1, npix
+ b[i] = Mem$t[a[i]+l]
+
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ $if (datatype == x)
+ for (i=i+1; abs(b[i]) < abs(pivot); i=i+1)
+ $else
+ for (i=i+1; b[i] < pivot; i=i+1)
+ $endif
+ ;
+ for (j=j-1; j > i; j=j-1)
+ $if (datatype == x)
+ if (abs(b[j]) <= abs(pivot))
+ $else
+ if (b[j] <= pivot)
+ $endif
+ break
+ if (i < j) # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix
+ Mem$t[a[i]+l] = b[i]
+ }
+end
+
+
+# IC_2SORT -- Quicksort. This is based on the VOPS asrt except that
+# the input is an array of pointers to image lines and the sort is done
+# across the image lines at each point along the lines. The number of
+# valid pixels at each point is allowed to vary. The cases of 1, 2, and 3
+# pixels per point are treated specially. A second integer set of
+# vectors is sorted.
+
+procedure ic_2sort$t (a, b, c, d, nvecs, npts)
+
+pointer a[ARB] # pointer to input vectors
+PIXEL b[ARB] # work array
+pointer c[ARB] # pointer to associated integer vectors
+int d[ARB] # work array
+int nvecs[npts] # number of vectors
+int npts # number of points in vectors
+
+PIXEL pivot, temp, temp3
+int i, j, k, l, p, npix, lv[LOGPTR], uv[LOGPTR], itemp
+define swap {temp=$1;$1=$2;$2=temp}
+define iswap {itemp=$1;$1=$2;$2=itemp}
+define copy_ 10
+
+begin
+ do l = 0, npts-1 {
+ npix = nvecs[l+1]
+ if (npix <= 1)
+ next
+
+ do i = 1, npix {
+ b[i] = Mem$t[a[i]+l]
+ d[i] = Memi[c[i]+l]
+ }
+
+ # Special cases
+ $if (datatype == x)
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (abs (temp) < abs (pivot)) {
+ b[1] = temp
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (abs (temp) < abs (pivot)) { # bac|bca|cba
+ if (abs (temp) < abs (temp3)) { # bac|bca
+ b[1] = temp
+ if (abs (pivot) < abs (temp3)) { # bac
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ itemp = d[2]
+ d[2] = d[3]
+ d[3] = d[1]
+ d[1] = itemp
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ iswap (d[1], d[3])
+ }
+ } else if (abs (temp3) < abs (temp)) { # acb|cab
+ b[3] = temp
+ if (abs (pivot) < abs (temp3)) { # acb
+ b[2] = temp3
+ iswap (d[2], d[3])
+ } else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ itemp = d[2]
+ d[2] = d[1]
+ d[1] = d[3]
+ d[3] = itemp
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+ $else
+ if (npix <= 3) {
+ pivot = b[1]
+ temp = b[2]
+ if (npix == 2) {
+ if (temp < pivot) {
+ b[1] = temp
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else
+ next
+ } else {
+ temp3 = b[3]
+ if (temp < pivot) { # bac|bca|cba
+ if (temp < temp3) { # bac|bca
+ b[1] = temp
+ if (pivot < temp3) { # bac
+ b[2] = pivot
+ iswap (d[1], d[2])
+ } else { # bca
+ b[2] = temp3
+ b[3] = pivot
+ itemp = d[2]
+ d[2] = d[3]
+ d[3] = d[1]
+ d[1] = itemp
+ }
+ } else { # cba
+ b[1] = temp3
+ b[3] = pivot
+ iswap (d[1], d[3])
+ }
+ } else if (temp3 < temp) { # acb|cab
+ b[3] = temp
+ if (pivot < temp3) { # acb
+ b[2] = temp3
+ iswap (d[2], d[3])
+ } else { # cab
+ b[1] = temp3
+ b[2] = pivot
+ itemp = d[2]
+ d[2] = d[1]
+ d[1] = d[3]
+ d[3] = itemp
+ }
+ } else
+ next
+ }
+ goto copy_
+ }
+ $endif
+
+ # General case
+ lv[1] = 1
+ uv[1] = npix
+ p = 1
+
+ while (p > 0) {
+ if (lv[p] >= uv[p]) # only one elem in this subset
+ p = p - 1 # pop stack
+ else {
+ # Dummy do loop to trigger the Fortran optimizer.
+ do p = p, ARB {
+ i = lv[p] - 1
+ j = uv[p]
+
+ # Select as the pivot the element at the center of the
+ # array, to avoid quadratic behavior on an already
+ # sorted array.
+
+ k = (lv[p] + uv[p]) / 2
+ swap (b[j], b[k]); swap (d[j], d[k])
+ pivot = b[j] # pivot line
+
+ while (i < j) {
+ $if (datatype == x)
+ for (i=i+1; abs(b[i]) < abs(pivot); i=i+1)
+ $else
+ for (i=i+1; b[i] < pivot; i=i+1)
+ $endif
+ ;
+ for (j=j-1; j > i; j=j-1)
+ $if (datatype == x)
+ if (abs(b[j]) <= abs(pivot))
+ $else
+ if (b[j] <= pivot)
+ $endif
+ break
+ if (i < j) { # out of order pair
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+ }
+ }
+
+ j = uv[p] # move pivot to position i
+ swap (b[i], b[j]) # interchange elements
+ swap (d[i], d[j])
+
+ if (i-lv[p] < uv[p] - i) { # stack so shorter done first
+ lv[p+1] = lv[p]
+ uv[p+1] = i - 1
+ lv[p] = i + 1
+ } else {
+ lv[p+1] = i + 1
+ uv[p+1] = uv[p]
+ uv[p] = i - 1
+ }
+
+ break
+ }
+ p = p + 1 # push onto stack
+ }
+ }
+
+copy_
+ do i = 1, npix {
+ Mem$t[a[i]+l] = b[i]
+ Memi[c[i]+l] = d[i]
+ }
+ }
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/icstat.gx b/pkg/obsolete/imcombine/icstat.gx
new file mode 100644
index 00000000..f2b65089
--- /dev/null
+++ b/pkg/obsolete/imcombine/icstat.gx
@@ -0,0 +1,237 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+define NMAX 10000 # Maximum number of pixels to sample
+
+$for (sird)
+# IC_STAT -- Compute image statistics within specified section.
+# The image section is relative to a reference image which may be
+# different than the input image and may have an offset. Only a
+# subsample of pixels is used. Masked and thresholded pixels are
+# ignored. Only the desired statistics are computed to increase
+# efficiency.
+
+procedure ic_stat$t (im, imref, section, offsets, image, nimages,
+ domode, domedian, domean, mode, median, mean)
+
+pointer im # Data image
+pointer imref # Reference image for image section
+char section[ARB] # Image section
+int offsets[nimages,ARB] # Image section offset from data to reference
+int image # Image index (for mask I/O)
+int nimages # Number of images in offsets.
+bool domode, domedian, domean # Statistics to compute
+real mode, median, mean # Statistics
+
+int i, j, ndim, n, nv
+real a
+pointer sp, v1, v2, dv, va, vb
+pointer data, mask, dp, lp, mp, imgnl$t()
+PIXEL ic_mode$t()
+$if (datatype == irs)
+real asum$t()
+$endif
+$if (datatype == dl)
+double asum$t()
+$endif
+$if (datatype == x)
+complex asum$t()
+$endif
+
+
+include "../icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (v1, IM_MAXDIM, TY_LONG)
+ call salloc (v2, IM_MAXDIM, TY_LONG)
+ call salloc (dv, IM_MAXDIM, TY_LONG)
+ call salloc (va, IM_MAXDIM, TY_LONG)
+ call salloc (vb, IM_MAXDIM, TY_LONG)
+
+ # Determine the image section parameters. This must be in terms of
+ # the data image pixel coordinates though the section may be specified
+ # in terms of the reference image coordinates. Limit the number of
+ # pixels in each dimension to a maximum.
+
+ ndim = IM_NDIM(im)
+ if (project)
+ ndim = ndim - 1
+ call amovki (1, Memi[v1], IM_MAXDIM)
+ call amovki (1, Memi[va], IM_MAXDIM)
+ call amovki (1, Memi[dv], IM_MAXDIM)
+ call amovi (IM_LEN(imref,1), Memi[vb], ndim)
+ call ic_section (section, Memi[va], Memi[vb], Memi[dv], ndim)
+ if (im != imref)
+ do i = 1, ndim {
+ Memi[va+i-1] = Memi[va+i-1] - offsets[image,i]
+ Memi[vb+i-1] = Memi[vb+i-1] - offsets[image,i]
+ }
+
+ do j = 1, 10 {
+ n = 1
+ do i = 0, ndim-1 {
+ Memi[v1+i] = max (1, min (Memi[va+i], Memi[vb+i]))
+ Memi[v2+i] = min (IM_LEN(im,i+1), max (Memi[va+i], Memi[vb+i]))
+ Memi[dv+i] = j
+ nv = max (1, (Memi[v2+i] - Memi[v1+i]) / Memi[dv+i] + 1)
+ Memi[v2+i] = Memi[v1+i] + (nv - 1) * Memi[dv+i]
+ n = n * nv
+ }
+ if (n < NMAX)
+ break
+ }
+
+ call amovl (Memi[v1], Memi[va], IM_MAXDIM)
+ Memi[va] = 1
+ if (project)
+ Memi[va+ndim] = image
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+
+ # Accumulate the pixel values within the section. Masked pixels and
+ # thresholded pixels are ignored.
+
+ call salloc (data, n, TY_PIXEL)
+ dp = data
+ while (imgnl$t (im, lp, Memi[vb]) != EOF) {
+ call ic_mget1 (im, image, offsets[image,1], Memi[va], mask)
+ lp = lp + Memi[v1] - 1
+ if (dflag == D_ALL) {
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ a = Mem$t[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Mem$t[dp] = a
+ dp = dp + 1
+ }
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ Mem$t[dp] = Mem$t[lp]
+ dp = dp + 1
+ lp = lp + Memi[dv]
+ }
+ }
+ } else if (dflag == D_MIX) {
+ mp = mask + Memi[v1] - 1
+ if (dothresh) {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ a = Mem$t[lp]
+ if (a >= lthresh && a <= hthresh) {
+ Mem$t[dp] = a
+ dp = dp + 1
+ }
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ } else {
+ do i = Memi[v1], Memi[v2], Memi[dv] {
+ if (Memi[mp] == 0) {
+ Mem$t[dp] = Mem$t[lp]
+ dp = dp + 1
+ }
+ mp = mp + Memi[dv]
+ lp = lp + Memi[dv]
+ }
+ }
+ }
+ for (i=2; i<=ndim; i=i+1) {
+ Memi[va+i-1] = Memi[va+i-1] + Memi[dv+i-1]
+ if (Memi[va+i-1] <= Memi[v2+i-1])
+ break
+ Memi[va+i-1] = Memi[v1+i-1]
+ }
+ if (i > ndim)
+ break
+ call amovl (Memi[va], Memi[vb], IM_MAXDIM)
+ }
+
+ n = dp - data
+ if (n < 1) {
+ call sfree (sp)
+ call error (1, "Image section contains no pixels")
+ }
+
+ # Compute only statistics needed.
+ if (domode || domedian) {
+ call asrt$t (Mem$t[data], Mem$t[data], n)
+ mode = ic_mode$t (Mem$t[data], n)
+ median = Mem$t[data+n/2-1]
+ }
+ if (domean)
+ mean = asum$t (Mem$t[data], n) / n
+
+ call sfree (sp)
+end
+
+
+define NMIN 10 # Minimum number of pixels for mode calculation
+define ZRANGE 0.8 # Fraction of pixels about median to use
+define ZSTEP 0.01 # Step size for search for mode
+define ZBIN 0.1 # Bin size for mode.
+
+# IC_MODE -- Compute mode of an array. The mode is found by binning
+# with a bin size based on the data range over a fraction of the
+# pixels about the median and a bin step which may be smaller than the
+# bin size. If there are too few points the median is returned.
+# The input array must be sorted.
+
+PIXEL procedure ic_mode$t (a, n)
+
+PIXEL a[n] # Data array
+int n # Number of points
+
+int i, j, k, nmax
+real z1, z2, zstep, zbin
+PIXEL mode
+bool fp_equalr()
+
+begin
+ if (n < NMIN)
+ return (a[n/2])
+
+ # Compute the mode. The array must be sorted. Consider a
+ # range of values about the median point. Use a bin size which
+ # is ZBIN of the range. Step the bin limits in ZSTEP fraction of
+ # the bin size.
+
+ i = 1 + n * (1. - ZRANGE) / 2.
+ j = 1 + n * (1. + ZRANGE) / 2.
+ z1 = a[i]
+ z2 = a[j]
+ if (fp_equalr (z1, z2)) {
+ mode = z1
+ return (mode)
+ }
+
+ zstep = ZSTEP * (z2 - z1)
+ zbin = ZBIN * (z2 - z1)
+ $if (datatype == sil)
+ zstep = max (1., zstep)
+ zbin = max (1., zbin)
+ $endif
+
+ z1 = z1 - zstep
+ k = i
+ nmax = 0
+ repeat {
+ z1 = z1 + zstep
+ z2 = z1 + zbin
+ for (; i < j && a[i] < z1; i=i+1)
+ ;
+ for (; k < j && a[k] < z2; k=k+1)
+ ;
+ if (k - i > nmax) {
+ nmax = k - i
+ mode = a[(i+k)/2]
+ }
+ } until (k >= j)
+
+ return (mode)
+end
+$endfor
diff --git a/pkg/obsolete/imcombine/mkpkg b/pkg/obsolete/imcombine/mkpkg
new file mode 100644
index 00000000..4b6c120b
--- /dev/null
+++ b/pkg/obsolete/imcombine/mkpkg
@@ -0,0 +1,54 @@
+# Make the IMCOMBINE Task.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+generic:
+ $set GEN = "$$generic -k"
+
+ $ifolder (generic/icaclip.x, icaclip.gx)
+ $(GEN) icaclip.gx -o generic/icaclip.x $endif
+ $ifolder (generic/icaverage.x, icaverage.gx)
+ $(GEN) icaverage.gx -o generic/icaverage.x $endif
+ $ifolder (generic/iccclip.x, iccclip.gx)
+ $(GEN) iccclip.gx -o generic/iccclip.x $endif
+ $ifolder (generic/icgdata.x, icgdata.gx)
+ $(GEN) icgdata.gx -o generic/icgdata.x $endif
+ $ifolder (generic/icgrow.x, icgrow.gx)
+ $(GEN) icgrow.gx -o generic/icgrow.x $endif
+ $ifolder (generic/icmedian.x, icmedian.gx)
+ $(GEN) icmedian.gx -o generic/icmedian.x $endif
+ $ifolder (generic/icmm.x, icmm.gx)
+ $(GEN) icmm.gx -o generic/icmm.x $endif
+ $ifolder (generic/icombine.x, icombine.gx)
+ $(GEN) icombine.gx -o generic/icombine.x $endif
+ $ifolder (generic/icpclip.x, icpclip.gx)
+ $(GEN) icpclip.gx -o generic/icpclip.x $endif
+ $ifolder (generic/icsclip.x, icsclip.gx)
+ $(GEN) icsclip.gx -o generic/icsclip.x $endif
+ $ifolder (generic/icsigma.x, icsigma.gx)
+ $(GEN) icsigma.gx -o generic/icsigma.x $endif
+ $ifolder (generic/icsort.x, icsort.gx)
+ $(GEN) icsort.gx -o generic/icsort.x $endif
+ $ifolder (generic/icstat.x, icstat.gx)
+ $(GEN) icstat.gx -o generic/icstat.x $endif
+ ;
+
+libpkg.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+
+ @generic
+
+ icimstack.x <error.h> <imhdr.h>
+ iclog.x icmask.com icombine.com icombine.h <imhdr.h> <imset.h>\
+ <mach.h>
+ icmask.x icmask.com icombine.com icombine.h <imhdr.h> <pmset.h>
+ icrmasks.x <imhdr.h>
+ icscale.x icombine.com icombine.h <error.h> <imhdr.h> <imset.h>
+ icsection.x <ctype.h>
+ icsetout.x icombine.com <imhdr.h> <mwset.h> <imset.h>
+ t_imcombine.x icombine.com icombine.h <error.h> <imhdr.h> <mach.h> \
+ <syserr.h> <pmset.h>
+ ;
diff --git a/pkg/obsolete/imcombine/t_imcombine.x b/pkg/obsolete/imcombine/t_imcombine.x
new file mode 100644
index 00000000..5b2e5026
--- /dev/null
+++ b/pkg/obsolete/imcombine/t_imcombine.x
@@ -0,0 +1,501 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <error.h>
+include <syserr.h>
+include <mach.h>
+include <pmset.h>
+include "icombine.h"
+
+
+# T_IMCOMBINE - This task combines a list of images into an output image
+# and an optional sigma image. There are many combining options from
+# which to choose.
+
+procedure t_imcombine ()
+
+pointer sp, input, output, rmask, sigma, plfile, logfile
+int ilist, olist, rlist, slist, plist, n
+
+bool clgetb()
+real clgetr()
+int clgwrd(), clgeti(), imtopenp(), imtgetim(), imtlen()
+
+include "icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (rmask, SZ_FNAME, TY_CHAR)
+ call salloc (plfile, SZ_FNAME, TY_CHAR)
+ call salloc (sigma, SZ_FNAME, TY_CHAR)
+ call salloc (gain, SZ_FNAME, TY_CHAR)
+ call salloc (rdnoise, SZ_FNAME, TY_CHAR)
+ call salloc (snoise, SZ_FNAME, TY_CHAR)
+ call salloc (logfile, SZ_FNAME, TY_CHAR)
+
+ # Get task parameters. Some additional parameters are obtained later.
+ ilist = imtopenp ("input")
+ olist = imtopenp ("output")
+ rlist = imtopenp ("rejmask")
+ plist = imtopenp ("plfile")
+ slist = imtopenp ("sigma")
+ call clgstr ("logfile", Memc[logfile], SZ_FNAME)
+
+ project = clgetb ("project")
+ combine = clgwrd ("combine", Memc[input], SZ_FNAME, COMBINE)
+ reject = clgwrd ("reject", Memc[input], SZ_FNAME, REJECT)
+ blank = clgetr ("blank")
+ call clgstr ("gain", Memc[gain], SZ_FNAME)
+ call clgstr ("rdnoise", Memc[rdnoise], SZ_FNAME)
+ call clgstr ("snoise", Memc[snoise], SZ_FNAME)
+ lthresh = clgetr ("lthreshold")
+ hthresh = clgetr ("hthreshold")
+ lsigma = clgetr ("lsigma")
+ hsigma = clgetr ("hsigma")
+ pclip = clgetr ("pclip")
+ flow = clgetr ("nlow")
+ fhigh = clgetr ("nhigh")
+ nkeep = clgeti ("nkeep")
+ grow = clgetr ("grow")
+ mclip = clgetb ("mclip")
+ sigscale = clgetr ("sigscale")
+
+ # Check lists.
+ n = imtlen (ilist)
+ if (n == 0)
+ call error (1, "No input images to combine")
+ if (project) {
+ if (imtlen (olist) != n)
+ call error (1, "Wrong number of images in output list")
+ if (imtlen (rlist) != 0 && imtlen (rlist) != n)
+ call error (1, "Wrong number of masks in rejection mask list")
+ if (imtlen (plist) > 0 && imtlen (plist) != n)
+ call error (1, "Wrong number of masks in output mask list")
+ if (imtlen (slist) > 0 && imtlen (slist) != n)
+ call error (1, "Wrong number of images in output sigma list")
+ } else {
+ if (imtlen (olist) != 1)
+ call error (1, "Wrong number of images in output list")
+ if (imtlen (rlist) > 1)
+ call error (1, "Wrong number of masks in rejection mask list")
+ if (imtlen (plist) > 1)
+ call error (1, "Wrong number of masks in output mask list")
+ if (imtlen (slist) > 1)
+ call error (1, "Wrong number of images in output sigma list")
+ }
+
+ # Check parameters, map INDEFs, and set threshold flag
+ if (pclip == 0. && reject == PCLIP)
+ call error (1, "Pclip parameter may not be zero")
+ if (IS_INDEFR (blank))
+ blank = 0.
+ if (IS_INDEFR (lsigma))
+ lsigma = MAX_REAL
+ if (IS_INDEFR (hsigma))
+ hsigma = MAX_REAL
+ if (IS_INDEFR (pclip))
+ pclip = -0.5
+ if (IS_INDEFR (flow))
+ flow = 0
+ if (IS_INDEFR (fhigh))
+ fhigh = 0
+ if (IS_INDEFR (grow))
+ grow = 0.
+ if (IS_INDEF (sigscale))
+ sigscale = 0.
+
+ if (IS_INDEF(lthresh) && IS_INDEF(hthresh))
+ dothresh = false
+ else {
+ dothresh = true
+ if (IS_INDEF(lthresh))
+ lthresh = -MAX_REAL
+ if (IS_INDEF(hthresh))
+ hthresh = MAX_REAL
+ }
+
+ # Loop through image lists. Note that if not projecting then
+ # the input and rejmask lists will be exhausted by IMCOMBINE.
+
+ while (imtgetim (ilist, Memc[input], SZ_FNAME) != EOF) {
+ if (imtgetim (olist, Memc[output], SZ_FNAME) == EOF) {
+ if (project) {
+ call eprintf ("IMCOMBINE: No output image for %s\n")
+ call pargstr (Memc[input])
+ next
+ } else {
+ call eprintf ("IMCOMBINE: No output image\n")
+ call pargstr (Memc[input])
+ break
+ }
+ }
+ if (imtgetim (rlist, Memc[rmask], SZ_FNAME) == EOF)
+ Memc[rmask] = EOS
+ if (imtgetim (plist, Memc[plfile], SZ_FNAME) == EOF)
+ Memc[plfile] = EOS
+ if (imtgetim (slist, Memc[sigma], SZ_FNAME) == EOF)
+ Memc[sigma] = EOS
+
+ iferr (call icombine (ilist, Memc[input], Memc[output],
+ Memc[rmask], Memc[plfile], Memc[sigma], Memc[logfile], NO))
+ call erract (EA_WARN)
+ }
+
+ call imtclose (ilist)
+ call imtclose (olist)
+ call imtclose (rlist)
+ call imtclose (plist)
+ call imtclose (slist)
+ call sfree (sp)
+end
+
+
+# IMCOMBINE -- Combine input list or image.
+# This procedure maps the images, sets the output dimensions and datatype,
+# opens the logfile, and sets IMIO parameters. It attempts to adjust
+# buffer sizes and memory requirements for maximum efficiency.
+
+procedure icombine (list, input, output, rmask, plfile, sigma,
+ logfile, stack)
+
+int list # List of input images
+char input[ARB] # Input image
+char output[ARB] # Output image
+char rmask[ARB] # Rejection mask
+char plfile[ARB] # Output pixel list file
+char sigma[ARB] # Sigma image (optional)
+char logfile[ARB] # Logfile (optional)
+int stack # Stack input images?
+
+char errstr[SZ_LINE]
+int i, j, nimages, intype, bufsize, maxsize, memory, oldsize, stack1, err
+pointer sp, in, out[4], icm, offsets, key, tmp
+
+char clgetc()
+int imtlen(), imtgetim(), imtrgetim(), getdatatype()
+int begmem(), errget(), open(), ty_max(), sizeof()
+pointer immap(), ic_pmmap()
+errchk ic_imstack, immap, ic_pmmap, ic_setout
+
+include "icombine.com"
+
+define retry_ 98
+
+begin
+ # Map the input images.
+ bufsize = 0
+ stack1 = stack
+
+retry_
+ iferr {
+ call smark (sp)
+
+ in = NULL
+ out[1] = NULL
+ out[2] = NULL
+ out[3] = NULL
+ out[4] = NULL
+ icm = NULL
+ logfd = NULL
+
+ # Stack the input images.
+ if (stack1 == YES) {
+ call mktemp ("tmp", input, SZ_FNAME)
+ call imtrew (list)
+ call ic_imstack (list, input)
+ project = true
+ }
+
+ # Open the input image(s).
+ nimages = 0
+ if (project) {
+ tmp = immap (input, READ_ONLY, 0); out[1] = tmp
+ if (IM_NDIM(out[1]) == 1)
+ call error (1, "Can't project one dimensional images")
+ nimages = IM_LEN(out[1],IM_NDIM(out[1]))
+ call salloc (in, nimages, TY_POINTER)
+ call amovki (out[1], Memi[in], nimages)
+ } else {
+ call salloc (in, imtlen(list), TY_POINTER)
+ call amovki (NULL, Memi[in], imtlen(list))
+ call imtrew (list)
+ while (imtgetim (list, input, SZ_FNAME)!=EOF) {
+ tmp = immap (input, READ_ONLY, 0)
+ Memi[in+nimages] = tmp
+ nimages = nimages + 1
+ }
+ }
+
+ # Check if there are no images.
+ if (nimages == 0)
+ call error (1, "No input images to combine")
+
+ # Convert the pclip parameter to a number of pixels rather than
+ # a fraction. This number stays constant even if pixels are
+ # rejected. The number of low and high pixel rejected, however,
+ # are converted to a fraction of the valid pixels.
+
+ if (reject == PCLIP) {
+ i = (nimages - 1) / 2.
+ if (abs (pclip) < 1.)
+ pclip = pclip * i
+ if (pclip < 0.)
+ pclip = min (-1, max (-i, int (pclip)))
+ else
+ pclip = max (1, min (i, int (pclip)))
+ }
+
+ if (reject == MINMAX) {
+ if (flow >= 1)
+ flow = flow / nimages
+ if (fhigh >= 1)
+ fhigh = fhigh / nimages
+ i = flow * nimages
+ j = fhigh * nimages
+ if (i + j == 0)
+ reject = NONE
+ else if (i + j >= nimages)
+ call error (1, "Bad minmax rejection parameters")
+ }
+
+ # Map the output image and set dimensions and offsets.
+ tmp = immap (output, NEW_COPY, Memi[in]); out[1] = tmp
+ if (stack1 == YES) {
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ do i = 1, nimages {
+ call sprintf (Memc[key], SZ_FNAME, "stck%04d")
+ call pargi (i)
+ call imdelf (out[1], Memc[key])
+ }
+ }
+ call salloc (offsets, nimages*IM_NDIM(out[1]), TY_INT)
+ call ic_setout (Memi[in], out, Memi[offsets], nimages)
+
+ # Determine the highest precedence datatype and set output datatype.
+ intype = IM_PIXTYPE(Memi[in])
+ do i = 2, nimages
+ intype = ty_max (intype, IM_PIXTYPE(Memi[in+i-1]))
+ IM_PIXTYPE(out[1]) = getdatatype (clgetc ("outtype"))
+ if (IM_PIXTYPE(out[1]) == ERR)
+ IM_PIXTYPE(out[1]) = intype
+
+ # Open rejection masks
+ if (rmask[1] != EOS) {
+ tmp = ic_pmmap (rmask, NEW_COPY, out[1]); out[4] = tmp
+ IM_NDIM(out[4]) = IM_NDIM(out[4]) + 1
+ IM_LEN(out[4],IM_NDIM(out[4])) = nimages
+ if (!project) {
+ if (key == NULL)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ do i = 1, nimages {
+ j = imtrgetim (list, i, input, SZ_FNAME)
+ call sprintf (Memc[key], SZ_FNAME, "mask%04d")
+ call pargi (i)
+ call imastr (out[4], Memc[key], input)
+ }
+ }
+ } else
+ out[4] = NULL
+
+ # Open pixel list file if given.
+ if (plfile[1] != EOS) {
+ tmp = ic_pmmap (plfile, NEW_COPY, out[1]); out[2] = tmp
+ } else
+ out[2] = NULL
+
+ # Open the sigma image if given.
+ if (sigma[1] != EOS) {
+ tmp = immap (sigma, NEW_COPY, out[1]); out[3] = tmp
+ IM_PIXTYPE(out[3]) = ty_max (TY_REAL, IM_PIXTYPE(out[1]))
+ call sprintf (IM_TITLE(out[3]), SZ_IMTITLE,
+ "Combine sigma images for %s")
+ call pargstr (output)
+ } else
+ out[3] = NULL
+
+ # Open masks.
+ call ic_mopen (Memi[in], out, nimages)
+ icm = nimages
+
+ # Open the log file.
+ logfd = NULL
+ if (logfile[1] != EOS) {
+ iferr (logfd = open (logfile, APPEND, TEXT_FILE)) {
+ logfd = NULL
+ call erract (EA_WARN)
+ }
+ }
+
+ if (bufsize == 0) {
+ # Set initial IMIO buffer size based on the number of images
+ # and maximum amount of working memory available. The buffer
+ # size may be adjusted later if the task runs out of memory.
+ # The FUDGE factor is used to allow for the size of the
+ # program, memory allocator inefficiencies, and any other
+ # memory requirements besides IMIO.
+
+ bufsize = 1
+ do i = 1, IM_NDIM(out[1])
+ bufsize = bufsize * IM_LEN(out[1],i)
+ bufsize = bufsize * sizeof (intype)
+ bufsize = min (bufsize, DEFBUFSIZE)
+ memory = begmem ((nimages + 1) * bufsize, oldsize, maxsize)
+ memory = min (memory, int (FUDGE * maxsize))
+ bufsize = memory / (nimages + 1)
+ }
+
+ # Combine the images. If an out of memory error occurs close all
+ # images and files, divide the IMIO buffer size in half and try
+ # again. The integer types are not support because scaling is
+ # done on the input data vectors.
+
+ switch (ty_max (intype, IM_PIXTYPE(out[1]))) {
+ case TY_SHORT:
+ call icombines (Memi[in], out, Memi[offsets], nimages, bufsize)
+ case TY_USHORT, TY_INT, TY_LONG:
+ call icombinei (Memi[in], out, Memi[offsets], nimages, bufsize)
+ case TY_DOUBLE:
+ call icombined (Memi[in], out, Memi[offsets], nimages, bufsize)
+ case TY_COMPLEX:
+ call error (1, "Complex images not allowed")
+ default:
+ call icombiner (Memi[in], out, Memi[offsets], nimages, bufsize)
+ }
+ } then {
+ err = errget (errstr, SZ_LINE)
+ if (icm != NULL)
+ call ic_mclose (nimages)
+ if (!project) {
+ do j = 2, nimages {
+ if (Memi[in+j-1] != NULL)
+ call imunmap (Memi[in+j-1])
+ }
+ }
+ if (out[2] != NULL)
+ call imunmap (out[2])
+ if (out[3] != NULL) {
+ call imunmap (out[3])
+ call imdelete (sigma)
+ }
+ if (out[4] != NULL)
+ call imunmap (out[4])
+ if (out[1] != NULL) {
+ call imunmap (out[1])
+ call imdelete (output)
+ }
+ if (Memi[in] != NULL)
+ call imunmap (Memi[in])
+ if (logfd != NULL)
+ call close (logfd)
+
+ switch (err) {
+ case SYS_MFULL:
+ bufsize = bufsize / 2
+ call sfree (sp)
+ goto retry_
+ case SYS_FTOOMANYFILES, SYS_IKIOPEN, SYS_IKIOPIX:
+ if (!project) {
+ stack1 = YES
+ goto retry_
+ }
+ if (stack1 == YES)
+ call imdelete (input)
+ call fixmem (oldsize)
+ call sfree (sp)
+ call error (err, errstr)
+ default:
+ if (stack1 == YES)
+ call imdelete (input)
+ call fixmem (oldsize)
+ call sfree (sp)
+ call error (err, errstr)
+ }
+ }
+
+ # Unmap all the images, close the log file, and restore memory.
+ # The input images must be unmapped first to insure that there
+ # is a FD for the output images since the headers are opened to
+ # update them. However, the order of the NEW_COPY pointers must
+ # be preserved.
+
+ if (!project) {
+ do i = 2, nimages
+ if (Memi[in+i-1] != NULL)
+ call imunmap (Memi[in+i-1])
+ }
+ if (out[2] != NULL)
+ call imunmap (out[2])
+ if (out[3] != NULL)
+ call imunmap (out[3])
+ if (out[4] != NULL)
+ call imunmap (out[4])
+ if (out[1] != NULL)
+ call imunmap (out[1])
+ if (Memi[in] != NULL)
+ call imunmap (Memi[in])
+ if (stack1 == YES)
+ call imdelete (input)
+ if (logfd != NULL)
+ call close (logfd)
+ if (icm != NULL)
+ call ic_mclose (nimages)
+ call fixmem (oldsize)
+ call sfree (sp)
+end
+
+
+# TY_MAX -- Return the datatype of highest precedence.
+
+int procedure ty_max (type1, type2)
+
+int type1, type2 # Datatypes
+
+int i, j, type, order[8]
+data order/TY_SHORT,TY_USHORT,TY_INT,TY_LONG,TY_REAL,TY_DOUBLE,TY_COMPLEX,TY_REAL/
+
+begin
+ for (i=1; (i<=7) && (type1!=order[i]); i=i+1)
+ ;
+ for (j=1; (j<=7) && (type2!=order[j]); j=j+1)
+ ;
+ type = order[max(i,j)]
+
+ # Special case of mixing short and unsigned short.
+ if (type == TY_USHORT && type1 != type2)
+ type = TY_INT
+
+ return (type)
+end
+
+
+# IC_PMMAP -- Map pixel mask.
+
+pointer procedure ic_pmmap (fname, mode, refim)
+
+char fname[ARB] # Mask name
+int mode # Image mode
+pointer refim # Reference image
+pointer pm # IMIO pointer (returned)
+
+int i, fnextn()
+pointer sp, extn, immap()
+bool streq()
+
+begin
+ call smark (sp)
+ call salloc (extn, SZ_FNAME, TY_CHAR)
+
+ i = fnextn (fname, Memc[extn], SZ_FNAME)
+ if (streq (Memc[extn], "pl"))
+ pm = immap (fname, mode, refim)
+ else {
+ call strcpy (fname, Memc[extn], SZ_FNAME)
+ call strcat (".pl", Memc[extn], SZ_FNAME)
+ pm = immap (Memc[extn], mode, refim)
+ }
+
+ call sfree (sp)
+ return (pm)
+end
diff --git a/pkg/obsolete/imtitle.par b/pkg/obsolete/imtitle.par
new file mode 100644
index 00000000..be55db05
--- /dev/null
+++ b/pkg/obsolete/imtitle.par
@@ -0,0 +1,4 @@
+#IMTITLE -- Change the title of an image.
+
+image,f,a,,,,Image to be changed
+title,s,a,,,,New image title
diff --git a/pkg/obsolete/mkhistogram.par b/pkg/obsolete/mkhistogram.par
new file mode 100644
index 00000000..8f250459
--- /dev/null
+++ b/pkg/obsolete/mkhistogram.par
@@ -0,0 +1,7 @@
+file,s,a,,,,File name
+nbins,i,a,1,1,,Number of bins in histogram
+z1,r,h,INDEF,,,Minimum histogram intensity
+z2,r,h,INDEF,,,Maximum histogram intensity
+listout,b,h,yes,,,List instead of plot histogram
+device,s,h,"stdgraph",,,output graphics device
+mode,s,h,ql,,,
diff --git a/pkg/obsolete/mkpkg b/pkg/obsolete/mkpkg
new file mode 100644
index 00000000..a321582e
--- /dev/null
+++ b/pkg/obsolete/mkpkg
@@ -0,0 +1,41 @@
+# Make the OBSOLETE package.
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $update libpkg.a
+ $omake x_obsolete.x
+ $link x_obsolete.o libpkg.a -lxtools -o xx_obsolete.e
+ ;
+
+install:
+ $move xx_obsolete.e bin$x_obsolete.e
+ ;
+
+generic:
+ $set GEN = "$$generic -k"
+
+ $ifolder (generic/fixcol.x, fixcol.gx)
+ $(GEN) fixcol.gx -o generic/fixcol.x $endif
+ $ifolder (generic/fixline.x, fixline.gx)
+ $(GEN) fixline.gx -o generic/fixline.x $endif
+ ;
+
+libpkg.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+ @generic
+ @fits
+ @imcombine
+
+ t_fixpix.x <fset.h> <imhdr.h>
+ t_imtitle.x <imhdr.h>
+ t_mkhgm.x <gset.h> <mach.h>
+ t_oimstat.x <mach.h> <imhdr.h> "oimstat.h"
+ t_radplt.x <imhdr.h> <error.h> <mach.h> <gset.h>
+ ;
diff --git a/pkg/obsolete/obsolete.cl b/pkg/obsolete/obsolete.cl
new file mode 100644
index 00000000..26643d74
--- /dev/null
+++ b/pkg/obsolete/obsolete.cl
@@ -0,0 +1,14 @@
+#{ Package script task for the OBSOLETE package.
+
+package obsolete
+
+task imtitle,
+ mkhistogram,
+ ofixpix,
+ oimcombine,
+ oimstatistics,
+ orfits,
+ owfits,
+ radplt = obsolete$x_obsolete.e
+
+clbye
diff --git a/pkg/obsolete/obsolete.hd b/pkg/obsolete/obsolete.hd
new file mode 100644
index 00000000..58c60998
--- /dev/null
+++ b/pkg/obsolete/obsolete.hd
@@ -0,0 +1,15 @@
+# Help directory for the OBSOLETE package.
+
+$doc = "pkg$obsolete/doc/"
+$fits = "pkg$obsolete/fits/"
+
+imtitle hlp =doc$imtitle.hlp, src = t_imtitle.x
+mkhistogram hlp =doc$mkhistogram.hlp, src = t_mkhistogram.x
+ofixpix hlp =doc$ofixpix.hlp, src = t_fixpix.x
+oimcombine hlp =doc$oimcombine.hlp
+oimstatistics hlp =doc$oimstat.hlp
+orfits hlp =doc$orfits.hlp, src = fits$t_rfits.x
+owfits hlp =doc$owfits.hlp, src = fits$t_wfits.x
+radplt hlp =doc$radplt.hlp, src = t_radplt.x
+
+revisions sys=Revisions
diff --git a/pkg/obsolete/obsolete.men b/pkg/obsolete/obsolete.men
new file mode 100644
index 00000000..87b85715
--- /dev/null
+++ b/pkg/obsolete/obsolete.men
@@ -0,0 +1,11 @@
+ imtitle - Change the title of an image (noao.proto V2.9)
+ mkhistogram - List or plot the histogram of a data stream (noao.proto V2.9)
+ ofixpix - Fix bad pixels using text file (proto V2.10.4)
+ oimcombine - IMCOMBINE from V2.11-V2.11.3
+ oimstatistics - IMSTATISTICS from V2.11.3
+ orfits - Convert a FITS image into an IRAF image (dataio V2.10.4)
+ owfits - Convert an IRAF image into a FITS image (dataio V2.10.4)
+ radplt - Plot the radial profile of an object (noao.proto V2.9)
+
+
+ The previous package and release is listed in parenthesis
diff --git a/pkg/obsolete/obsolete.par b/pkg/obsolete/obsolete.par
new file mode 100644
index 00000000..da669776
--- /dev/null
+++ b/pkg/obsolete/obsolete.par
@@ -0,0 +1,3 @@
+# OBSOLETE package parameter file.
+
+version,s,h,"September 2001"
diff --git a/pkg/obsolete/ofixpix.par b/pkg/obsolete/ofixpix.par
new file mode 100644
index 00000000..c15397c9
--- /dev/null
+++ b/pkg/obsolete/ofixpix.par
@@ -0,0 +1,5 @@
+# FIXPIX -- Replace bad pixels by linear interpolation
+
+images,s,a,,,,Images to be modified
+badpixels,f,a,,,,Bad pixel regions file
+verbose,b,h,no,,,Print the image name and bad regions?
diff --git a/pkg/obsolete/oimcombine.par b/pkg/obsolete/oimcombine.par
new file mode 100644
index 00000000..e1f6b3c1
--- /dev/null
+++ b/pkg/obsolete/oimcombine.par
@@ -0,0 +1,38 @@
+# IMCOMBINE -- Image combine parameters
+
+input,s,a,,,,List of images to combine
+output,s,a,,,,List of output images
+rejmask,s,h,"",,,List of rejection masks (optional)
+plfile,s,h,"",,,List of pixel list files (optional)
+sigma,s,h,"",,,List of sigma images (optional)
+logfile,s,h,"STDOUT",,,"Log file
+"
+combine,s,h,"average","average|median",,Type of combine operation
+reject,s,h,"none","none|minmax|ccdclip|crreject|sigclip|avsigclip|pclip",,Type of rejection
+project,b,h,no,,,Project highest dimension of input images?
+outtype,s,h,"real","short|ushort|integer|long|real|double",,Output image pixel datatype
+offsets,f,h,"none",,,Input image offsets
+masktype,s,h,"none","none|goodvalue|badvalue|goodbits|badbits",,Mask type
+maskvalue,r,h,0,,,Mask value
+blank,r,h,0.,,,"Value if there are no pixels
+"
+scale,s,h,"none",,,Image scaling
+zero,s,h,"none",,,Image zero point offset
+weight,s,h,"none",,,Image weights
+statsec,s,h,"",,,Image section for computing statistics
+expname,s,h,"",,,"Image header exposure time keyword
+"
+lthreshold,r,h,INDEF,,,Lower threshold
+hthreshold,r,h,INDEF,,,Upper threshold
+nlow,i,h,1,0,,minmax: Number of low pixels to reject
+nhigh,i,h,1,0,,minmax: Number of high pixels to reject
+nkeep,i,h,1,,,Minimum to keep (pos) or maximum to reject (neg)
+mclip,b,h,yes,,,Use median in sigma clipping algorithms?
+lsigma,r,h,3.,0.,,Lower sigma clipping factor
+hsigma,r,h,3.,0.,,Upper sigma clipping factor
+rdnoise,s,h,"0.",,,ccdclip: CCD readout noise (electrons)
+gain,s,h,"1.",,,ccdclip: CCD gain (electrons/DN)
+snoise,s,h,"0.",,,ccdclip: Sensitivity noise (fraction)
+sigscale,r,h,0.1,0.,,Tolerance for sigma clipping scaling corrections
+pclip,r,h,-0.5,,,pclip: Percentile clipping parameter
+grow,r,h,0.,0.,,Radius (pixels) for neighbor rejection
diff --git a/pkg/obsolete/oimstat.h b/pkg/obsolete/oimstat.h
new file mode 100644
index 00000000..ba787642
--- /dev/null
+++ b/pkg/obsolete/oimstat.h
@@ -0,0 +1,50 @@
+# Header file for the IMSTATISTICS task.
+
+define LEN_IMSTAT 20
+
+define IS_SUMX Memd[P2D($1)]
+define IS_SUMX2 Memd[P2D($1+2)]
+define IS_SUMX3 Memd[P2D($1+4)]
+define IS_SUMX4 Memd[P2D($1+6)]
+define IS_LO Memr[P2R($1+8)]
+define IS_HI Memr[P2R($1+9)]
+define IS_MIN Memr[P2R($1+10)]
+define IS_MAX Memr[P2R($1+11)]
+define IS_MEAN Memr[P2R($1+12)]
+define IS_MEDIAN Memr[P2R($1+13)]
+define IS_MODE Memr[P2R($1+14)]
+define IS_STDDEV Memr[P2R($1+15)]
+define IS_SKEW Memr[P2R($1+16)]
+define IS_KURTOSIS Memr[P2R($1+17)]
+define IS_NPIX Memi[$1+18]
+
+define IS_FIELDS "|image|npix|min|max|mean|midpt|mode|stddev|skew|kurtosis|"
+
+define NFIELDS 10
+
+define IS_KIMAGE "IMAGE"
+define IS_KNPIX "NPIX"
+define IS_KMIN "MIN"
+define IS_KMAX "MAX"
+define IS_KMEAN "MEAN"
+define IS_KMEDIAN "MIDPT"
+define IS_KMODE "MODE"
+define IS_KSTDDEV "STDDEV"
+define IS_KSKEW "SKEW"
+define IS_KKURTOSIS "KURTOSIS"
+
+define IS_FIMAGE 1
+define IS_FNPIX 2
+define IS_FMIN 3
+define IS_FMAX 4
+define IS_FMEAN 5
+define IS_FMEDIAN 6
+define IS_FMODE 7
+define IS_FSTDDEV 8
+define IS_FSKEW 9
+define IS_FKURTOSIS 10
+
+define IS_FCOLUMN "%10d"
+define IS_FINTEGER "%10d"
+define IS_FREAL "%10.4g"
+define IS_FSTRING "%20s"
diff --git a/pkg/obsolete/oimstatistics.par b/pkg/obsolete/oimstatistics.par
new file mode 100644
index 00000000..9bb004dc
--- /dev/null
+++ b/pkg/obsolete/oimstatistics.par
@@ -0,0 +1,6 @@
+images,s,a,,,,Images
+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/pkg/obsolete/orfits.par b/pkg/obsolete/orfits.par
new file mode 100644
index 00000000..a5b1d704
--- /dev/null
+++ b/pkg/obsolete/orfits.par
@@ -0,0 +1,13 @@
+# FITS parameters
+fits_file,f,a,mta,,,FITS data source
+file_list,s,a,,,,File list
+iraf_file,f,a,,,,IRAF filename
+make_image,b,h,yes,,,Create an IRAF image?
+long_header,b,h,no,,,Print FITS header cards?
+short_header,b,h,yes,,,Print short header?
+datatype,s,h,"",,,IRAF data type
+blank,r,h,0.0,,,Blank value
+scale,b,h,yes,,,Scale the data?
+oldirafname,b,h,no,,,Use old IRAF name in place of iraf_file?
+offset,i,h,0,,,Tape file offset
+mode,s,h,ql,,,
diff --git a/pkg/obsolete/owfits.par b/pkg/obsolete/owfits.par
new file mode 100644
index 00000000..e89d1a58
--- /dev/null
+++ b/pkg/obsolete/owfits.par
@@ -0,0 +1,14 @@
+# FITS parameters
+iraf_files,s,a,,,,IRAF images
+fits_files,f,a,,,,FITS filename
+newtape,b,a,,,,Blank tape?
+make_image,b,h,yes,,,Create a FITS image?
+long_header,b,h,no,,,Print FITS header cards?
+short_header,b,h,yes,,,Print short header?
+bitpix,i,h,0,,,FITS bits per pixel
+blocking_factor,i,h,0,0,10,FITS tape blocking factor
+scale,b,h,yes,,,Scale data?
+autoscale,b,h,yes,,,Auto_scaling?
+bscale,r,a,1.0,,,FITS bscale
+bzero,r,a,0.0,,,FITS bzero
+mode,s,h,ql,,,
diff --git a/pkg/obsolete/radplt.par b/pkg/obsolete/radplt.par
new file mode 100644
index 00000000..cd296b1f
--- /dev/null
+++ b/pkg/obsolete/radplt.par
@@ -0,0 +1,5 @@
+input,s,a,,,,Image names
+x_init,r,a,,,,Approx x position of star
+y_init,r,a,,,,Approx y position of star
+cboxsize,i,h,5,3,,Size of extraction box
+rboxsize,i,h,21,3,,Size of profile extraction box
diff --git a/pkg/obsolete/t_fixpix.x b/pkg/obsolete/t_fixpix.x
new file mode 100644
index 00000000..4442cd32
--- /dev/null
+++ b/pkg/obsolete/t_fixpix.x
@@ -0,0 +1,172 @@
+include <imhdr.h>
+include <fset.h>
+
+# FIXPIX -- Interpolate over bad columns and lines.
+
+procedure t_fixpix ()
+
+char images[SZ_LINE] # Image template
+char badpixels[SZ_FNAME] # File containing the badpixel regions
+bool verbose # Print image names and regions?
+
+char imname[SZ_FNAME] # Image name
+pointer image # Image pointer
+
+int list, badpix
+
+int open(), imtopen(), imtgetim()
+bool clgetb()
+pointer immap()
+
+begin
+ # Get the image template and expand.
+
+ call clgstr ("images", images, SZ_LINE)
+ call clgstr ("badpixels", badpixels, SZ_FNAME)
+ verbose = clgetb ("verbose")
+ if (verbose)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ list = imtopen (images)
+
+ while (imtgetim (list, imname, SZ_FNAME) != EOF) {
+
+ if (verbose) {
+ call printf ("fixpix: %s\n")
+ call pargstr (imname)
+ }
+ image = immap (imname, READ_WRITE, 0)
+ badpix = open (badpixels, READ_ONLY, TEXT_FILE)
+ call fixpix (image, badpix, verbose)
+ call imunmap (image)
+ call close (badpix)
+ }
+
+ call imtclose (list)
+end
+
+procedure fixpix (image, badpix, verbose)
+
+pointer image # Image pointer
+int badpix # File pointer
+bool verbose # Print regions fixed?
+
+int x1, x2, y1, y2 # Bad region
+
+int temp, fscan(), nscan()
+
+begin
+ # Scan the bad pixel regions from the file.
+
+ while (fscan (badpix) != EOF) {
+ call gargi (x1)
+ call gargi (x2)
+ call gargi (y1)
+ call gargi (y2)
+ if (nscan () != 4)
+ next
+
+ if (x1 > x2) {
+ temp = x1; x1 = x2; x2 = temp
+ }
+ if (y1 > y2) {
+ temp = y1; y1 = y2; y2 = temp
+ }
+
+ # Check that the region is not the entire image.
+
+ if ((x1 == 1) && (x2 == IM_LEN (image, 1)) &&
+ (y1 == 1) && (y2 == IM_LEN (image, 2))) {
+ call eprintf ("Cannot fix an entire image")
+ next
+ }
+
+ # If the bad region spans entire lines interpolate lines.
+ if ((x1 == 1) && (x2 == IM_LEN (image, 1)))
+ call fixline (image, x1, x2, y1, y2, verbose)
+
+ # If the bad region spans entire columns interpolate columns.
+ else if ((y1 == 1) && (y2 == IM_LEN (image, 2)))
+ call fixcolumn (image, x1, x2, y1, y2, verbose)
+
+ # If the bad region is longer in the columns interpolate columns.
+ else if ((x2 - x1) < (y2 - y1))
+ call fixcolumn (image, x1, x2, y1, y2, verbose)
+
+ # If the bad region is longer in the lines interpolate lines.
+ else
+ call fixline (image, x1, x2, y1, y2, verbose)
+ }
+end
+
+# FIXLINE -- Switch to the appropriate generic procedure to optimize the
+# image I/O.
+
+procedure fixline (image, x1, x2, y1, y2, verbose)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+bool verbose # Print regions fixed?
+
+begin
+ if (verbose) {
+ call printf (" Interpolate lines for region %d %d %d %d\n")
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+ }
+
+ switch (IM_PIXTYPE (image)) {
+ case TY_SHORT:
+ call fixlines (image, x1, x2, y1, y2)
+ case TY_INT:
+ call fixlinei (image, x1, x2, y1, y2)
+ case TY_USHORT, TY_LONG:
+ call fixlinel (image, x1, x2, y1, y2)
+ case TY_REAL:
+ call fixliner (image, x1, x2, y1, y2)
+ case TY_DOUBLE:
+ call fixlined (image, x1, x2, y1, y2)
+ case TY_COMPLEX:
+ call fixlinex (image, x1, x2, y1, y2)
+ default:
+ call eprintf ("Unknown pixel type")
+ }
+end
+
+# FIXCOLUMN -- Switch to the appropriate generic procedure to optimize the
+# image I/O.
+
+procedure fixcolumn (image, x1, x2, y1, y2, verbose)
+
+pointer image # Image pointer
+int x1, x2, y1, y2 # Region to be fixed
+bool verbose # Print regions fixed?
+
+begin
+ if (verbose) {
+ call printf (" Interpolate columns for region %d %d %d %d\n")
+ call pargi (x1)
+ call pargi (x2)
+ call pargi (y1)
+ call pargi (y2)
+ }
+
+ switch (IM_PIXTYPE (image)) {
+ case TY_SHORT:
+ call fixcols (image, x1, x2, y1, y2)
+ case TY_INT:
+ call fixcoli (image, x1, x2, y1, y2)
+ case TY_USHORT, TY_LONG:
+ call fixcoll (image, x1, x2, y1, y2)
+ case TY_REAL:
+ call fixcolr (image, x1, x2, y1, y2)
+ case TY_DOUBLE:
+ call fixcold (image, x1, x2, y1, y2)
+ case TY_COMPLEX:
+ call fixcolx (image, x1, x2, y1, y2)
+ default:
+ call eprintf ("Unknown pixel type")
+ }
+end
diff --git a/pkg/obsolete/t_imtitle.x b/pkg/obsolete/t_imtitle.x
new file mode 100644
index 00000000..d4edeb35
--- /dev/null
+++ b/pkg/obsolete/t_imtitle.x
@@ -0,0 +1,21 @@
+include <imhdr.h>
+
+# T_IMTITLE -- Set the title of an image.
+
+procedure t_imtitle ()
+
+char image[SZ_FNAME] # Image to be editted
+
+pointer im, immap()
+
+begin
+ # Access image.
+ call clgstr ("image", image, SZ_FNAME)
+ im = immap (image, READ_WRITE, 0)
+
+ # Substitute new title.
+ call clgstr ("title", IM_TITLE(im), SZ_IMTITLE)
+
+ # Unmap image.
+ call imunmap (im)
+end
diff --git a/pkg/obsolete/t_mkhgm.x b/pkg/obsolete/t_mkhgm.x
new file mode 100644
index 00000000..6bc906dc
--- /dev/null
+++ b/pkg/obsolete/t_mkhgm.x
@@ -0,0 +1,137 @@
+include <mach.h>
+include <gset.h>
+
+define SZ_HISTBUF 512
+
+# HISTOGRAM -- Compute and plot the histogram of an file.
+
+procedure t_mkhistogram()
+
+bool listout
+int fd, ndata, nbins
+pointer sp, file, device, data, hgm, hgmr, gp
+real z1, z2, zmin, zmax, dz, zval
+
+bool clgetb(), fp_equalr()
+int i, clgeti(), open(), get_histdata()
+real clgetr()
+pointer gopen()
+
+begin
+ call smark (sp)
+ call salloc (file, SZ_LINE, TY_CHAR)
+ call salloc (device, SZ_FNAME, TY_CHAR)
+
+ # Get the file name.
+ call clgstr ("file", Memc[file], SZ_LINE)
+ fd = open (Memc[file], READ_ONLY, TEXT_FILE)
+
+ # Output can be either a list or a plot.
+ listout = clgetb ("listout")
+ if (! listout)
+ call clgstr ("device", Memc[device], SZ_FNAME)
+
+
+ # Get histogram length and allocate buffer.
+ nbins = clgeti ("nbins")
+ if (nbins < 2) {
+ call eprintf ("Warning: Less than 2 bins in histogram.\n")
+ call sfree (sp)
+ return
+ }
+ call salloc (hgm, nbins, TY_INT)
+ call salloc (hgmr, nbins, TY_REAL)
+
+ # Fetch the data.
+ call malloc (data, SZ_HISTBUF, TY_REAL)
+ ndata = get_histdata (fd, data, SZ_HISTBUF)
+ if (ndata <= 0) {
+ call eprintf ("Warning: No input data for histogram.\n")
+ call mfree (data, TY_REAL)
+ call sfree (sp)
+ return
+ }
+
+ z1 = clgetr ("z1")
+ z2 = clgetr ("z2")
+ if (IS_INDEFR(z1) || IS_INDEFR(z2)) {
+ call alimr (Memr[data], ndata, zmin, zmax)
+ if (IS_INDEFR(z1))
+ z1 = zmin
+ if (IS_INDEFR(z2))
+ z2 = zmax
+ }
+ dz = (z2 - z1) / (nbins - 1)
+
+ # Test for constant valued file, which causes zero divide in ahgm.
+ if (fp_equalr (z1, z2)) {
+ call eprintf (
+ "Warning: Constant valued file `%s' has no data range.\n")
+ call pargstr (Memc[file])
+ call mfree (data, TY_REAL)
+ call sfree (sp)
+ return
+ }
+
+ # Initialize histogram and file line vector.
+ call aclri (Memi[hgm], nbins)
+
+ # Accumulate the histogram.
+ call ahgmr (Memr[data], ndata, Memi[hgm], nbins, z1, z2)
+
+ # List or plot the histogram.
+ if (listout) {
+ zval = z1
+ do i = 1, nbins {
+ call printf ("%4d %g %d\n")
+ call pargi (i)
+ call pargr (zval + dz / 2.)
+ call pargi (Memi[hgm+i-1])
+ zval = zval + dz
+ }
+ } else {
+ gp = gopen (Memc[device], NEW_FILE, STDGRAPH)
+ #call gseti (gp, G_YTRAN, GW_LOG)
+ call achtir (Memi[hgm], Memr[hgmr], nbins)
+ call gploto (gp, Memr[hgmr], nbins, z1 + dz / 2., z2 + dz / 2.,
+ Memc[file])
+ call gclose (gp)
+ }
+
+ # Shutdown.
+ call close (fd)
+ call sfree (sp)
+end
+
+
+# GET_HISTDATA -- Procedure to get data for the histogram
+
+int procedure get_histdata (fd, data, buf_incr)
+
+int fd # file descriptor of histogram data
+pointer data # pointer to the data array
+int buf_incr # increment for data buffer size
+
+int szbuf, ndata
+int fscan(), nscan()
+
+begin
+ szbuf = buf_incr
+ ndata = 0
+ while (fscan (fd) != EOF) {
+ call gargr (Memr[data+ndata])
+ if (nscan() != 1)
+ next
+ ndata = ndata + 1
+ if (ndata == szbuf) {
+ szbuf = szbuf + buf_incr
+ call realloc (data, szbuf, TY_REAL)
+ }
+ }
+
+ # Fit the buffer size to the data.
+ if (ndata > 0)
+ call realloc (data, ndata, TY_REAL)
+
+ return (ndata)
+end
diff --git a/pkg/obsolete/t_oimstat.x b/pkg/obsolete/t_oimstat.x
new file mode 100644
index 00000000..417d1eed
--- /dev/null
+++ b/pkg/obsolete/t_oimstat.x
@@ -0,0 +1,1014 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <imhdr.h>
+include "oimstat.h"
+
+
+# T_OIMSTATISTICS -- Compute and print the statistics of images.
+
+procedure t_oimstatistics ()
+
+pointer fieldstr # Pointer to fields string
+real lower # Lower limit of data value window
+real upper # Upper limit of data value window
+real binwidth # Width of histogram bin in sigma
+int format # Format the output
+
+int nfields, nbins
+int minmax, npix, mean, median, mode, stddev, skew, kurtosis
+pointer sp, fields, image, v
+pointer im, list, ist, buf, hgm
+real hwidth, hmin, hmax
+
+bool clgetb()
+int ist_fields(), ist_isfield, imtgetim(), ist_ihist(), btoi()
+pointer imtopenp(), imgnlr()
+real clgetr()
+pointer immap()
+
+begin
+ call smark (sp)
+ call salloc (fieldstr, SZ_LINE, TY_CHAR)
+ call salloc (fields, NFIELDS, TY_INT)
+ call salloc (ist, LEN_IMSTAT, TY_STRUCT)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (v, IM_MAXDIM, TY_LONG)
+
+ # Open the list of input images, the fields and the data value limits.
+ list = imtopenp ("images")
+ call clgstr ("fields", Memc[fieldstr], SZ_LINE)
+ lower = clgetr ("lower")
+ upper = clgetr ("upper")
+ binwidth = clgetr ("binwidth")
+ format = btoi (clgetb ("format"))
+
+ # Get the selected fields.
+ nfields = ist_fields (Memc[fieldstr], Memi[fields], NFIELDS)
+ if (nfields <= 0) {
+ call imtclose (list)
+ call sfree (sp)
+ return
+ }
+
+ # Set the computation switches.
+ npix = ist_isfield (IS_FNPIX, Memi[fields], nfields)
+ mean = ist_isfield (IS_FMEAN, Memi[fields], nfields)
+ median = ist_isfield (IS_FMEDIAN, Memi[fields], nfields)
+ mode = ist_isfield (IS_FMODE, Memi[fields], nfields)
+ stddev = ist_isfield (IS_FSTDDEV, Memi[fields], nfields)
+ skew = ist_isfield (IS_FSKEW, Memi[fields], nfields)
+ kurtosis = ist_isfield (IS_FKURTOSIS, Memi[fields], nfields)
+ if (ist_isfield (IS_FMIN, Memi[fields], nfields) == YES)
+ minmax = YES
+ else if (ist_isfield (IS_FMAX, Memi[fields], nfields) == YES)
+ minmax = YES
+ else if (median == YES || mode == YES)
+ minmax = YES
+ else
+ minmax = NO
+
+ # Print a header banner for the selected fields.
+ if (format == YES)
+ call ist_pheader (Memi[fields], nfields)
+
+ # Loop through the input images.
+ while (imtgetim (list, Memc[image], SZ_FNAME) != EOF) {
+
+ im = immap (Memc[image], READ_ONLY, 0)
+ call ist_initialize (ist, lower, upper)
+
+ # Accumulate the central moment statistics.
+ call amovkl (long(1), Meml[v], IM_MAXDIM)
+ if (kurtosis == YES) {
+ while (imgnlr (im, buf, Meml[v]) != EOF)
+ call ist_accumulate4 (ist, Memr[buf], int (IM_LEN(im, 1)),
+ lower, upper, minmax)
+ } else if (skew == YES) {
+ while (imgnlr (im, buf, Meml[v]) != EOF)
+ call ist_accumulate3 (ist, Memr[buf], int (IM_LEN (im, 1)),
+ lower, upper, minmax)
+ } else if (stddev == YES || median == YES || mode == YES) {
+ while (imgnlr (im, buf, Meml[v]) != EOF)
+ call ist_accumulate2 (ist, Memr[buf], int (IM_LEN(im,1)),
+ lower, upper, minmax)
+ } else if (mean == YES) {
+ while (imgnlr (im, buf, Meml[v]) != EOF)
+ call ist_accumulate1 (ist, Memr[buf], int (IM_LEN(im,1)),
+ lower, upper, minmax)
+ } else if (npix == YES) {
+ while (imgnlr (im, buf, Meml[v]) != EOF)
+ call ist_accumulate0 (ist, Memr[buf], int (IM_LEN(im,1)),
+ lower, upper, minmax)
+ } else if (minmax == YES) {
+ while (imgnlr (im, buf, Meml[v]) != EOF)
+ call ist_accumulate0 (ist, Memr[buf], int (IM_LEN(im,1)),
+ lower, upper, YES)
+ }
+
+ # Compute the central moment statistics.
+ call ist_stats (ist, skew, kurtosis)
+
+ # Accumulate the histogram.
+ hgm = NULL
+ if ((median == YES || mode == YES) && ist_ihist (ist, binwidth,
+ hgm, nbins, hwidth, hmin, hmax) == YES) {
+ call aclri (Memi[hgm], nbins)
+ call amovkl (long(1), Meml[v], IM_MAXDIM)
+ while (imgnlr (im, buf, Meml[v]) != EOF)
+ call ahgmr (Memr[buf], int(IM_LEN(im,1)), Memi[hgm], nbins,
+ hmin, hmax)
+ if (median == YES)
+ call ist_hmedian (ist, Memi[hgm], nbins, hwidth, hmin,
+ hmax)
+ if (mode == YES)
+ call ist_hmode (ist, Memi[hgm], nbins, hwidth, hmin, hmax)
+ }
+
+ # Print the statistics.
+ if (format == YES)
+ call ist_print (Memc[image], ist, Memi[fields], nfields)
+ else
+ call ist_fprint (Memc[image], ist, Memi[fields], nfields)
+
+ if (hgm != NULL)
+ call mfree (hgm, TY_INT)
+ call imunmap (im)
+ }
+
+ call imtclose (list)
+ call sfree (sp)
+end
+
+
+# IST_FIELDS -- Procedure to decode the fields string into a list of the
+# fields to be computed and printed.
+
+int procedure ist_fields (fieldstr, fields, max_nfields)
+
+char fieldstr[ARB] # string containing the list of fields
+int fields[ARB] # fields array
+int max_nfields # maximum number of fields
+
+int nfields, flist, field
+pointer sp, fname
+int fntopnb(), fntgfnb(), strdic()
+
+begin
+ nfields = 0
+
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+
+ flist = fntopnb (fieldstr, NO)
+ while (fntgfnb (flist, Memc[fname], SZ_FNAME) != EOF &&
+ (nfields < max_nfields)) {
+ field = strdic (Memc[fname], Memc[fname], SZ_FNAME, IS_FIELDS)
+ if (field == 0)
+ next
+ nfields = nfields + 1
+ fields[nfields] = field
+ }
+ call fntclsb (flist)
+
+ call sfree (sp)
+
+ return (nfields)
+end
+
+
+# IST_ISFIELD -- Procedure to determine whether a specified field is one
+# of the selected fields or not.
+
+int procedure ist_isfield (field, fields, nfields)
+
+int field # field to be tested
+int fields[ARB] # array of selected fields
+int nfields # number of fields
+
+int i, isfield
+
+begin
+ isfield = NO
+ do i = 1, nfields {
+ if (field != fields[i])
+ next
+ isfield = YES
+ break
+ }
+
+ return (isfield)
+end
+
+
+# IST_INITIALIZE -- Initialize the sum array to zero.
+
+procedure ist_initialize (ist, lower, upper)
+
+pointer ist # pointer to the statistics structure
+real lower # lower datalimit
+real upper # upperlimit
+
+begin
+ if (IS_INDEFR(lower))
+ IS_LO(ist) = -MAX_REAL
+ else
+ IS_LO(ist) = lower
+ if (IS_INDEFR(upper))
+ IS_HI(ist) = MAX_REAL
+ else
+ IS_HI(ist) = upper
+
+ IS_NPIX(ist) = 0
+ IS_SUMX(ist) = 0.0d0
+ IS_SUMX2(ist) = 0.0d0
+ IS_SUMX3(ist) = 0.0d0
+ IS_SUMX4(ist) = 0.0d0
+
+ IS_MIN(ist) = MAX_REAL
+ IS_MAX(ist) = -MAX_REAL
+ IS_MEAN(ist) = INDEFR
+ IS_MEDIAN(ist) = INDEFR
+ IS_MODE(ist) = INDEFR
+ IS_STDDEV(ist) = INDEFR
+ IS_SKEW(ist) = INDEFR
+ IS_KURTOSIS(ist) = INDEFR
+end
+
+
+# IST_ACCUMULATE4 -- Accumulate sums up to the fourth power of the data for
+# data values between lower and upper.
+
+procedure ist_accumulate4 (is, x, npts, lower, upper, minmax)
+
+pointer is # pointer to the statistics structure
+real x[ARB] # the data array
+int npts # the number of data points
+real lower # lower data boundary
+real upper # upper data boundary
+int minmax # compute the minimum and maximum
+
+int i, npix
+real lo, hi, xmin, xmax
+double xx, xx2, sumx, sumx2, sumx3, sumx4
+
+begin
+ lo = IS_LO(is)
+ hi = IS_HI(is)
+ npix = IS_NPIX(is)
+ sumx = 0.0
+ sumx2 = 0.0
+ sumx3 = 0.0
+ sumx4 = 0.0
+ xmin = IS_MIN(is)
+ xmax = IS_MAX(is)
+
+ if (IS_INDEFR(lower) && IS_INDEFR(upper)) {
+ npix = npix + npts
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ sumx4 = sumx4 + xx2 * xx2
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ sumx4 = sumx4 + xx2 * xx2
+ }
+ }
+ } else {
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ npix = npix + 1
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ sumx4 = sumx4 + xx2 * xx2
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ npix = npix + 1
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ sumx4 = sumx4 + xx2 * xx2
+ }
+ }
+ }
+
+ IS_NPIX(is) = npix
+ IS_SUMX(is) = IS_SUMX(is) + sumx
+ IS_SUMX2(is) = IS_SUMX2(is) + sumx2
+ IS_SUMX3(is) = IS_SUMX3(is) + sumx3
+ IS_SUMX4(is) = IS_SUMX4(is) + sumx4
+ IS_MIN(is) = xmin
+ IS_MAX(is) = xmax
+end
+
+
+# IST_ACCUMULATE3 -- Accumulate sums up to the third power of the data for
+# data values between lower and upper.
+
+procedure ist_accumulate3 (is, x, npts, lower, upper, minmax)
+
+pointer is # pointer to the statistics structure
+real x[ARB] # the data array
+int npts # the number of data points
+real lower # lower data boundary
+real upper # upper data boundary
+int minmax # compute the minimum and maximum
+
+int i, npix
+real lo, hi, xmin, xmax
+double xx, xx2, sumx, sumx2, sumx3
+
+begin
+ lo = IS_LO(is)
+ hi = IS_HI(is)
+ npix = IS_NPIX(is)
+ sumx = 0.0
+ sumx2 = 0.0
+ sumx3 = 0.0
+ xmin = IS_MIN(is)
+ xmax = IS_MAX(is)
+
+ if (IS_INDEFR(lower) && IS_INDEFR(upper)) {
+ npix = npix + npts
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ }
+ }
+ } else {
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ npix = npix + 1
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ npix = npix + 1
+ xx2 = xx * xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx2
+ sumx3 = sumx3 + xx2 * xx
+ }
+ }
+ }
+
+ IS_NPIX(is) = npix
+ IS_SUMX(is) = IS_SUMX(is) + sumx
+ IS_SUMX2(is) = IS_SUMX2(is) + sumx2
+ IS_SUMX3(is) = IS_SUMX3(is) + sumx3
+ IS_MIN(is) = xmin
+ IS_MAX(is) = xmax
+end
+
+
+# IST_ACCUMULATE2 -- Accumulate sums up to the second power of the data for
+# data values between lower and upper.
+
+procedure ist_accumulate2 (is, x, npts, lower, upper, minmax)
+
+pointer is # pointer to the statistics structure
+real x[ARB] # the data array
+int npts # the number of data points
+real lower # lower data boundary
+real upper # upper data boundary
+int minmax # compute the minimum and maximum
+
+int i, npix
+real lo, hi, xmin, xmax
+double xx, sumx, sumx2
+
+begin
+ lo = IS_LO(is)
+ hi = IS_HI(is)
+ npix = IS_NPIX(is)
+ sumx = 0.0
+ sumx2 = 0.0
+ xmin = IS_MIN(is)
+ xmax = IS_MAX(is)
+
+ if (IS_INDEFR(lower) && IS_INDEFR(upper)) {
+ npix = npix + npts
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx * xx
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx * xx
+ }
+ }
+ } else {
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ npix = npix + 1
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx * xx
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ npix = npix + 1
+ sumx = sumx + xx
+ sumx2 = sumx2 + xx * xx
+ }
+ }
+ }
+
+ IS_NPIX(is) = npix
+ IS_SUMX(is) = IS_SUMX(is) + sumx
+ IS_SUMX2(is) = IS_SUMX2(is) + sumx2
+ IS_MIN(is) = xmin
+ IS_MAX(is) = xmax
+end
+
+
+# IST_ACCUMULATE1 -- Accumulate sums up to the first power of the data for
+# data values between lower and upper.
+
+procedure ist_accumulate1 (is, x, npts, lower, upper, minmax)
+
+pointer is # pointer to the statistics structure
+real x[ARB] # the data array
+int npts # the number of data points
+real lower # lower data boundary
+real upper # upper data boundary
+int minmax # compute the minimum and maximum
+
+int i, npix
+real lo, hi, xx, xmin, xmax
+double sumx
+
+begin
+ lo = IS_LO(is)
+ hi = IS_HI(is)
+ npix = IS_NPIX(is)
+ sumx = 0.0
+ xmin = IS_MIN(is)
+ xmax = IS_MAX(is)
+
+ if (IS_INDEFR(lower) && IS_INDEFR(upper)) {
+ npix = npix + npts
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ sumx = sumx + xx
+ }
+ } else {
+ do i = 1, npts
+ sumx = sumx + x[i]
+ }
+ } else {
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ npix = npix + 1
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ sumx = sumx + xx
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ npix = npix + 1
+ sumx = sumx + xx
+ }
+ }
+ }
+
+ IS_NPIX(is) = npix
+ IS_SUMX(is) = IS_SUMX(is) + sumx
+ IS_MIN(is) = xmin
+ IS_MAX(is) = xmax
+end
+
+
+# IST_ACCUMULATE0 -- Accumulate sums up to the 0th power of the data for
+# data values between lower and upper.
+
+procedure ist_accumulate0 (is, x, npts, lower, upper, minmax)
+
+pointer is # pointer to the statistics structure
+real x[ARB] # the data array
+int npts # the number of data points
+real lower # lower data boundary
+real upper # upper data boundary
+int minmax # compute the minimum and maximum
+
+int i, npix
+real lo, hi, xx, xmin, xmax
+
+begin
+ lo = IS_LO(is)
+ hi = IS_HI(is)
+ npix = IS_NPIX(is)
+ xmin = IS_MIN(is)
+ xmax = IS_MAX(is)
+
+ if (IS_INDEFR(lower) && IS_INDEFR(upper)) {
+ npix = npix + npts
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ }
+ }
+ } else {
+ if (minmax == YES) {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ npix = npix + 1
+ if (xx < xmin)
+ xmin = xx
+ if (xx > xmax)
+ xmax = xx
+ }
+ } else {
+ do i = 1, npts {
+ xx = x[i]
+ if (xx < lo || xx > hi)
+ next
+ npix = npix + 1
+ }
+ }
+ }
+
+ IS_NPIX(is) = npix
+ IS_MIN(is) = xmin
+ IS_MAX(is) = xmax
+end
+
+
+# IST_STATS -- Procedure to compute the first four central moments of the
+# distribution.
+
+procedure ist_stats (ist, bskew, bkurtosis)
+
+pointer ist # statistics structure
+int bskew # skew switch
+int bkurtosis # kurtosis switch
+
+double mean, var, stdev
+bool fp_equalr()
+
+begin
+ if (fp_equalr (IS_MIN(ist), MAX_REAL))
+ IS_MIN(ist) = INDEFR
+ if (fp_equalr (IS_MAX(ist), -MAX_REAL))
+ IS_MAX(ist) = INDEFR
+
+ if (IS_NPIX(ist) <= 0)
+ return
+ mean = IS_SUMX(ist) / IS_NPIX(ist)
+ IS_MEAN(ist) = mean
+
+ if (IS_NPIX(ist) < 2)
+ return
+ var = (IS_SUMX2(ist) - IS_SUMX(ist) * mean) /
+ (IS_NPIX(ist) - 1)
+ if (var <= 0.0) {
+ IS_STDDEV(ist) = 0.0
+ return
+ } else {
+ stdev = sqrt (var)
+ IS_STDDEV(ist) = stdev
+ }
+
+ if (bskew == YES)
+ IS_SKEW(ist) = (IS_SUMX3(ist) - 3.0d0 * IS_MEAN(ist) *
+ IS_SUMX2(ist) + 3.0d0 * mean * mean *
+ IS_SUMX(ist) - IS_NPIX(ist) * mean ** 3) /
+ IS_NPIX(ist) / stdev / stdev / stdev
+
+ if (bkurtosis == YES)
+ IS_KURTOSIS(ist) = (IS_SUMX4(ist) - 4.0d0 * mean *
+ IS_SUMX3(ist) + 6.0d0 * mean * mean *
+ IS_SUMX2(ist) - 4.0 * mean ** 3 * IS_SUMX(ist) +
+ IS_NPIX(ist) * mean ** 4) / IS_NPIX(ist) /
+ stdev / stdev / stdev / stdev - 3.0d0
+end
+
+
+# IST_IHIST -- Procedure to initilaize the histogram of the image pixels.
+
+int procedure ist_ihist (ist, binwidth, hgm, nbins, hwidth, hmin, hmax)
+
+pointer ist # pointer to the statistics structure
+real binwidth # histogram bin width in sigma
+pointer hgm # pointer to the histogram
+int nbins # number of bins
+real hwidth # histogram resolution
+real hmin # minimum histogram value
+real hmax # maximum histogram value
+
+begin
+ nbins = 0
+ if (binwidth <= 0.0)
+ return (NO)
+ hwidth = binwidth * IS_STDDEV(ist)
+ if (hwidth <= 0.0)
+ return (NO)
+ nbins = (IS_MAX(ist) - IS_MIN(ist)) / hwidth + 1
+ if (nbins < 3)
+ return (NO)
+
+ hmin = IS_MIN(ist)
+ hmax = IS_MAX(ist)
+ call malloc (hgm, nbins, TY_INT)
+ return (YES)
+end
+
+
+# IST_HMEDIAN -- Procedure to compute the median of the values.
+
+procedure ist_hmedian (ist, hgm, nbins, hwidth, hmin, hmax)
+
+pointer ist # pointer to the statistics strucuture
+int hgm[ARB] # histogram of the pixels
+int nbins # number of bins in the histogram
+real hwidth # resolution of the histogram
+real hmin # minimum histogram value
+real hmax # maximum histogram value
+
+int i, lo, hi
+pointer sp, ihgm
+real h1, hdiff, hnorm
+bool fp_equalr()
+
+begin
+ call smark (sp)
+ call salloc (ihgm, nbins, TY_REAL)
+
+ # Integrate the histogram and normalize.
+ Memr[ihgm] = hgm[1]
+ do i = 2, nbins
+ Memr[ihgm+i-1] = hgm[i] + Memr[ihgm+i-2]
+ hnorm = Memr[ihgm+nbins-1]
+ call adivkr (Memr[ihgm], hnorm, Memr[ihgm], nbins)
+
+ # Initialize the low and high bin numbers.
+ lo = 0
+ hi = 1
+
+ # Search for the point which divides the integral in half.
+ do i = 1, nbins {
+ if (Memr[ihgm+i-1] > 0.5)
+ break
+ lo = i
+ }
+ hi = lo + 1
+ #call eprintf (
+ #"hmin=%g hmax=%g hw=%g nbins=%d lo=%d ih(lo)=%g hi=%d ih(hi)=%g\n")
+ #call pargr (hmin)
+ #call pargr (hmax)
+ #call pargr (hwidth)
+ #call pargi (nbins)
+ #call pargi (lo)
+ #call pargr (Memr[ihgm+lo-1])
+ #call pargi (hi)
+ #call pargr (Memr[ihgm+hi-1])
+
+ # Approximate the histogram.
+ h1 = hmin + lo * hwidth
+ if (lo == 0)
+ hdiff = Memr[ihgm+hi-1]
+ else
+ hdiff = Memr[ihgm+hi-1] - Memr[ihgm+lo-1]
+ if (fp_equalr (hdiff, 0.0))
+ IS_MEDIAN(ist) = h1
+ else if (lo == 0)
+ IS_MEDIAN(ist) = h1 + 0.5 / hdiff * hwidth
+ else
+ IS_MEDIAN(ist) = h1 + (0.5 - Memr[ihgm+lo-1]) / hdiff * hwidth
+ #call eprintf ("hlo=%g hhi=%g h1=%g hdiff=%g median=%g\n")
+ #call pargr (hmin)
+ #call pargr (hmin + (nbins - 1) * hwidth)
+ #call pargr (h1)
+ #call pargr (hdiff)
+ #call pargr (IS_MEDIAN(ist))
+
+ call sfree (sp)
+end
+
+
+# IST_HMODE -- Procedure to compute the mode.
+
+procedure ist_hmode (ist, hgm, nbins, hwidth, hmin, hmax)
+
+pointer ist # pointer to the statistics strucuture
+int hgm[ARB] # histogram of the pixels
+int nbins # number of bins in the histogram
+real hwidth # resolution of the histogram
+real hmin # minimum histogram value
+real hmax # maximum histogram value
+
+int i, bpeak
+real hpeak, dh1, dh2, denom
+bool fp_equalr()
+
+begin
+ # If there is a single bin return the midpoint of that bin.
+ if (nbins == 1) {
+ IS_MODE(ist) = hmin + 0.5 * hwidth
+ return
+ }
+
+ # If there are two bins return the midpoint of the greater bin.
+ if (nbins == 2) {
+ if (hgm[1] > hgm[2])
+ IS_MODE(ist) = hmin + 0.5 * hwidth
+ else if (hgm[2] > hgm[1])
+ IS_MODE(ist) = hmin + 1.5 * hwidth
+ else
+ IS_MODE(ist) = hmin + hwidth
+ return
+ }
+
+ # Find the bin containing the histogram maximum.
+ hpeak = hgm[1]
+ bpeak = 1
+ do i = 2, nbins {
+ if (hgm[i] > hpeak) {
+ hpeak = hgm[i]
+ bpeak = i
+ }
+ }
+
+ # If the maximum is in the first bin return the midpoint of the bin.
+ if (bpeak == 1) {
+ IS_MODE(ist) = hmin + 0.5 * hwidth
+ return
+ }
+
+ # If the maximum is in the last bin return the midpoint of the bin.
+ if (bpeak == nbins) {
+ IS_MODE(ist) = hmin + (nbins - 0.5) * hwidth
+ return
+ }
+
+ # Compute the lower limit of bpeak.
+ bpeak = bpeak - 1
+
+ # Do a parabolic interpolation to find the peak.
+ dh1 = hgm[bpeak+1] - hgm[bpeak]
+ dh2 = hgm[bpeak+1] - hgm[bpeak+2]
+ denom = dh1 + dh2
+ if (fp_equalr (denom, 0.0)) {
+ IS_MODE(ist) = hmin + (bpeak + 0.5) * hwidth
+ } else {
+ IS_MODE(ist) = bpeak + 1 + 0.5 * (dh1 - dh2) / denom
+ IS_MODE(ist) = hmin + (IS_MODE(ist) - 0.5) * hwidth
+ }
+
+
+ dh1 = hgm[bpeak] * (hmin + (bpeak - 0.5) * hwidth) +
+ hgm[bpeak+1] * (hmin + (bpeak + 0.5) * hwidth) +
+ hgm[bpeak+2] * (hmin + (bpeak + 1.5) * hwidth)
+ dh2 = hgm[bpeak] + hgm[bpeak+1] + hgm[bpeak+2]
+end
+
+
+# IST_PHEADER -- Print the banner fields.
+
+procedure ist_pheader (fields, nfields)
+
+int fields[ARB] # fields to be printed
+int nfields # number of fields
+
+int i
+
+begin
+ call printf ("#")
+ do i = 1, nfields {
+ switch (fields[i]) {
+ case IS_FIMAGE:
+ call printf (IS_FSTRING)
+ call pargstr (IS_KIMAGE)
+ case IS_FNPIX:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KNPIX)
+ case IS_FMIN:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KMIN)
+ case IS_FMAX:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KMAX)
+ case IS_FMEAN:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KMEAN)
+ case IS_FMEDIAN:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KMEDIAN)
+ case IS_FMODE:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KMODE)
+ case IS_FSTDDEV:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KSTDDEV)
+ case IS_FSKEW:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KSKEW)
+ case IS_FKURTOSIS:
+ call printf (IS_FCOLUMN)
+ call pargstr (IS_KKURTOSIS)
+ }
+ }
+
+ call printf ("\n")
+ call flush (STDOUT)
+end
+
+
+# IST_PRINT -- Print the fields
+
+procedure ist_print (image, ist, fields, nfields)
+
+char image[ARB] # image name
+pointer ist # pointer to the statistics structure
+int fields[ARB] # fields to be printed
+int nfields # number of fields
+
+int i
+
+begin
+ call printf (" ")
+ do i = 1, nfields {
+ switch (fields[i]) {
+ case IS_FIMAGE:
+ call printf (IS_FSTRING)
+ call pargstr (image)
+ case IS_FNPIX:
+ call printf (IS_FINTEGER)
+ call pargi (IS_NPIX(ist))
+ case IS_FMIN:
+ call printf (IS_FREAL)
+ call pargr (IS_MIN(ist))
+ case IS_FMAX:
+ call printf (IS_FREAL)
+ call pargr (IS_MAX(ist))
+ case IS_FMEAN:
+ call printf (IS_FREAL)
+ call pargr (IS_MEAN(ist))
+ case IS_FMEDIAN:
+ call printf (IS_FREAL)
+ call pargr (IS_MEDIAN(ist))
+ case IS_FMODE:
+ call printf (IS_FREAL)
+ call pargr (IS_MODE(ist))
+ case IS_FSTDDEV:
+ call printf (IS_FREAL)
+ call pargr (IS_STDDEV(ist))
+ case IS_FSKEW:
+ call printf (IS_FREAL)
+ call pargr (IS_SKEW(ist))
+ case IS_FKURTOSIS:
+ call printf (IS_FREAL)
+ call pargr (IS_KURTOSIS(ist))
+ }
+ }
+
+ call printf ("\n")
+ call flush (STDOUT)
+end
+
+
+# IST_FPRINT -- Print the fields using a free format.
+
+procedure ist_fprint (image, ist, fields, nfields)
+
+char image[ARB] # image name
+pointer ist # pointer to the statistics structure
+int fields[ARB] # fields to be printed
+int nfields # number of fields
+
+int i
+
+begin
+ do i = 1, nfields {
+ switch (fields[i]) {
+ case IS_FIMAGE:
+ call printf ("%s")
+ call pargstr (image)
+ case IS_FNPIX:
+ call printf ("%d")
+ call pargi (IS_NPIX(ist))
+ case IS_FMIN:
+ call printf ("%g")
+ call pargr (IS_MIN(ist))
+ case IS_FMAX:
+ call printf ("%g")
+ call pargr (IS_MAX(ist))
+ case IS_FMEAN:
+ call printf ("%g")
+ call pargr (IS_MEAN(ist))
+ case IS_FMEDIAN:
+ call printf ("%g")
+ call pargr (IS_MEDIAN(ist))
+ case IS_FMODE:
+ call printf ("%g")
+ call pargr (IS_MODE(ist))
+ case IS_FSTDDEV:
+ call printf ("%g")
+ call pargr (IS_STDDEV(ist))
+ case IS_FSKEW:
+ call printf ("%g")
+ call pargr (IS_SKEW(ist))
+ case IS_FKURTOSIS:
+ call printf ("%g")
+ call pargr (IS_KURTOSIS(ist))
+ }
+ if (i < nfields)
+ call printf (" ")
+ }
+
+ call printf ("\n")
+ call flush (STDOUT)
+end
diff --git a/pkg/obsolete/t_radplt.x b/pkg/obsolete/t_radplt.x
new file mode 100644
index 00000000..49f153e7
--- /dev/null
+++ b/pkg/obsolete/t_radplt.x
@@ -0,0 +1,305 @@
+include <imhdr.h>
+include <error.h>
+include <mach.h>
+include <gset.h>
+
+define EXTRA_HT 0.1
+define SZ_TITLE 512
+
+# T_RADPLT -- Generate a radial profile plot around a star center.
+
+procedure t_radplt()
+
+char ifile[SZ_FNAME]
+int infile, nfiles
+
+pointer im
+int cboxsize, rboxsize
+real xinit, yinit, xcntr, ycntr
+
+int clpopni(), clplen(), clgfil()
+int clgeti()
+real clgetr()
+pointer immap()
+
+begin
+ # Get file names
+ infile = clpopni ("input")
+ nfiles = clplen (infile)
+
+ # Get x and y initial
+ xinit = clgetr ("x_init")
+ yinit = clgetr ("y_init")
+
+ # Get box size to use for centering
+ cboxsize = clgeti ("cboxsize")
+
+ # Get box size to use for radial plot
+ rboxsize = clgeti ("rboxsize")
+
+ # Loop over all images
+ while (clgfil (infile, ifile, SZ_FNAME) != EOF) {
+ iferr (im = immap (ifile, READ_ONLY, 0)) {
+ call eprintf ("[%s] not found\n")
+ call pargstr (ifile)
+ next
+ }
+
+ # Find star center
+ call mpc_cntr (im, xinit, yinit, cboxsize, xcntr, ycntr)
+
+ # Plot profile
+ call mpc_rplot (im, ifile, xcntr, ycntr, rboxsize)
+
+ call printf ("[%s] x:%7.2f y:%7.2f\n")
+ call pargstr (ifile)
+ call pargr (xcntr)
+ call pargr (ycntr)
+
+ call imunmap (im)
+ }
+end
+
+
+# MPC_CNTR -- Compute star center using MPC algorithm.
+
+procedure mpc_cntr (im, xstart, ystart, boxsize, xcntr, ycntr)
+
+pointer im
+real xstart, ystart
+int boxsize
+real xcntr, ycntr
+
+int x1, x2, y1, y2, half_box
+int ncols, nrows, nx, ny, try
+real xinit, yinit
+pointer bufptr, sp, x_vect, y_vect
+int imgs2r()
+
+begin
+ half_box = (boxsize - 1) / 2
+ xinit = xstart
+ yinit = ystart
+
+ # Mark region to extract - use box size
+ ncols = IM_LEN (im, 1)
+ nrows = IM_LEN (im, 2)
+ try = 0
+
+ repeat {
+ x1 = amax1 (xinit - half_box, 1.0) +0.5
+ x2 = amin1 (xinit + half_box, real(ncols)) +0.5
+ y1 = amax1 (yinit - half_box, 1.0) +0.5
+ y2 = amin1 (yinit + half_box, real(nrows)) +0.5
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+
+ # Extract region around center
+ bufptr = imgs2r (im, x1, x2, y1, y2)
+
+ # Collapse to two 1-D arrays
+ call smark (sp)
+ call salloc (x_vect, nx, TY_REAL)
+ call salloc (y_vect, ny, TY_REAL)
+
+ call aclrr (Memr[x_vect], nx)
+ call aclrr (Memr[y_vect], ny)
+
+ # Sum all rows
+ call mpc_rowsum (Memr[bufptr], Memr[x_vect], nx, ny)
+
+ # Sum all columns
+ call mpc_colsum (Memr[bufptr], Memr[y_vect], nx, ny)
+
+ # Find centers
+ call mpc_getcenter (Memr[x_vect], nx, xcntr)
+ call mpc_getcenter (Memr[y_vect], ny, ycntr)
+
+ # Add in offsets
+ xcntr = xcntr + x1
+ ycntr = ycntr + y1
+
+ call sfree (sp)
+ try = try + 1
+ if (try == 1) {
+ if ((abs(xcntr-xinit) > 1.0) || (abs(ycntr-yinit) > 1.0)) {
+ xinit = xcntr
+ yinit = ycntr
+ }
+ } else
+ break
+ }
+end
+
+
+# MPC_RPLOT -- Plot intensity as a function of radial distance.
+
+procedure mpc_rplot (im, imname, xcntr, ycntr, rboxsize)
+
+pointer im
+char imname[ARB]
+real xcntr, ycntr
+int rboxsize
+
+int x1, x2, y1, y2, half_box
+pointer bufptr, title, sp, gp, op
+int ncols, nrows, nx, ny, i, j
+real xinit, yinit, radval, intval, ymin, ymax, xlen
+int imgs2r(), strlen()
+pointer gopen()
+
+begin
+ call smark (sp)
+ call salloc (title, SZ_TITLE, TY_CHAR)
+
+ half_box = (rboxsize - 1) / 2
+ xinit = xcntr
+ yinit = ycntr
+
+ # Mark region to extract - use box size
+ ncols = IM_LEN(im,1)
+ nrows = IM_LEN(im,2)
+
+ x1 = amax1 (xinit - half_box, 1.0) +0.5
+ x2 = amin1 (xinit + half_box, real(ncols)) +0.5
+ y1 = amax1 (yinit - half_box, 1.0) +0.5
+ y2 = amin1 (yinit + half_box, real(nrows)) +0.5
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+
+ # Extract region around center.
+ bufptr = imgs2r (im, x1, x2, y1, y2)
+
+ # Begin plotting.
+ gp = gopen ("stdgraph", NEW_FILE, STDGRAPH)
+
+ call mpc_aminmax (Memr[bufptr], nx, ny, ymin, ymax)
+ ymax = ymax + EXTRA_HT * (ymax-ymin)
+ ymin = ymin - EXTRA_HT * (ymax-ymin)
+
+ xlen = 1.5 * rboxsize / 2
+ call gswind (gp, 0.0, xlen, ymin, ymax)
+
+ call sysid (Memc[title], SZ_LINE)
+ op = title + strlen (Memc[title])
+ call sprintf (Memc[op], SZ_TITLE-SZ_LINE,
+ "\nRadial Plot of %s at [%0.2f,%0.2f]\n")
+ call pargstr (imname)
+ call pargr (xcntr)
+ call pargr (ycntr)
+
+ call glabax (gp, Memc[title], "Pixels", "Counts")
+
+ do i = 1, ny
+ do j = 1, nx {
+ call mpc_radius (Memr[bufptr], nx, ny, j, i, xcntr-x1+1,
+ ycntr-y1+1, radval, intval)
+ call gmark (gp, radval, intval, GM_PLUS, -.005*xlen,
+ -0.007*(ymax-ymin))
+ }
+
+ call gclose (gp)
+ call sfree (sp)
+end
+
+
+# AMINMAX -- Compute min and max of two-d array.
+
+procedure mpc_aminmax (a, nx, ny, ymin, ymax)
+
+int nx, ny
+real a[nx,ny]
+real ymin, ymax
+
+int i, j
+
+begin
+ ymin = a[1,1]
+ ymax = ymin
+
+ do i = 1, ny
+ do j = 1, nx {
+ ymin = amin1 (ymin, a[j,i])
+ ymax = amax1 (ymax, a[j,i])
+ }
+end
+
+
+# RADIUS -- Compute radius from center.
+
+procedure mpc_radius (a, nx, ny, i, j, xc, yc, radval, intval)
+
+real a[nx, ny]
+int nx, ny, i, j
+real xc, yc, dx, dy, radval, intval
+
+begin
+ dx = xc - i
+ dy = yc - j
+ radval = sqrt (dx**2 + dy**2)
+ intval = a[i,j]
+end
+
+
+# ROWSUM -- Sum all rows in a raster
+
+procedure mpc_rowsum (v, row, nx, ny)
+
+int nx, ny
+real v[nx,ny]
+real row[ARB]
+
+int i, j
+
+begin
+ do i = 1, ny
+ do j = 1, nx
+ row[j] = row[j] + v[j,i]
+end
+
+
+# COLSUM -- Sum all columns in a raster.
+
+procedure mpc_colsum (v, col, nx, ny)
+
+int nx, ny
+real v[nx,ny]
+real col[ARB]
+
+int i, j
+
+begin
+ do i = 1, ny
+ do j = 1, nx
+ col[j] = col[j] + v[i,j]
+end
+
+
+# GETCENTER -- Compute center of gravity of array.
+
+procedure mpc_getcenter (v, nv, vc)
+
+real v[ARB]
+int nv
+real vc
+
+int i
+real sum1, sum2, sigma, cont
+
+begin
+ # Assume continuum level is at endpoints
+ # Compute first moment
+ sum1 = 0.0
+ sum2 = 0.0
+
+ call aavgr (v, nv, cont, sigma)
+
+ do i = 1, nv
+ if (v[i] > cont) {
+ sum1 = sum1 + (i-1) * (v[i] - cont)
+ sum2 = sum2 + (v[i] - cont)
+ }
+
+ # Determine center
+ vc = sum1 / sum2
+end
diff --git a/pkg/obsolete/x_obsolete.x b/pkg/obsolete/x_obsolete.x
new file mode 100644
index 00000000..7f0cf71d
--- /dev/null
+++ b/pkg/obsolete/x_obsolete.x
@@ -0,0 +1,8 @@
+task imtitle = t_imtitle,
+ mkhistogram = t_mkhistogram,
+ oimcombine = t_imcombine,
+ ofixpix = t_fixpix,
+ oimstatistics = t_oimstatistics,
+ orfits = t_rfits,
+ owfits = t_wfits,
+ radplt = t_radplt