aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/immatch/src/imcombine
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/images/immatch/src/imcombine')
-rw-r--r--pkg/images/immatch/src/imcombine/imcombine.par43
-rw-r--r--pkg/images/immatch/src/imcombine/mkpkg20
-rw-r--r--pkg/images/immatch/src/imcombine/src/Revisions36
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icaclip.x2207
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icaverage.x424
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/iccclip.x1791
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icgdata.x1531
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icgrow.x263
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icmedian.x753
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icmm.x645
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icnmodel.x528
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icomb.x2198
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icpclip.x879
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icquad.x476
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icsclip.x1923
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icsigma.x434
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icsort.x1096
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/icstat.x892
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/mkpkg27
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/xtimmap.com9
-rw-r--r--pkg/images/immatch/src/imcombine/src/generic/xtimmap.x1207
-rw-r--r--pkg/images/immatch/src/imcombine/src/icaclip.gx575
-rw-r--r--pkg/images/immatch/src/imcombine/src/icaverage.gx120
-rw-r--r--pkg/images/immatch/src/imcombine/src/iccclip.gx471
-rw-r--r--pkg/images/immatch/src/imcombine/src/icemask.x115
-rw-r--r--pkg/images/immatch/src/imcombine/src/icgdata.gx396
-rw-r--r--pkg/images/immatch/src/imcombine/src/icgrow.gx135
-rw-r--r--pkg/images/immatch/src/imcombine/src/icgscale.x88
-rw-r--r--pkg/images/immatch/src/imcombine/src/ichdr.x72
-rw-r--r--pkg/images/immatch/src/imcombine/src/icimstack.x186
-rw-r--r--pkg/images/immatch/src/imcombine/src/iclog.x431
-rw-r--r--pkg/images/immatch/src/imcombine/src/icmask.com8
-rw-r--r--pkg/images/immatch/src/imcombine/src/icmask.h12
-rw-r--r--pkg/images/immatch/src/imcombine/src/icmask.x685
-rw-r--r--pkg/images/immatch/src/imcombine/src/icmedian.gx246
-rw-r--r--pkg/images/immatch/src/imcombine/src/icmm.gx189
-rw-r--r--pkg/images/immatch/src/imcombine/src/icnmodel.gx147
-rw-r--r--pkg/images/immatch/src/imcombine/src/icomb.gx761
-rw-r--r--pkg/images/immatch/src/imcombine/src/icombine.com45
-rw-r--r--pkg/images/immatch/src/imcombine/src/icombine.h63
-rw-r--r--pkg/images/immatch/src/imcombine/src/icombine.x520
-rw-r--r--pkg/images/immatch/src/imcombine/src/icpclip.gx233
-rw-r--r--pkg/images/immatch/src/imcombine/src/icpmmap.x34
-rw-r--r--pkg/images/immatch/src/imcombine/src/icquad.gx133
-rw-r--r--pkg/images/immatch/src/imcombine/src/icrmasks.x41
-rw-r--r--pkg/images/immatch/src/imcombine/src/icscale.x351
-rw-r--r--pkg/images/immatch/src/imcombine/src/icsclip.gx504
-rw-r--r--pkg/images/immatch/src/imcombine/src/icsection.x94
-rw-r--r--pkg/images/immatch/src/imcombine/src/icsetout.x332
-rw-r--r--pkg/images/immatch/src/imcombine/src/icsigma.gx122
-rw-r--r--pkg/images/immatch/src/imcombine/src/icsort.gx386
-rw-r--r--pkg/images/immatch/src/imcombine/src/icstat.gx238
-rw-r--r--pkg/images/immatch/src/imcombine/src/mkpkg67
-rw-r--r--pkg/images/immatch/src/imcombine/src/tymax.x27
-rw-r--r--pkg/images/immatch/src/imcombine/src/xtimmap.gx634
-rw-r--r--pkg/images/immatch/src/imcombine/src/xtprocid.x38
-rw-r--r--pkg/images/immatch/src/imcombine/t_imcombine.x230
-rw-r--r--pkg/images/immatch/src/imcombine/x_imcombine.x1
58 files changed, 26112 insertions, 0 deletions
diff --git a/pkg/images/immatch/src/imcombine/imcombine.par b/pkg/images/immatch/src/imcombine/imcombine.par
new file mode 100644
index 00000000..ead908e4
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/imcombine.par
@@ -0,0 +1,43 @@
+# IMCOMBINE -- Image combine parameters
+
+input,s,a,,,,List of images to combine
+output,s,a,,,,List of output images
+headers,s,h,"",,,List of header files (optional)
+bpmasks,s,h,"",,,List of bad pixel masks (optional)
+rejmasks,s,h,"",,,List of rejection masks (optional)
+nrejmasks,s,h,"",,,List of number rejected masks (optional)
+expmasks,s,h,"",,,List of exposure masks (optional)
+sigmas,s,h,"",,,List of sigma images (optional)
+imcmb,s,h,"$I",,,Keyword for IMCMB keywords
+logfile,s,h,"STDOUT",,,"Log file
+"
+combine,s,h,"average","average|median|lmedian|sum|quadrature|nmodel",,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
+outlimits,s,h,"",,,Output limits (x1 x2 y1 y2 ...)
+offsets,f,h,"none",,,Input image offsets
+masktype,s,h,"none","",,Mask type
+maskvalue,s,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/images/immatch/src/imcombine/mkpkg b/pkg/images/immatch/src/imcombine/mkpkg
new file mode 100644
index 00000000..456232e8
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/mkpkg
@@ -0,0 +1,20 @@
+# Make the IMCOMBINE Task.
+
+$checkout libpkg.a ../../../
+$update libpkg.a
+$checkin libpkg.a ../../../
+$exit
+
+standalone:
+ $set LIBS1 = "src/libimc.a -lxtools -lcurfit -lsurfit -lgsurfit"
+ $set LIBS2 = "-liminterp -lnlfit -lslalib -lncar -lgks"
+ $update libimc.a@src
+ $update libpkg.a
+ $omake x_imcombine.x
+ $link x_imcombine.o libpkg.a $(LIBS1) $(LIBS2) -o xx_imcombine.e
+ ;
+
+libpkg.a:
+ t_imcombine.x src/icombine.com src/icombine.h <error.h> <mach.h> \
+ <imhdr.h>
+ ;
diff --git a/pkg/images/immatch/src/imcombine/src/Revisions b/pkg/images/immatch/src/imcombine/src/Revisions
new file mode 100644
index 00000000..469f9e5c
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/Revisions
@@ -0,0 +1,36 @@
+.help revisions Jul04 imcombine/src
+.nf
+
+This directory contains generic code used in various tasks that combine
+images.
+
+=======
+V2.13
+=======
+
+icgdata.gx
+ Fixed a problem where 3-D images were closing an image in the case
+ of many bands leading to a slow execution (10/20/06, Valdes)
+
+=======
+V2.12.3
+=======
+
+icmask.x
+iclog.x
+icombine.h
+ As a special unadvertised feature the "maskvalue" parameter may be
+ specified with a leading '<' or '>'. Ultimately a full expression
+ should be added and documented. (7/26/04, Valdes)
+
+icmask.x
+ Added a feature to allow masks specified without a path to be found
+ either in the current directory or the directory with the image. This
+ is useful when images to be combined are distributed across multiple
+ directories. (7/16/04, Valdes)
+
+========
+V2.12.2a
+========
+
+.endhelp
diff --git a/pkg/images/immatch/src/imcombine/src/generic/icaclip.x b/pkg/images/immatch/src/imcombine/src/generic/icaclip.x
new file mode 100644
index 00000000..8fb89b1b
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icaclip.x
@@ -0,0 +1,2207 @@
+# 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 = max (0, n[1])
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 = max (0, 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 (max (0, 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, sig, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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)
+ sig = sqrt (s / (n2 - 1))
+ else {
+ call sfree (sp)
+ return
+ }
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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) && sig > 0.) {
+ if (doscale1) {
+ for (; nl <= nh; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = sig * 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 = sig * 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 = sig * sqrt (max (one, med))
+ for (; nl <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 = max (0, 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 (max (0, 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, sig, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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)
+ sig = sqrt (s / (n2 - 1))
+ else {
+ call sfree (sp)
+ return
+ }
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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) && sig > 0.) {
+ if (doscale1) {
+ for (; nl <= nh; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = sig * 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 = sig * 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 = sig * sqrt (max (one, med))
+ for (; nl <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 = max (0, 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 (max (0, 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, sig, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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)
+ sig = sqrt (s / (n2 - 1))
+ else {
+ call sfree (sp)
+ return
+ }
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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) && sig > 0.) {
+ if (doscale1) {
+ for (; nl <= nh; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = sig * 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 = sig * 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 = sig * sqrt (max (one, med))
+ for (; nl <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 = max (0, 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 (max (0, 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, sig, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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)
+ sig = sqrt (s / (n2 - 1))
+ else {
+ call sfree (sp)
+ return
+ }
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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) && sig > 0.) {
+ if (doscale1) {
+ for (; nl <= nh; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = sig * 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 = sig * 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 = sig * sqrt (max (one, med))
+ for (; nl <= nh; 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/generic/icaverage.x b/pkg/images/immatch/src/imcombine/src/generic/icaverage.x
new file mode 100644
index 00000000..7167d301
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icaverage.x
@@ -0,0 +1,424 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+include "../icmask.h"
+
+
+# IC_AVERAGE -- Compute the average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_averages (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real sumwt, wt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ 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]
+ if (doaverage == YES)
+ average[i] = sum / n[i]
+ else
+ average[i] = sum
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Mems[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Mems[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sum / sumwt
+ else {
+ sum = Mems[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mems[d[j]+k]
+ average[i] = sum / n1
+ }
+ } else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ sum = Mems[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mems[d[j]+k]
+ if (doaverage == YES)
+ average[i] = sum / n1
+ else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_AVERAGE -- Compute the average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_averagei (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real sumwt, wt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ 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]
+ if (doaverage == YES)
+ average[i] = sum / n[i]
+ else
+ average[i] = sum
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memi[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memi[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sum / sumwt
+ else {
+ sum = Memi[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memi[d[j]+k]
+ average[i] = sum / n1
+ }
+ } else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ sum = Memi[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memi[d[j]+k]
+ if (doaverage == YES)
+ average[i] = sum / n1
+ else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_AVERAGE -- Compute the average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_averager (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real sumwt, wt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ 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]
+ if (doaverage == YES)
+ average[i] = sum / n[i]
+ else
+ average[i] = sum
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memr[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memr[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sum / sumwt
+ else {
+ sum = Memr[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memr[d[j]+k]
+ average[i] = sum / n1
+ }
+ } else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ sum = Memr[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memr[d[j]+k]
+ if (doaverage == YES)
+ average[i] = sum / n1
+ else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_AVERAGE -- Compute the average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_averaged (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+double average[npts] # Average (returned)
+
+int i, j, k, n1
+real sumwt, wt
+double sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ 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]
+ if (doaverage == YES)
+ average[i] = sum / n[i]
+ else
+ average[i] = sum
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Memd[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Memd[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sum / sumwt
+ else {
+ sum = Memd[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memd[d[j]+k]
+ average[i] = sum / n1
+ }
+ } else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ sum = Memd[d[1]+k]
+ do j = 2, n1
+ sum = sum + Memd[d[j]+k]
+ if (doaverage == YES)
+ average[i] = sum / n1
+ else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
diff --git a/pkg/images/immatch/src/imcombine/src/generic/iccclip.x b/pkg/images/immatch/src/imcombine/src/generic/iccclip.x
new file mode 100644
index 00000000..cf60c779
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/iccclip.x
@@ -0,0 +1,1791 @@
+# 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/generic/icgdata.x b/pkg/images/immatch/src/imcombine/src/generic/icgdata.x
new file mode 100644
index 00000000..774de63c
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icgdata.x
@@ -0,0 +1,1531 @@
+# 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[ARB] # 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
+
+short temp
+int i, j, k, l, n1, n2, npix, nin, nout, ndim, nused, mtype, xt_imgnls()
+real a, b
+pointer buf, dp, ip, mp
+errchk xt_cpix, xt_imgnls
+
+short max_pixel
+data max_pixel/MAX_SHORT/
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages, mtype)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Close images which are not needed.
+ nout = IM_LEN(out[1],1)
+ ndim = IM_NDIM(out[1])
+ if (!project && ndim < 3) {
+ do i = 1, nimages {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1)
+ call xt_cpix (i)
+ if (ndim > 1) {
+ j = v1[2] - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+ }
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ 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 = xt_imgnls (in[i], i, d[i], v2, v1[2])
+ } else {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1) {
+ lflag[i] = D_NONE
+ next
+ }
+ k = 1 + j - offsets[i,1]
+ v2[1] = k
+ do l = 2, ndim {
+ v2[l] = v1[l] - offsets[i,l]
+ if (v2[l] < 1 || v2[l] > IM_LEN(in[i],l)) {
+ lflag[i] = D_NONE
+ break
+ }
+ }
+ if (lflag[i] == D_NONE)
+ next
+ if (project)
+ v2[ndim+1] = i
+ l = xt_imgnls (in[i], i, buf, v2, v1[2])
+ call amovs (Mems[buf+k-1], Mems[dbuf[i]+j], npix)
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Set values to max_pixel if needed.
+ if (mtype == M_NOVAL) {
+ do i = 1, nimages {
+ dp = d[i]; mp = m[i]
+ if (lflag[i] == D_NONE || dp == NULL)
+ next
+ else if (lflag[i] == D_MIX) {
+ do j = 1, npts {
+ if (Memi[mp] == 1)
+ Mems[dp] = max_pixel
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ a = Mems[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 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
+ }
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1) {
+ a = Mems[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+
+ # Check for completely empty lines
+ lflag[i] = D_NONE
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ 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 {
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ Mems[dp] = Mems[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1)
+ 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
+ }
+ }
+ do i = nused+1, nimages
+ d[i] = NULL
+ 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]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ ip = id[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ Memi[ip] = l
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Mems[d[k]+j-1]
+ Mems[d[k]+j-1] = Mems[dp]
+ Mems[dp] = temp
+ Memi[ip] = Memi[id[k]+j-1]
+ Memi[id[k]+j-1] = l
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ } else
+ Memi[ip] = 0
+ 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 {
+ l = lflag[i]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Mems[d[k]+j-1]
+ Mems[d[k]+j-1] = Mems[dp]
+ Mems[dp] = temp
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nused, TY_SHORT)
+ if (keepids) {
+ call malloc (ip, nused, 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)
+ }
+
+ # If no good pixels set the number of usable values as -n and
+ # shift them to lower values.
+ if (mtype == M_NOVAL) {
+ if (keepids) {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ ip = id[i] + j - 1
+ if (Mems[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i) {
+ Mems[d[k]+j-1] = Mems[dp]
+ Memi[id[k]+j-1] = Memi[ip]
+ }
+ }
+ }
+ }
+ } else {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ if (Mems[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i)
+ Mems[d[k]+j-1] = Mems[dp]
+ }
+ }
+ }
+ }
+ }
+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[ARB] # 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 temp
+int i, j, k, l, n1, n2, npix, nin, nout, ndim, nused, mtype, xt_imgnli()
+real a, b
+pointer buf, dp, ip, mp
+errchk xt_cpix, xt_imgnli
+
+int max_pixel
+data max_pixel/MAX_INT/
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages, mtype)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Close images which are not needed.
+ nout = IM_LEN(out[1],1)
+ ndim = IM_NDIM(out[1])
+ if (!project && ndim < 3) {
+ do i = 1, nimages {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1)
+ call xt_cpix (i)
+ if (ndim > 1) {
+ j = v1[2] - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+ }
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ 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 = xt_imgnli (in[i], i, d[i], v2, v1[2])
+ } else {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1) {
+ lflag[i] = D_NONE
+ next
+ }
+ k = 1 + j - offsets[i,1]
+ v2[1] = k
+ do l = 2, ndim {
+ v2[l] = v1[l] - offsets[i,l]
+ if (v2[l] < 1 || v2[l] > IM_LEN(in[i],l)) {
+ lflag[i] = D_NONE
+ break
+ }
+ }
+ if (lflag[i] == D_NONE)
+ next
+ if (project)
+ v2[ndim+1] = i
+ l = xt_imgnli (in[i], i, buf, v2, v1[2])
+ call amovi (Memi[buf+k-1], Memi[dbuf[i]+j], npix)
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Set values to max_pixel if needed.
+ if (mtype == M_NOVAL) {
+ do i = 1, nimages {
+ dp = d[i]; mp = m[i]
+ if (lflag[i] == D_NONE || dp == NULL)
+ next
+ else if (lflag[i] == D_MIX) {
+ do j = 1, npts {
+ if (Memi[mp] == 1)
+ Memi[dp] = max_pixel
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ a = Memi[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 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
+ }
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1) {
+ a = Memi[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+
+ # Check for completely empty lines
+ lflag[i] = D_NONE
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ 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 {
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ Memi[dp] = Memi[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1)
+ 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
+ }
+ }
+ do i = nused+1, nimages
+ d[i] = NULL
+ 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]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ ip = id[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ Memi[ip] = l
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Memi[d[k]+j-1]
+ Memi[d[k]+j-1] = Memi[dp]
+ Memi[dp] = temp
+ Memi[ip] = Memi[id[k]+j-1]
+ Memi[id[k]+j-1] = l
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ } else
+ Memi[ip] = 0
+ 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 {
+ l = lflag[i]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Memi[d[k]+j-1]
+ Memi[d[k]+j-1] = Memi[dp]
+ Memi[dp] = temp
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nused, TY_INT)
+ if (keepids) {
+ call malloc (ip, nused, 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)
+ }
+
+ # If no good pixels set the number of usable values as -n and
+ # shift them to lower values.
+ if (mtype == M_NOVAL) {
+ if (keepids) {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ ip = id[i] + j - 1
+ if (Memi[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i) {
+ Memi[d[k]+j-1] = Memi[dp]
+ Memi[id[k]+j-1] = Memi[ip]
+ }
+ }
+ }
+ }
+ } else {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ if (Memi[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i)
+ Memi[d[k]+j-1] = Memi[dp]
+ }
+ }
+ }
+ }
+ }
+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[ARB] # 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
+
+real temp
+int i, j, k, l, n1, n2, npix, nin, nout, ndim, nused, mtype, xt_imgnlr()
+real a, b
+pointer buf, dp, ip, mp
+errchk xt_cpix, xt_imgnlr
+
+real max_pixel
+data max_pixel/MAX_REAL/
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages, mtype)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Close images which are not needed.
+ nout = IM_LEN(out[1],1)
+ ndim = IM_NDIM(out[1])
+ if (!project && ndim < 3) {
+ do i = 1, nimages {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1)
+ call xt_cpix (i)
+ if (ndim > 1) {
+ j = v1[2] - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+ }
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ 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 = xt_imgnlr (in[i], i, d[i], v2, v1[2])
+ } else {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1) {
+ lflag[i] = D_NONE
+ next
+ }
+ k = 1 + j - offsets[i,1]
+ v2[1] = k
+ do l = 2, ndim {
+ v2[l] = v1[l] - offsets[i,l]
+ if (v2[l] < 1 || v2[l] > IM_LEN(in[i],l)) {
+ lflag[i] = D_NONE
+ break
+ }
+ }
+ if (lflag[i] == D_NONE)
+ next
+ if (project)
+ v2[ndim+1] = i
+ l = xt_imgnlr (in[i], i, buf, v2, v1[2])
+ call amovr (Memr[buf+k-1], Memr[dbuf[i]+j], npix)
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Set values to max_pixel if needed.
+ if (mtype == M_NOVAL) {
+ do i = 1, nimages {
+ dp = d[i]; mp = m[i]
+ if (lflag[i] == D_NONE || dp == NULL)
+ next
+ else if (lflag[i] == D_MIX) {
+ do j = 1, npts {
+ if (Memi[mp] == 1)
+ Memr[dp] = max_pixel
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ a = Memr[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 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
+ }
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1) {
+ a = Memr[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+
+ # Check for completely empty lines
+ lflag[i] = D_NONE
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ 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 {
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ Memr[dp] = Memr[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1)
+ 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
+ }
+ }
+ do i = nused+1, nimages
+ d[i] = NULL
+ 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]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ ip = id[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ Memi[ip] = l
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Memr[d[k]+j-1]
+ Memr[d[k]+j-1] = Memr[dp]
+ Memr[dp] = temp
+ Memi[ip] = Memi[id[k]+j-1]
+ Memi[id[k]+j-1] = l
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ } else
+ Memi[ip] = 0
+ 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 {
+ l = lflag[i]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Memr[d[k]+j-1]
+ Memr[d[k]+j-1] = Memr[dp]
+ Memr[dp] = temp
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nused, TY_REAL)
+ if (keepids) {
+ call malloc (ip, nused, 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)
+ }
+
+ # If no good pixels set the number of usable values as -n and
+ # shift them to lower values.
+ if (mtype == M_NOVAL) {
+ if (keepids) {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ ip = id[i] + j - 1
+ if (Memr[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i) {
+ Memr[d[k]+j-1] = Memr[dp]
+ Memi[id[k]+j-1] = Memi[ip]
+ }
+ }
+ }
+ }
+ } else {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ if (Memr[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i)
+ Memr[d[k]+j-1] = Memr[dp]
+ }
+ }
+ }
+ }
+ }
+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[ARB] # 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
+
+double temp
+int i, j, k, l, n1, n2, npix, nin, nout, ndim, nused, mtype, xt_imgnld()
+real a, b
+pointer buf, dp, ip, mp
+errchk xt_cpix, xt_imgnld
+
+double max_pixel
+data max_pixel/MAX_DOUBLE/
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages, mtype)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Close images which are not needed.
+ nout = IM_LEN(out[1],1)
+ ndim = IM_NDIM(out[1])
+ if (!project && ndim < 3) {
+ do i = 1, nimages {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1)
+ call xt_cpix (i)
+ if (ndim > 1) {
+ j = v1[2] - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+ }
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ 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 = xt_imgnld (in[i], i, d[i], v2, v1[2])
+ } else {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1) {
+ lflag[i] = D_NONE
+ next
+ }
+ k = 1 + j - offsets[i,1]
+ v2[1] = k
+ do l = 2, ndim {
+ v2[l] = v1[l] - offsets[i,l]
+ if (v2[l] < 1 || v2[l] > IM_LEN(in[i],l)) {
+ lflag[i] = D_NONE
+ break
+ }
+ }
+ if (lflag[i] == D_NONE)
+ next
+ if (project)
+ v2[ndim+1] = i
+ l = xt_imgnld (in[i], i, buf, v2, v1[2])
+ call amovd (Memd[buf+k-1], Memd[dbuf[i]+j], npix)
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Set values to max_pixel if needed.
+ if (mtype == M_NOVAL) {
+ do i = 1, nimages {
+ dp = d[i]; mp = m[i]
+ if (lflag[i] == D_NONE || dp == NULL)
+ next
+ else if (lflag[i] == D_MIX) {
+ do j = 1, npts {
+ if (Memi[mp] == 1)
+ Memd[dp] = max_pixel
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ a = Memd[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 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
+ }
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1) {
+ a = Memd[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+
+ # Check for completely empty lines
+ lflag[i] = D_NONE
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ 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 {
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ Memd[dp] = Memd[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1)
+ 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
+ }
+ }
+ do i = nused+1, nimages
+ d[i] = NULL
+ 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]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ ip = id[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ Memi[ip] = l
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Memd[d[k]+j-1]
+ Memd[d[k]+j-1] = Memd[dp]
+ Memd[dp] = temp
+ Memi[ip] = Memi[id[k]+j-1]
+ Memi[id[k]+j-1] = l
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ } else
+ Memi[ip] = 0
+ 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 {
+ l = lflag[i]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Memd[d[k]+j-1]
+ Memd[d[k]+j-1] = Memd[dp]
+ Memd[dp] = temp
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nused, TY_DOUBLE)
+ if (keepids) {
+ call malloc (ip, nused, 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)
+ }
+
+ # If no good pixels set the number of usable values as -n and
+ # shift them to lower values.
+ if (mtype == M_NOVAL) {
+ if (keepids) {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ ip = id[i] + j - 1
+ if (Memd[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i) {
+ Memd[d[k]+j-1] = Memd[dp]
+ Memi[id[k]+j-1] = Memi[ip]
+ }
+ }
+ }
+ }
+ } else {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ if (Memd[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i)
+ Memd[d[k]+j-1] = Memd[dp]
+ }
+ }
+ }
+ }
+ }
+end
+
diff --git a/pkg/images/immatch/src/imcombine/src/generic/icgrow.x b/pkg/images/immatch/src/imcombine/src/generic/icgrow.x
new file mode 100644
index 00000000..1ccb7885
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icgrow.x
@@ -0,0 +1,263 @@
+# 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, ncompress, 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)
+ ncompress = 0
+ }
+ 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)
+ if (l > 0) {
+ v[2] = line + l
+ if (v[2] <= nl)
+ call pmplpi (pm, v, buf[1,i], 1, npts, rop)
+ }
+ }
+ }
+ v[2] = line
+
+ if (ncompress > 10) {
+ do i = 1, nimages {
+ pm = Memi[pms+i-1]
+ call pm_compress (pm)
+ }
+ ncompress = 0
+ } else
+ ncompress = ncompress + 1
+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/images/immatch/src/imcombine/src/generic/icmedian.x b/pkg/images/immatch/src/imcombine/src/generic/icmedian.x
new file mode 100644
index 00000000..c482454b
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icmedian.x
@@ -0,0 +1,753 @@
+# 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, j, k, j1, j2, n1, lo, up, lo1, up1
+bool even
+real val1, val2, val3
+short temp, wtemp
+
+include "../icombine.com"
+
+begin
+ # If no data return after possibly setting blank values.
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # If the data were previously sorted then directly compute the median.
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ even = (mod(n1,2)==0 && (medtype==MEDAVG || 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]
+ }
+ return
+ } else {
+ # Check for negative n values. If found then there are
+ # pixels with no good values but with values we want to
+ # use as a substitute median. In this case ignore that
+ # the good pixels have been sorted.
+ do i = 1, npts {
+ if (n[i] < 0)
+ break
+ }
+
+ if (n[i] >= 0) {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1>2)) {
+ 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
+ }
+ }
+ }
+
+ # Compute the median.
+ do i = 1, npts {
+ k = i - 1
+ n1 = abs(n[i])
+
+ # If there are more than 3 points use Wirth algorithm. This
+ # is the same as vops$amed.gx except for an even number of
+ # points it selects the middle two and averages.
+ if (n1 > 3) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2))
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Mems[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Mems[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Mems[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Mems[d[lo1]+k]
+ Mems[d[lo1]+k] = Mems[d[up1]+k]
+ Mems[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+
+ median[i] = Mems[d[j]+k]
+
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1 > 2)) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2)+1)
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Mems[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Mems[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Mems[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Mems[d[lo1]+k]
+ Mems[d[lo1]+k] = Mems[d[up1]+k]
+ Mems[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+ median[i] = (median[i] + Mems[d[j]+k]) / 2
+ }
+
+ # If 3 points find the median directly.
+ } else 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
+ }
+
+ # If 2 points average.
+ } else if (n1 == 2) {
+ val1 = Mems[d[1]+k]
+ val2 = Mems[d[2]+k]
+ if (medtype == MEDAVG)
+ median[i] = (val1 + val2) / 2
+ else
+ median[i] = min (val1, val2)
+
+ # If 1 point return the value.
+ } else if (n1 == 1)
+ median[i] = Mems[d[1]+k]
+
+ # If no points return with a possibly blank value.
+ 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, j, k, j1, j2, n1, lo, up, lo1, up1
+bool even
+real val1, val2, val3
+int temp, wtemp
+
+include "../icombine.com"
+
+begin
+ # If no data return after possibly setting blank values.
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # If the data were previously sorted then directly compute the median.
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ even = (mod(n1,2)==0 && (medtype==MEDAVG || 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]
+ }
+ return
+ } else {
+ # Check for negative n values. If found then there are
+ # pixels with no good values but with values we want to
+ # use as a substitute median. In this case ignore that
+ # the good pixels have been sorted.
+ do i = 1, npts {
+ if (n[i] < 0)
+ break
+ }
+
+ if (n[i] >= 0) {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1>2)) {
+ 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
+ }
+ }
+ }
+
+ # Compute the median.
+ do i = 1, npts {
+ k = i - 1
+ n1 = abs(n[i])
+
+ # If there are more than 3 points use Wirth algorithm. This
+ # is the same as vops$amed.gx except for an even number of
+ # points it selects the middle two and averages.
+ if (n1 > 3) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2))
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Memi[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Memi[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Memi[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Memi[d[lo1]+k]
+ Memi[d[lo1]+k] = Memi[d[up1]+k]
+ Memi[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+
+ median[i] = Memi[d[j]+k]
+
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1 > 2)) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2)+1)
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Memi[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Memi[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Memi[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Memi[d[lo1]+k]
+ Memi[d[lo1]+k] = Memi[d[up1]+k]
+ Memi[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+ median[i] = (median[i] + Memi[d[j]+k]) / 2
+ }
+
+ # If 3 points find the median directly.
+ } else 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
+ }
+
+ # If 2 points average.
+ } else if (n1 == 2) {
+ val1 = Memi[d[1]+k]
+ val2 = Memi[d[2]+k]
+ if (medtype == MEDAVG)
+ median[i] = (val1 + val2) / 2
+ else
+ median[i] = min (val1, val2)
+
+ # If 1 point return the value.
+ } else if (n1 == 1)
+ median[i] = Memi[d[1]+k]
+
+ # If no points return with a possibly blank value.
+ 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, j, k, j1, j2, n1, lo, up, lo1, up1
+bool even
+real val1, val2, val3
+real temp, wtemp
+
+include "../icombine.com"
+
+begin
+ # If no data return after possibly setting blank values.
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # If the data were previously sorted then directly compute the median.
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ even = (mod(n1,2)==0 && (medtype==MEDAVG || 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]
+ }
+ return
+ } else {
+ # Check for negative n values. If found then there are
+ # pixels with no good values but with values we want to
+ # use as a substitute median. In this case ignore that
+ # the good pixels have been sorted.
+ do i = 1, npts {
+ if (n[i] < 0)
+ break
+ }
+
+ if (n[i] >= 0) {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1>2)) {
+ 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
+ }
+ }
+ }
+
+ # Compute the median.
+ do i = 1, npts {
+ k = i - 1
+ n1 = abs(n[i])
+
+ # If there are more than 3 points use Wirth algorithm. This
+ # is the same as vops$amed.gx except for an even number of
+ # points it selects the middle two and averages.
+ if (n1 > 3) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2))
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Memr[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Memr[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Memr[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Memr[d[lo1]+k]
+ Memr[d[lo1]+k] = Memr[d[up1]+k]
+ Memr[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+
+ median[i] = Memr[d[j]+k]
+
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1 > 2)) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2)+1)
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Memr[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Memr[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Memr[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Memr[d[lo1]+k]
+ Memr[d[lo1]+k] = Memr[d[up1]+k]
+ Memr[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+ median[i] = (median[i] + Memr[d[j]+k]) / 2
+ }
+
+ # If 3 points find the median directly.
+ } else 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
+ }
+
+ # If 2 points average.
+ } else if (n1 == 2) {
+ val1 = Memr[d[1]+k]
+ val2 = Memr[d[2]+k]
+ if (medtype == MEDAVG)
+ median[i] = (val1 + val2) / 2
+ else
+ median[i] = min (val1, val2)
+
+ # If 1 point return the value.
+ } else if (n1 == 1)
+ median[i] = Memr[d[1]+k]
+
+ # If no points return with a possibly blank value.
+ 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, j, k, j1, j2, n1, lo, up, lo1, up1
+bool even
+double val1, val2, val3
+double temp, wtemp
+
+include "../icombine.com"
+
+begin
+ # If no data return after possibly setting blank values.
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # If the data were previously sorted then directly compute the median.
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ even = (mod(n1,2)==0 && (medtype==MEDAVG || 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]
+ }
+ return
+ } else {
+ # Check for negative n values. If found then there are
+ # pixels with no good values but with values we want to
+ # use as a substitute median. In this case ignore that
+ # the good pixels have been sorted.
+ do i = 1, npts {
+ if (n[i] < 0)
+ break
+ }
+
+ if (n[i] >= 0) {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1>2)) {
+ 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
+ }
+ }
+ }
+
+ # Compute the median.
+ do i = 1, npts {
+ k = i - 1
+ n1 = abs(n[i])
+
+ # If there are more than 3 points use Wirth algorithm. This
+ # is the same as vops$amed.gx except for an even number of
+ # points it selects the middle two and averages.
+ if (n1 > 3) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2))
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Memd[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Memd[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Memd[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Memd[d[lo1]+k]
+ Memd[d[lo1]+k] = Memd[d[up1]+k]
+ Memd[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+
+ median[i] = Memd[d[j]+k]
+
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1 > 2)) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2)+1)
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Memd[d[j]+k]; lo1 = lo; up1 = up
+
+ repeat {
+ while (Memd[d[lo1]+k] < temp)
+ lo1 = lo1 + 1
+ while (temp < Memd[d[up1]+k])
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Memd[d[lo1]+k]
+ Memd[d[lo1]+k] = Memd[d[up1]+k]
+ Memd[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+ median[i] = (median[i] + Memd[d[j]+k]) / 2
+ }
+
+ # If 3 points find the median directly.
+ } else 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
+ }
+
+ # If 2 points average.
+ } else if (n1 == 2) {
+ val1 = Memd[d[1]+k]
+ val2 = Memd[d[2]+k]
+ if (medtype == MEDAVG)
+ median[i] = (val1 + val2) / 2
+ else
+ median[i] = min (val1, val2)
+
+ # If 1 point return the value.
+ } else if (n1 == 1)
+ median[i] = Memd[d[1]+k]
+
+ # If no points return with a possibly blank value.
+ else if (doblank == YES)
+ median[i] = blank
+ }
+end
+
diff --git a/pkg/images/immatch/src/imcombine/src/generic/icmm.x b/pkg/images/immatch/src/imcombine/src/generic/icmm.x
new file mode 100644
index 00000000..9c8274c8
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icmm.x
@@ -0,0 +1,645 @@
+# 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 = max (0, 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 = max (0, 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
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ } else {
+ Mems[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Mems[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ } else {
+ Mems[kmin] = d2
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ }
+ }
+ } 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 = max (0, 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 = max (0, 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
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ } else {
+ Memi[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Memi[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ } else {
+ Memi[kmin] = d2
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ }
+ }
+ } 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 = max (0, 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 = max (0, 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
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ } else {
+ Memr[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Memr[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ } else {
+ Memr[kmin] = d2
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ }
+ }
+ } 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 = max (0, 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 = max (0, 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
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ } else {
+ Memd[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Memd[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ } else {
+ Memd[kmin] = d2
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ }
+ }
+ } 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/images/immatch/src/imcombine/src/generic/icnmodel.x b/pkg/images/immatch/src/imcombine/src/generic/icnmodel.x
new file mode 100644
index 00000000..559cba73
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icnmodel.x
@@ -0,0 +1,528 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+include "../icmask.h"
+
+
+# IC_NMODEL -- Compute the quadrature average (or summed) noise model.
+# Options include a weighted average/sum.
+
+procedure ic_nmodels (d, m, n, nm, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real nm[3,nimages] # Noise model parameters
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+real sum, zero
+data zero /0.0/
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Mems[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ do j = 2, n[i] {
+ val = max (zero, Mems[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Mems[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n[i] {
+ val = max (zero, Mems[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Mems[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ sumwt = wt
+ do j = 2, n1 {
+ val = max (zero, Mems[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = max (zero, Mems[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = Mems[d[1]+k]**2
+ do j = 2, n1 {
+ val = max (zero, Mems[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] +
+ (val*nm[3,j])**2
+ sum = sum + val
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Mems[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n1 {
+ val = max (zero, Mems[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_NMODEL -- Compute the quadrature average (or summed) noise model.
+# Options include a weighted average/sum.
+
+procedure ic_nmodeli (d, m, n, nm, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real nm[3,nimages] # Noise model parameters
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+real sum, zero
+data zero /0.0/
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Memi[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ do j = 2, n[i] {
+ val = max (zero, Memi[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Memi[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n[i] {
+ val = max (zero, Memi[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Memi[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ sumwt = wt
+ do j = 2, n1 {
+ val = max (zero, Memi[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = max (zero, Memi[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = Memi[d[1]+k]**2
+ do j = 2, n1 {
+ val = max (zero, Memi[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] +
+ (val*nm[3,j])**2
+ sum = sum + val
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Memi[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n1 {
+ val = max (zero, Memi[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_NMODEL -- Compute the quadrature average (or summed) noise model.
+# Options include a weighted average/sum.
+
+procedure ic_nmodelr (d, m, n, nm, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real nm[3,nimages] # Noise model parameters
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+real sum, zero
+data zero /0.0/
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Memr[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ do j = 2, n[i] {
+ val = max (zero, Memr[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Memr[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n[i] {
+ val = max (zero, Memr[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Memr[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ sumwt = wt
+ do j = 2, n1 {
+ val = max (zero, Memr[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = max (zero, Memr[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = Memr[d[1]+k]**2
+ do j = 2, n1 {
+ val = max (zero, Memr[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] +
+ (val*nm[3,j])**2
+ sum = sum + val
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Memr[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n1 {
+ val = max (zero, Memr[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_NMODEL -- Compute the quadrature average (or summed) noise model.
+# Options include a weighted average/sum.
+
+procedure ic_nmodeld (d, m, n, nm, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real nm[3,nimages] # Noise model parameters
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+double average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+double sum, zero
+data zero /0.0D0/
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Memd[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ do j = 2, n[i] {
+ val = max (zero, Memd[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Memd[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n[i] {
+ val = max (zero, Memd[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Memd[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ sumwt = wt
+ do j = 2, n1 {
+ val = max (zero, Memd[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = max (zero, Memd[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = Memd[d[1]+k]**2
+ do j = 2, n1 {
+ val = max (zero, Memd[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] +
+ (val*nm[3,j])**2
+ sum = sum + val
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Memd[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n1 {
+ val = max (zero, Memd[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
diff --git a/pkg/images/immatch/src/imcombine/src/generic/icomb.x b/pkg/images/immatch/src/imcombine/src/generic/icomb.x
new file mode 100644
index 00000000..3466073b
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icomb.x
@@ -0,0 +1,2198 @@
+# 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"
+
+# The following is for compiling under V2.11.
+define IM_BUFFRAC IM_BUFSIZE
+include <imset.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, scales, zeros, wts, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[ARB] # Output images
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real wts[nimages] # Weights
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, k, npts, fd, stropen(), xt_imgnls()
+pointer sp, d, id, n, m, lflag, v, dbuf
+pointer im, buf, xt_opix(), impl1i()
+errchk stropen, xt_cpix, xt_opix, xt_imgnls, impl1i, ic_combines
+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 (v, IM_MAXDIM, TY_LONG)
+ call amovki (D_ALL, Memi[lflag], nimages)
+ call amovkl (1, Meml[v], IM_MAXDIM)
+
+ # 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)
+ call aclrs (Mems[Memi[dbuf+i-1]], npts)
+ }
+ } else {
+ do i = 1, nimages {
+ im = xt_opix (in[i], i, 1)
+ if (im != in[i]) {
+ call salloc (Memi[dbuf+i-1], npts, TY_SHORT)
+ call aclrs (Mems[Memi[dbuf+i-1]], npts)
+ }
+ }
+ call amovki (NULL, Memi[dbuf], nimages)
+ }
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFFRAC, 0)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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)
+ }
+ if (out[4] != NULL) {
+ buf = impl1i (out[4])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[5] != NULL) {
+ buf = impl1i (out[5])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[6] != NULL) {
+ buf = impl1i (out[6])
+ call aclri (Memi[buf], npts)
+ }
+
+ # Do I/O for first input image line.
+ if (!project) {
+ do i = 1, nimages {
+ call xt_imseti (i, "bufsize", bufsize)
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ call xt_cpix (i)
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+
+ do i = 1, nimages {
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ next
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ next
+ iferr {
+ Meml[v+1] = j
+ j = xt_imgnls (in[i], i, buf, Meml[v], 1)
+ } then {
+ call imseti (im, IM_PIXFD, NULL)
+ 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, scales, zeros, 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[ARB] # 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(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nmod, nm, pms
+pointer immap(), impnli()
+pointer impnlr(), imgnlr()
+errchk immap, ic_scale, imgetr, ic_grow, ic_grows, ic_rmasks, ic_emask
+errchk ic_gdatas
+
+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, SUM, QUAD, NMODEL:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Get noise model parameters.
+ if (combine==NMODEL) {
+ call salloc (nmod, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nmod+3*(i-1)+2] = r
+ }
+ }
+ }
+
+ # 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 (out[6] != NULL) {
+ keepids = true
+ call ic_einit (in, nimages, Memc[expkeyword], 1., 2**27-1)
+ }
+
+ 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)
+ }
+
+# This idea turns out to has a problem with masks are used with wcs offsets.
+# the matching of masks to images based on WCS requires access to the WCS
+# of the images. For now we drop this idea but maybe a way can be identified
+# to know when this is not going to be needed.
+# # Reduce header memory use.
+# do i = 1, nimages
+# call xt_minhdr (i)
+
+ 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, nimages, npts,
+ YES, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_medians (d, n, npts, YES, Memr[outdata])
+ case SUM:
+ call ic_averages (d, id, n, wts, nimages, npts,
+ YES, NO, Memr[outdata])
+ case QUAD:
+ call ic_quads (d, id, n, wts, nimages, npts,
+ YES, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodels (d, id, n, Memr[nmod], wts,
+ nimages, npts, YES, 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])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, nimages, npts,
+ NO, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_medians (d, n, npts, NO, Memr[outdata])
+ case SUM:
+ call ic_averages (d, id, n, wts, nimages, npts,
+ NO, NO, Memr[outdata])
+ case QUAD:
+ call ic_quads (d, id, n, wts, nimages, npts,
+ NO, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodels (d, id, n, Memr[nmod], wts,
+ nimages, npts, NO, YES, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, scales, zeros, wts, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[ARB] # Output images
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real wts[nimages] # Weights
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, k, npts, fd, stropen(), xt_imgnli()
+pointer sp, d, id, n, m, lflag, v, dbuf
+pointer im, buf, xt_opix(), impl1i()
+errchk stropen, xt_cpix, xt_opix, xt_imgnli, impl1i, ic_combinei
+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 (v, IM_MAXDIM, TY_LONG)
+ call amovki (D_ALL, Memi[lflag], nimages)
+ call amovkl (1, Meml[v], IM_MAXDIM)
+
+ # 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)
+ call aclri (Memi[Memi[dbuf+i-1]], npts)
+ }
+ } else {
+ do i = 1, nimages {
+ im = xt_opix (in[i], i, 1)
+ if (im != in[i]) {
+ call salloc (Memi[dbuf+i-1], npts, TY_INT)
+ call aclri (Memi[Memi[dbuf+i-1]], npts)
+ }
+ }
+ call amovki (NULL, Memi[dbuf], nimages)
+ }
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFFRAC, 0)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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)
+ }
+ if (out[4] != NULL) {
+ buf = impl1i (out[4])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[5] != NULL) {
+ buf = impl1i (out[5])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[6] != NULL) {
+ buf = impl1i (out[6])
+ call aclri (Memi[buf], npts)
+ }
+
+ # Do I/O for first input image line.
+ if (!project) {
+ do i = 1, nimages {
+ call xt_imseti (i, "bufsize", bufsize)
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ call xt_cpix (i)
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+
+ do i = 1, nimages {
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ next
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ next
+ iferr {
+ Meml[v+1] = j
+ j = xt_imgnli (in[i], i, buf, Meml[v], 1)
+ } then {
+ call imseti (im, IM_PIXFD, NULL)
+ 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, scales, zeros, 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[ARB] # 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(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nmod, nm, pms
+pointer immap(), impnli()
+pointer impnlr(), imgnlr()
+errchk immap, ic_scale, imgetr, ic_grow, ic_growi, ic_rmasks, ic_emask
+errchk ic_gdatai
+
+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, SUM, QUAD, NMODEL:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Get noise model parameters.
+ if (combine==NMODEL) {
+ call salloc (nmod, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nmod+3*(i-1)+2] = r
+ }
+ }
+ }
+
+ # 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 (out[6] != NULL) {
+ keepids = true
+ call ic_einit (in, nimages, Memc[expkeyword], 1., 2**27-1)
+ }
+
+ 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)
+ }
+
+# This idea turns out to has a problem with masks are used with wcs offsets.
+# the matching of masks to images based on WCS requires access to the WCS
+# of the images. For now we drop this idea but maybe a way can be identified
+# to know when this is not going to be needed.
+# # Reduce header memory use.
+# do i = 1, nimages
+# call xt_minhdr (i)
+
+ 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, nimages, npts,
+ YES, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_mediani (d, n, npts, YES, Memr[outdata])
+ case SUM:
+ call ic_averagei (d, id, n, wts, nimages, npts,
+ YES, NO, Memr[outdata])
+ case QUAD:
+ call ic_quadi (d, id, n, wts, nimages, npts,
+ YES, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodeli (d, id, n, Memr[nmod], wts,
+ nimages, npts, YES, 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])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, nimages, npts,
+ NO, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_mediani (d, n, npts, NO, Memr[outdata])
+ case SUM:
+ call ic_averagei (d, id, n, wts, nimages, npts,
+ NO, NO, Memr[outdata])
+ case QUAD:
+ call ic_quadi (d, id, n, wts, nimages, npts,
+ NO, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodeli (d, id, n, Memr[nmod], wts,
+ nimages, npts, NO, YES, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, scales, zeros, wts, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[ARB] # Output images
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real wts[nimages] # Weights
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, k, npts, fd, stropen(), xt_imgnlr()
+pointer sp, d, id, n, m, lflag, v, dbuf
+pointer im, buf, xt_opix(), impl1i()
+errchk stropen, xt_cpix, xt_opix, xt_imgnlr, impl1i, ic_combiner
+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 (v, IM_MAXDIM, TY_LONG)
+ call amovki (D_ALL, Memi[lflag], nimages)
+ call amovkl (1, Meml[v], IM_MAXDIM)
+
+ # 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)
+ call aclrr (Memr[Memi[dbuf+i-1]], npts)
+ }
+ } else {
+ do i = 1, nimages {
+ im = xt_opix (in[i], i, 1)
+ if (im != in[i]) {
+ call salloc (Memi[dbuf+i-1], npts, TY_REAL)
+ call aclrr (Memr[Memi[dbuf+i-1]], npts)
+ }
+ }
+ call amovki (NULL, Memi[dbuf], nimages)
+ }
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFFRAC, 0)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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)
+ }
+ if (out[4] != NULL) {
+ buf = impl1i (out[4])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[5] != NULL) {
+ buf = impl1i (out[5])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[6] != NULL) {
+ buf = impl1i (out[6])
+ call aclri (Memi[buf], npts)
+ }
+
+ # Do I/O for first input image line.
+ if (!project) {
+ do i = 1, nimages {
+ call xt_imseti (i, "bufsize", bufsize)
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ call xt_cpix (i)
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+
+ do i = 1, nimages {
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ next
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ next
+ iferr {
+ Meml[v+1] = j
+ j = xt_imgnlr (in[i], i, buf, Meml[v], 1)
+ } then {
+ call imseti (im, IM_PIXFD, NULL)
+ 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, scales, zeros, 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[ARB] # 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(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nmod, nm, pms
+pointer immap(), impnli()
+pointer impnlr(), imgnlr
+errchk immap, ic_scale, imgetr, ic_grow, ic_growr, ic_rmasks, ic_emask
+errchk ic_gdatar
+
+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, SUM, QUAD, NMODEL:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Get noise model parameters.
+ if (combine==NMODEL) {
+ call salloc (nmod, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nmod+3*(i-1)+2] = r
+ }
+ }
+ }
+
+ # 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 (out[6] != NULL) {
+ keepids = true
+ call ic_einit (in, nimages, Memc[expkeyword], 1., 2**27-1)
+ }
+
+ 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)
+ }
+
+# This idea turns out to has a problem with masks are used with wcs offsets.
+# the matching of masks to images based on WCS requires access to the WCS
+# of the images. For now we drop this idea but maybe a way can be identified
+# to know when this is not going to be needed.
+# # Reduce header memory use.
+# do i = 1, nimages
+# call xt_minhdr (i)
+
+ 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, nimages, npts,
+ YES, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_medianr (d, n, npts, YES, Memr[outdata])
+ case SUM:
+ call ic_averager (d, id, n, wts, nimages, npts,
+ YES, NO, Memr[outdata])
+ case QUAD:
+ call ic_quadr (d, id, n, wts, nimages, npts,
+ YES, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodelr (d, id, n, Memr[nmod], wts,
+ nimages, npts, YES, 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])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, nimages, npts,
+ NO, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_medianr (d, n, npts, NO, Memr[outdata])
+ case SUM:
+ call ic_averager (d, id, n, wts, nimages, npts,
+ NO, NO, Memr[outdata])
+ case QUAD:
+ call ic_quadr (d, id, n, wts, nimages, npts,
+ NO, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodelr (d, id, n, Memr[nmod], wts,
+ nimages, npts, NO, YES, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, scales, zeros, wts, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[ARB] # Output images
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real wts[nimages] # Weights
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, k, npts, fd, stropen(), xt_imgnld()
+pointer sp, d, id, n, m, lflag, v, dbuf
+pointer im, buf, xt_opix(), impl1i()
+errchk stropen, xt_cpix, xt_opix, xt_imgnld, impl1i, ic_combined
+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 (v, IM_MAXDIM, TY_LONG)
+ call amovki (D_ALL, Memi[lflag], nimages)
+ call amovkl (1, Meml[v], IM_MAXDIM)
+
+ # 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)
+ call aclrd (Memd[Memi[dbuf+i-1]], npts)
+ }
+ } else {
+ do i = 1, nimages {
+ im = xt_opix (in[i], i, 1)
+ if (im != in[i]) {
+ call salloc (Memi[dbuf+i-1], npts, TY_DOUBLE)
+ call aclrd (Memd[Memi[dbuf+i-1]], npts)
+ }
+ }
+ call amovki (NULL, Memi[dbuf], nimages)
+ }
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFFRAC, 0)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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)
+ }
+ if (out[4] != NULL) {
+ buf = impl1i (out[4])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[5] != NULL) {
+ buf = impl1i (out[5])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[6] != NULL) {
+ buf = impl1i (out[6])
+ call aclri (Memi[buf], npts)
+ }
+
+ # Do I/O for first input image line.
+ if (!project) {
+ do i = 1, nimages {
+ call xt_imseti (i, "bufsize", bufsize)
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ call xt_cpix (i)
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+
+ do i = 1, nimages {
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ next
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ next
+ iferr {
+ Meml[v+1] = j
+ j = xt_imgnld (in[i], i, buf, Meml[v], 1)
+ } then {
+ call imseti (im, IM_PIXFD, NULL)
+ 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, scales, zeros, 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[ARB] # 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(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nmod, nm, pms
+pointer immap(), impnli()
+pointer impnld(), imgnld
+errchk immap, ic_scale, imgetr, ic_grow, ic_growd, ic_rmasks, ic_emask
+errchk ic_gdatad
+
+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, SUM, QUAD, NMODEL:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Get noise model parameters.
+ if (combine==NMODEL) {
+ call salloc (nmod, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nmod+3*(i-1)+2] = r
+ }
+ }
+ }
+
+ # 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 (out[6] != NULL) {
+ keepids = true
+ call ic_einit (in, nimages, Memc[expkeyword], 1., 2**27-1)
+ }
+
+ 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)
+ }
+
+# This idea turns out to has a problem with masks are used with wcs offsets.
+# the matching of masks to images based on WCS requires access to the WCS
+# of the images. For now we drop this idea but maybe a way can be identified
+# to know when this is not going to be needed.
+# # Reduce header memory use.
+# do i = 1, nimages
+# call xt_minhdr (i)
+
+ 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, nimages, npts,
+ YES, YES, Memd[outdata])
+ case MEDIAN:
+ call ic_mediand (d, n, npts, YES, Memd[outdata])
+ case SUM:
+ call ic_averaged (d, id, n, wts, nimages, npts,
+ YES, NO, Memd[outdata])
+ case QUAD:
+ call ic_quadd (d, id, n, wts, nimages, npts,
+ YES, YES, Memd[outdata])
+ case NMODEL:
+ call ic_nmodeld (d, id, n, Memr[nmod], wts,
+ nimages, npts, YES, 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])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, nimages, npts,
+ NO, YES, Memd[outdata])
+ case MEDIAN:
+ call ic_mediand (d, n, npts, NO, Memd[outdata])
+ case SUM:
+ call ic_averaged (d, id, n, wts, nimages, npts,
+ NO, NO, Memd[outdata])
+ case QUAD:
+ call ic_quadd (d, id, n, wts, nimages, npts,
+ NO, YES, Memd[outdata])
+ case NMODEL:
+ call ic_nmodeld (d, id, n, Memr[nmod], wts,
+ nimages, npts, NO, YES, Memd[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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
+
diff --git a/pkg/images/immatch/src/imcombine/src/generic/icpclip.x b/pkg/images/immatch/src/imcombine/src/generic/icpclip.x
new file mode 100644
index 00000000..3dfe7f48
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icpclip.x
@@ -0,0 +1,879 @@
+# 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 = max (0, 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 = max (0, 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 == max (0, 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 (max (0, 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 = max (0, 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 = max (0, 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 == max (0, 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 (max (0, 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 = max (0, 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 = max (0, 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 == max (0, 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 (max (0, 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 = max (0, 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 = max (0, 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/generic/icquad.x b/pkg/images/immatch/src/imcombine/src/generic/icquad.x
new file mode 100644
index 00000000..4ba5eb14
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icquad.x
@@ -0,0 +1,476 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+include "../icmask.h"
+
+
+# IC_QUAD -- Compute the quadrature average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_quads (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = Mems[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ do j = 2, n[i] {
+ val = Mems[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val * wt) ** 2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = Mems[d[1]+k]
+ sum = val**2
+ do j = 2, n[i] {
+ val = Mems[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Mems[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ sumwt = wt
+ do j = 2, n1 {
+ val = Mems[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val* wt) ** 2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = Mems[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Mems[d[j]+k]
+ sum = sum + val**2
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Mems[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Mems[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_QUAD -- Compute the quadrature average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_quadi (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = Memi[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ do j = 2, n[i] {
+ val = Memi[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val * wt) ** 2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = Memi[d[1]+k]
+ sum = val**2
+ do j = 2, n[i] {
+ val = Memi[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Memi[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ sumwt = wt
+ do j = 2, n1 {
+ val = Memi[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val* wt) ** 2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = Memi[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Memi[d[j]+k]
+ sum = sum + val**2
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Memi[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Memi[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_QUAD -- Compute the quadrature average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_quadr (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+real average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+real sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = Memr[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ do j = 2, n[i] {
+ val = Memr[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val * wt) ** 2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = Memr[d[1]+k]
+ sum = val**2
+ do j = 2, n[i] {
+ val = Memr[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Memr[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ sumwt = wt
+ do j = 2, n1 {
+ val = Memr[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val* wt) ** 2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = Memr[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Memr[d[j]+k]
+ sum = sum + val**2
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Memr[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Memr[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
+# IC_QUAD -- Compute the quadrature average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_quadd (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+double average[npts] # Average (returned)
+
+int i, j, k, n1
+real val, wt, sumwt
+double sum
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = Memd[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ do j = 2, n[i] {
+ val = Memd[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val * wt) ** 2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = Memd[d[1]+k]
+ sum = val**2
+ do j = 2, n[i] {
+ val = Memd[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Memd[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ sumwt = wt
+ do j = 2, n1 {
+ val = Memd[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val* wt) ** 2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = Memd[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Memd[d[j]+k]
+ sum = sum + val**2
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Memd[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Memd[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+
diff --git a/pkg/images/immatch/src/imcombine/src/generic/icsclip.x b/pkg/images/immatch/src/imcombine/src/generic/icsclip.x
new file mode 100644
index 00000000..2f2ac17e
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icsclip.x
@@ -0,0 +1,1923 @@
+# 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/generic/icsigma.x b/pkg/images/immatch/src/imcombine/src/generic/icsigma.x
new file mode 100644
index 00000000..b9c9a781
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icsigma.x
@@ -0,0 +1,434 @@
+# 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
+ }
+ if (sumwt > 0)
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ else {
+ sum = (Mems[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Mems[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum / n1 * 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
+ }
+ if (sumwt > 0)
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ else {
+ sum = (Memi[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memi[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum / n1 * 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
+ }
+ if (sumwt > 0)
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ else {
+ sum = (Memr[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memr[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum / n1 * 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
+ }
+ if (sumwt > 0)
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ else {
+ sum = (Memd[d[1]+k] - a) ** 2
+ do j = 2, n1
+ sum = sum + (Memd[d[j]+k] - a) ** 2
+ sigma[i] = sqrt (sum / n1 * 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/images/immatch/src/imcombine/src/generic/icsort.x b/pkg/images/immatch/src/imcombine/src/generic/icsort.x
new file mode 100644
index 00000000..3ec1d27e
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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/images/immatch/src/imcombine/src/generic/icstat.x b/pkg/images/immatch/src/imcombine/src/generic/icstat.x
new file mode 100644
index 00000000..3a0ed49c
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/icstat.x
@@ -0,0 +1,892 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+define NMAX 100000 # 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()
+
+real asums()
+short ic_modes()
+
+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, nimages, 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)
+ }
+
+ # Close mask until it is needed again.
+ call ic_mclose1 (image, nimages)
+
+ 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.7 # 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()
+
+real asumi()
+int ic_modei()
+
+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, nimages, 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)
+ }
+
+ # Close mask until it is needed again.
+ call ic_mclose1 (image, nimages)
+
+ 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.7 # 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 asumr()
+real ic_moder()
+
+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, nimages, 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)
+ }
+
+ # Close mask until it is needed again.
+ call ic_mclose1 (image, nimages)
+
+ 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.7 # 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 asumd()
+double ic_moded()
+
+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, nimages, 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)
+ }
+
+ # Close mask until it is needed again.
+ call ic_mclose1 (image, nimages)
+
+ 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.7 # 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/images/immatch/src/imcombine/src/generic/mkpkg b/pkg/images/immatch/src/imcombine/src/generic/mkpkg
new file mode 100644
index 00000000..af2fd0a8
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/mkpkg
@@ -0,0 +1,27 @@
+# Make IMCOMBINE.
+
+$checkout libimc.a lib$
+$update libimc.a
+$checkin libimc.a lib$
+$exit
+
+libimc.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
+ icnmodel.x ../icombine.com ../icombine.h <imhdr.h>
+ icomb.x ../icombine.com ../icombine.h <error.h> <imhdr.h>\
+ <imset.h> <mach.h> <pmset.h> <syserr.h>
+ icpclip.x ../icombine.com ../icombine.h
+ icquad.x ../icombine.com ../icombine.h <imhdr.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>
+
+ xtimmap.x xtimmap.com <config.h> <error.h> <imhdr.h> <imset.h>
+ ;
diff --git a/pkg/images/immatch/src/imcombine/src/generic/xtimmap.com b/pkg/images/immatch/src/imcombine/src/generic/xtimmap.com
new file mode 100644
index 00000000..57fcb8a0
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/xtimmap.com
@@ -0,0 +1,9 @@
+int option
+int nopen
+int nopenpix
+int nalloc
+int last_flag
+int min_open
+int max_openim
+pointer ims
+common /xtimmapcom/ option, ims, nopen, nopenpix, nalloc, last_flag, min_open, max_openim
diff --git a/pkg/images/immatch/src/imcombine/src/generic/xtimmap.x b/pkg/images/immatch/src/imcombine/src/generic/xtimmap.x
new file mode 100644
index 00000000..fcc53124
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/generic/xtimmap.x
@@ -0,0 +1,1207 @@
+include <syserr.h>
+include <error.h>
+include <imhdr.h>
+include <imset.h>
+include <config.h>
+
+# The following is for compiling under V2.11.
+define IM_BUFFRAC IM_BUFSIZE
+include <imset.h>
+
+define VERBOSE false
+
+# These routines maintain an arbitrary number of indexed "open" images which
+# must be READ_ONLY. The calling program may use the returned pointer for
+# header accesses but must call xt_opix before I/O. Subsequent calls to
+# xt_opix may invalidate the pointer. The xt_imunmap call will free memory.
+
+define MAX_OPENIM (LAST_FD-16) # Maximum images kept open
+define MAX_OPENPIX 45 # Maximum pixel files kept open
+
+define XT_SZIMNAME 299 # Size of IMNAME string
+define XT_LEN 179 # Structure length
+define XT_IMNAME Memc[P2C($1)] # Image name
+define XT_ARG Memi[$1+150] # IMMAP header argument
+define XT_IM Memi[$1+151] # IMIO pointer
+define XT_HDR Memi[$1+152] # Copy of IMIO pointer
+define XT_CLOSEFD Memi[$1+153] # Close FD?
+define XT_FLAG Memi[$1+154] # Flag
+define XT_BUFSIZE Memi[$1+155] # Buffer size
+define XT_BUF Memi[$1+156] # Data buffer
+define XT_BTYPE Memi[$1+157] # Data buffer type
+define XT_VS Memi[$1+157+$2] # Start vector (10)
+define XT_VE Memi[$1+167+$2] # End vector (10)
+
+# Options
+define XT_MAPUNMAP 1 # Map and unmap images.
+
+# XT_IMMAP -- Map an image and save it as an indexed open image.
+# The returned pointer may be used for header access but not I/O.
+# The indexed image is closed by xt_imunmap.
+
+pointer procedure xt_immap (imname, acmode, hdr_arg, index, retry)
+
+char imname[ARB] #I Image name
+int acmode #I Access mode
+int hdr_arg #I Header argument
+int index #I Save index
+int retry #I Retry counter
+pointer im #O Image pointer (returned)
+
+int i, envgeti()
+pointer xt, xt_opix()
+errchk xt_opix
+
+int first_time
+data first_time /YES/
+
+include "xtimmap.com"
+
+begin
+ if (acmode != READ_ONLY)
+ call error (1, "XT_IMMAP: Only READ_ONLY allowed")
+
+ # Set maximum number of open images based on retry.
+ if (retry > 0)
+ max_openim = min (1024, MAX_OPENIM) / retry
+ else
+ max_openim = MAX_OPENIM
+
+ # Initialize once per process.
+ if (first_time == YES) {
+ iferr (option = envgeti ("imcombine_option"))
+ option = 1
+ min_open = 1
+ nopen = 0
+ nopenpix = 0
+ nalloc = max_openim
+ call calloc (ims, nalloc, TY_POINTER)
+ first_time = NO
+ }
+
+ # Free image if needed.
+ call xt_imunmap (NULL, index)
+
+ # Allocate structure.
+ if (index > nalloc) {
+ i = nalloc
+ nalloc = index + max_openim
+ call realloc (ims, nalloc, TY_STRUCT)
+ call amovki (NULL, Memi[ims+i], nalloc-i)
+ }
+ call calloc (xt, XT_LEN, TY_STRUCT)
+ Memi[ims+index-1] = xt
+
+ # Initialize.
+ call strcpy (imname, XT_IMNAME(xt), XT_SZIMNAME)
+ XT_ARG(xt) = hdr_arg
+ XT_IM(xt) = NULL
+ XT_HDR(xt) = NULL
+
+ # Open image.
+ last_flag = 0
+ im = xt_opix (NULL, index, 0)
+
+ # Make copy of IMIO pointer for header keyword access.
+ call malloc (XT_HDR(xt), LEN_IMDES+IM_HDRLEN(im)+1, TY_STRUCT)
+ call amovi (Memi[im], Memi[XT_HDR(xt)], LEN_IMDES)
+ call amovi (IM_MAGIC(im), IM_MAGIC(XT_HDR(xt)), IM_HDRLEN(im)+1)
+
+ return (XT_HDR(xt))
+end
+
+
+# XT_OPIX -- Open the image for I/O.
+# If the image has not been mapped return the default pointer.
+
+pointer procedure xt_opix (imdef, index, flag)
+
+int index #I index
+pointer imdef #I Default pointer
+int flag #I Flag
+
+int i, open(), imstati()
+pointer im, xt, xt1, immap()
+errchk open, immap, imunmap
+
+include "xtimmap.com"
+
+begin
+ # Get index pointer.
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ # Use default pointer if index has not been mapped.
+ if (xt == NULL)
+ return (imdef)
+
+ # Close images not accessed during previous line.
+ # In normal usage this should only occur once per line over all
+ # indexed images.
+ if (flag != last_flag) {
+ do i = 1, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL || XT_FLAG(xt1) == last_flag)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: xt_opix imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ call mfree (XT_BUF(xt1), XT_BTYPE(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ }
+
+ # Optimize the file I/O.
+ do i = nalloc, 1, -1 {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ if (nopenpix < MAX_OPENPIX) {
+ if (XT_CLOSEFD(xt1) == NO)
+ next
+ XT_CLOSEFD(xt1) = NO
+ call imseti (im, IM_CLOSEFD, NO)
+ nopenpix = nopenpix + 1
+ }
+ }
+ last_flag = flag
+ }
+
+ # Return pointer for already opened images.
+ im = XT_IM(xt)
+ if (im != NULL) {
+ XT_FLAG(xt) = flag
+ return (im)
+ }
+
+ # Handle more images than the maximum that can be open at one time.
+ if (nopen >= max_openim) {
+ if (option == XT_MAPUNMAP || flag == 0) {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ min_open = i + 1
+ break
+ }
+ if (index <= min_open)
+ min_open = index
+ else {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ break
+ }
+ }
+ } else {
+ # Check here because we can't catch error in immap.
+ i = open ("dev$null", READ_ONLY, BINARY_FILE)
+ call close (i)
+ if (i == LAST_FD - 1)
+ call error (SYS_FTOOMANYFILES, "Too many open files")
+ }
+ }
+
+ # Open image.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_opix immap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ im = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt))
+ XT_IM(xt) = im
+ if (!IS_INDEFI(XT_BUFSIZE(xt)))
+ call imseti (im, IM_BUFSIZE, XT_BUFSIZE(xt))
+ else
+ XT_BUFSIZE(xt) = imstati (im, IM_BUFSIZE)
+ nopen = nopen + 1
+ XT_CLOSEFD(xt) = YES
+ if (nopenpix < MAX_OPENPIX) {
+ XT_CLOSEFD(xt) = NO
+ nopenpix = nopenpix + 1
+ }
+ if (XT_CLOSEFD(xt) == YES)
+ call imseti (im, IM_CLOSEFD, YES)
+ XT_FLAG(xt) = flag
+
+ return (im)
+end
+
+
+# XT_CPIX -- Close image.
+
+procedure xt_cpix (index)
+
+int index #I index
+
+pointer xt
+errchk imunmap
+
+include "xtimmap.com"
+
+begin
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ if (xt == NULL)
+ return
+
+ if (XT_IM(xt) != NULL) {
+ if (VERBOSE) {
+ call eprintf ("%d: xt_cpix imunmap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ call imunmap (XT_IM(xt))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt) == NO)
+ nopenpix = nopenpix - 1
+ }
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+end
+
+
+# XT_IMSETI -- Set IMIO value.
+
+procedure xt_imseti (index, param, value)
+
+int index #I index
+int param #I IMSET parameter
+int value #I Value
+
+pointer xt
+bool streq()
+
+include "xtimmap.com"
+
+begin
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ if (xt == NULL) {
+ if (streq (param, "option"))
+ option = value
+ } else {
+ if (streq (param, "bufsize")) {
+ XT_BUFSIZE(xt) = value
+ if (XT_IM(xt) != NULL) {
+ call imseti (XT_IM(xt), IM_BUFFRAC, 0)
+ call imseti (XT_IM(xt), IM_BUFSIZE, value)
+ }
+ }
+ }
+end
+
+
+# XT_IMUNMAP -- Unmap indexed open image.
+# The header pointer is set to NULL to indicate the image has been closed.
+
+procedure xt_imunmap (im, index)
+
+int im #U IMIO header pointer
+int index #I index
+
+pointer xt
+errchk imunmap
+
+include "xtimmap.com"
+
+begin
+ # Check for an indexed image. If it is not unmap the pointer
+ # as a regular IMIO pointer.
+
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+ if (xt == NULL) {
+ if (im != NULL)
+ call imunmap (im)
+ return
+ }
+
+ # Close indexed image.
+ if (XT_IM(xt) != NULL) {
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imunmap imunmap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ iferr (call imunmap (XT_IM(xt))) {
+ XT_IM(xt) = NULL
+ call erract (EA_WARN)
+ }
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt) == NO)
+ nopenpix = nopenpix - 1
+ if (index == min_open)
+ min_open = 1
+ }
+
+ # Free any buffered memory.
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+
+ # Free header pointer. Note that if the supplied pointer is not
+ # header pointer then it is not set to NULL.
+ if (XT_HDR(xt) == im)
+ im = NULL
+ call mfree (XT_HDR(xt), TY_STRUCT)
+
+ # Free save structure.
+ call mfree (Memi[ims+index-1], TY_STRUCT)
+ Memi[ims+index-1] = NULL
+end
+
+
+# XT_MINHDR -- Minimize header assuming keywords will not be accessed.
+
+procedure xt_minhdr (index)
+
+int index #I index
+
+pointer xt
+errchk realloc
+
+include "xtimmap.com"
+
+begin
+ # Check for an indexed image. If it is not unmap the pointer
+ # as a regular IMIO pointer.
+
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+ if (xt == NULL)
+ return
+
+ # Minimize header pointer.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_minhdr %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ call realloc (XT_HDR(xt), IMU+1, TY_STRUCT)
+ if (XT_IM(xt) != NULL)
+ call realloc (XT_IM(xt), IMU+1, TY_STRUCT)
+end
+
+
+# XT_REINDEX -- Reindex open images.
+# This is used when some images are closed by xt_imunmap. It is up to
+# the calling program to reindex the header pointers and to subsequently
+# use the new index values.
+
+procedure xt_reindex ()
+
+int old, new
+
+include "xtimmap.com"
+
+begin
+ new = 0
+ do old = 0, nalloc-1 {
+ if (Memi[ims+old] == NULL)
+ next
+ Memi[ims+new] = Memi[ims+old]
+ new = new + 1
+ }
+ do old = new, nalloc-1
+ Memi[ims+old] = NULL
+end
+
+
+
+# XT_IMGNL -- Return the next line for the indexed image.
+# Possibly unmap another image if too many files are open.
+# Buffer data when an image is unmmaped to minimize the mapping of images.
+# If the requested index has not been mapped use the default pointer.
+
+int procedure xt_imgnls (imdef, index, buf, v, flag)
+
+pointer imdef #I Default pointer
+int index #I index
+pointer buf #O Data buffer
+long v[ARB] #I Line vector
+int flag #I Flag (=output line)
+
+int i, j, nc, nl, open(), imgnls(), sizeof(), imloop()
+pointer im, xt, xt1, ptr, immap(), imggss()
+errchk open, immap, imgnls, imggss, imunmap
+
+long unit_v[IM_MAXDIM]
+data unit_v /IM_MAXDIM * 1/
+
+include "xtimmap.com"
+
+begin
+ # Get index pointer.
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ # Use default pointer if index has not been mapped.
+ if (xt == NULL)
+ return (imgnls (imdef, buf, v))
+
+ # Close images not accessed during previous line.
+ # In normal usage this should only occur once per line over all
+ # indexed images.
+ if (flag != last_flag) {
+ do i = 1, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL || XT_FLAG(xt1) == last_flag)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ call mfree (XT_BUF(xt1), XT_BTYPE(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ }
+
+ # Optimize the file I/O.
+ do i = nalloc, 1, -1 {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ if (nopenpix < MAX_OPENPIX) {
+ if (XT_CLOSEFD(xt1) == NO)
+ next
+ XT_CLOSEFD(xt1) = NO
+ call imseti (im, IM_CLOSEFD, NO)
+ nopenpix = nopenpix + 1
+ }
+ }
+ last_flag = flag
+ }
+
+ # Use IMIO for already opened images.
+ im = XT_IM(xt)
+ if (im != NULL) {
+ XT_FLAG(xt) = flag
+ return (imgnls (im, buf, v))
+ }
+
+ # If the image is not currently mapped use the stored header.
+ im = XT_HDR(xt)
+
+ # Check for EOF.
+ i = IM_NDIM(im)
+ if (v[i] > IM_LEN(im,i))
+ return (EOF)
+
+ # Check for buffered data.
+ if (XT_BUF(xt) != NULL) {
+ if (v[2] >= XT_VS(xt,2) && v[2] <= XT_VE(xt,2)) {
+ if (XT_BTYPE(xt) != TY_SHORT)
+ call error (1, "Cannot mix data types")
+ nc = IM_LEN(im,1)
+ buf = XT_BUF(xt) + (v[2]-XT_VS(xt,2)) * IM_LEN(im,1)
+ XT_FLAG(xt) = flag
+ if (i == 1)
+ v[1] = nc + 1
+ else
+ j = imloop (v, unit_v, IM_LEN(im,1), unit_v, i)
+ return (nc)
+ }
+ }
+
+ # Handle more images than the maximum that can be open at one time.
+ if (nopen >= max_openim) {
+ if (option == XT_MAPUNMAP || v[2] == 0) {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+
+ # Buffer some number of lines.
+ nl = XT_BUFSIZE(xt1) / sizeof (TY_SHORT) / IM_LEN(im,1)
+ if (nl > 1) {
+ nc = IM_LEN(im,1)
+ call amovl (v, XT_VS(xt1,1), IM_MAXDIM)
+ call amovl (v, XT_VE(xt1,1), IM_MAXDIM)
+ XT_VS(xt1,1) = 1
+ XT_VE(xt1,1) = nc
+ XT_VE(xt1,2) = min (XT_VS(xt1,2)+(nl-1), IM_LEN(im,2))
+ nl = XT_VE(xt1,2) - XT_VS(xt1,2) + 1
+ XT_BTYPE(xt1) = TY_SHORT
+ call malloc (XT_BUF(xt1), nl*nc, XT_BTYPE(xt1))
+ ptr = imggss (im, XT_VS(xt1,1), XT_VE(xt1,1),
+ IM_NDIM(im))
+ call amovs (Mems[ptr], Mems[XT_BUF(xt1)], nl*nc)
+ }
+
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ min_open = i + 1
+ break
+ }
+ if (index <= min_open)
+ min_open = index
+ else {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ if (XT_IM(xt1) == NULL)
+ next
+ min_open = i
+ break
+ }
+ }
+ } else {
+ # Check here because we can't catch error in immap.
+ i = open ("dev$null", READ_ONLY, BINARY_FILE)
+ call close (i)
+ if (i == LAST_FD - 1)
+ call error (SYS_FTOOMANYFILES, "Too many open files")
+ }
+ }
+
+ # Open image.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl immap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ im = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt))
+ XT_IM(xt) = im
+ call imseti (im, IM_BUFSIZE, XT_BUFSIZE(xt))
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+ nopen = nopen + 1
+ XT_CLOSEFD(xt) = YES
+ if (nopenpix < MAX_OPENPIX) {
+ XT_CLOSEFD(xt) = NO
+ nopenpix = nopenpix + 1
+ }
+ if (XT_CLOSEFD(xt) == YES)
+ call imseti (im, IM_CLOSEFD, YES)
+ XT_FLAG(xt) = flag
+
+ return (imgnls (im, buf, v))
+end
+
+# XT_IMGNL -- Return the next line for the indexed image.
+# Possibly unmap another image if too many files are open.
+# Buffer data when an image is unmmaped to minimize the mapping of images.
+# If the requested index has not been mapped use the default pointer.
+
+int procedure xt_imgnli (imdef, index, buf, v, flag)
+
+pointer imdef #I Default pointer
+int index #I index
+pointer buf #O Data buffer
+long v[ARB] #I Line vector
+int flag #I Flag (=output line)
+
+int i, j, nc, nl, open(), imgnli(), sizeof(), imloop()
+pointer im, xt, xt1, ptr, immap(), imggsi()
+errchk open, immap, imgnli, imggsi, imunmap
+
+long unit_v[IM_MAXDIM]
+data unit_v /IM_MAXDIM * 1/
+
+include "xtimmap.com"
+
+begin
+ # Get index pointer.
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ # Use default pointer if index has not been mapped.
+ if (xt == NULL)
+ return (imgnli (imdef, buf, v))
+
+ # Close images not accessed during previous line.
+ # In normal usage this should only occur once per line over all
+ # indexed images.
+ if (flag != last_flag) {
+ do i = 1, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL || XT_FLAG(xt1) == last_flag)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ call mfree (XT_BUF(xt1), XT_BTYPE(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ }
+
+ # Optimize the file I/O.
+ do i = nalloc, 1, -1 {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ if (nopenpix < MAX_OPENPIX) {
+ if (XT_CLOSEFD(xt1) == NO)
+ next
+ XT_CLOSEFD(xt1) = NO
+ call imseti (im, IM_CLOSEFD, NO)
+ nopenpix = nopenpix + 1
+ }
+ }
+ last_flag = flag
+ }
+
+ # Use IMIO for already opened images.
+ im = XT_IM(xt)
+ if (im != NULL) {
+ XT_FLAG(xt) = flag
+ return (imgnli (im, buf, v))
+ }
+
+ # If the image is not currently mapped use the stored header.
+ im = XT_HDR(xt)
+
+ # Check for EOF.
+ i = IM_NDIM(im)
+ if (v[i] > IM_LEN(im,i))
+ return (EOF)
+
+ # Check for buffered data.
+ if (XT_BUF(xt) != NULL) {
+ if (v[2] >= XT_VS(xt,2) && v[2] <= XT_VE(xt,2)) {
+ if (XT_BTYPE(xt) != TY_INT)
+ call error (1, "Cannot mix data types")
+ nc = IM_LEN(im,1)
+ buf = XT_BUF(xt) + (v[2]-XT_VS(xt,2)) * IM_LEN(im,1)
+ XT_FLAG(xt) = flag
+ if (i == 1)
+ v[1] = nc + 1
+ else
+ j = imloop (v, unit_v, IM_LEN(im,1), unit_v, i)
+ return (nc)
+ }
+ }
+
+ # Handle more images than the maximum that can be open at one time.
+ if (nopen >= max_openim) {
+ if (option == XT_MAPUNMAP || v[2] == 0) {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+
+ # Buffer some number of lines.
+ nl = XT_BUFSIZE(xt1) / sizeof (TY_INT) / IM_LEN(im,1)
+ if (nl > 1) {
+ nc = IM_LEN(im,1)
+ call amovl (v, XT_VS(xt1,1), IM_MAXDIM)
+ call amovl (v, XT_VE(xt1,1), IM_MAXDIM)
+ XT_VS(xt1,1) = 1
+ XT_VE(xt1,1) = nc
+ XT_VE(xt1,2) = min (XT_VS(xt1,2)+(nl-1), IM_LEN(im,2))
+ nl = XT_VE(xt1,2) - XT_VS(xt1,2) + 1
+ XT_BTYPE(xt1) = TY_INT
+ call malloc (XT_BUF(xt1), nl*nc, XT_BTYPE(xt1))
+ ptr = imggsi (im, XT_VS(xt1,1), XT_VE(xt1,1),
+ IM_NDIM(im))
+ call amovi (Memi[ptr], Memi[XT_BUF(xt1)], nl*nc)
+ }
+
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ min_open = i + 1
+ break
+ }
+ if (index <= min_open)
+ min_open = index
+ else {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ if (XT_IM(xt1) == NULL)
+ next
+ min_open = i
+ break
+ }
+ }
+ } else {
+ # Check here because we can't catch error in immap.
+ i = open ("dev$null", READ_ONLY, BINARY_FILE)
+ call close (i)
+ if (i == LAST_FD - 1)
+ call error (SYS_FTOOMANYFILES, "Too many open files")
+ }
+ }
+
+ # Open image.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl immap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ im = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt))
+ XT_IM(xt) = im
+ call imseti (im, IM_BUFSIZE, XT_BUFSIZE(xt))
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+ nopen = nopen + 1
+ XT_CLOSEFD(xt) = YES
+ if (nopenpix < MAX_OPENPIX) {
+ XT_CLOSEFD(xt) = NO
+ nopenpix = nopenpix + 1
+ }
+ if (XT_CLOSEFD(xt) == YES)
+ call imseti (im, IM_CLOSEFD, YES)
+ XT_FLAG(xt) = flag
+
+ return (imgnli (im, buf, v))
+end
+
+# XT_IMGNL -- Return the next line for the indexed image.
+# Possibly unmap another image if too many files are open.
+# Buffer data when an image is unmmaped to minimize the mapping of images.
+# If the requested index has not been mapped use the default pointer.
+
+int procedure xt_imgnlr (imdef, index, buf, v, flag)
+
+pointer imdef #I Default pointer
+int index #I index
+pointer buf #O Data buffer
+long v[ARB] #I Line vector
+int flag #I Flag (=output line)
+
+int i, j, nc, nl, open(), imgnlr(), sizeof(), imloop()
+pointer im, xt, xt1, ptr, immap(), imggsr()
+errchk open, immap, imgnlr, imggsr, imunmap
+
+long unit_v[IM_MAXDIM]
+data unit_v /IM_MAXDIM * 1/
+
+include "xtimmap.com"
+
+begin
+ # Get index pointer.
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ # Use default pointer if index has not been mapped.
+ if (xt == NULL)
+ return (imgnlr (imdef, buf, v))
+
+ # Close images not accessed during previous line.
+ # In normal usage this should only occur once per line over all
+ # indexed images.
+ if (flag != last_flag) {
+ do i = 1, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL || XT_FLAG(xt1) == last_flag)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ call mfree (XT_BUF(xt1), XT_BTYPE(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ }
+
+ # Optimize the file I/O.
+ do i = nalloc, 1, -1 {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ if (nopenpix < MAX_OPENPIX) {
+ if (XT_CLOSEFD(xt1) == NO)
+ next
+ XT_CLOSEFD(xt1) = NO
+ call imseti (im, IM_CLOSEFD, NO)
+ nopenpix = nopenpix + 1
+ }
+ }
+ last_flag = flag
+ }
+
+ # Use IMIO for already opened images.
+ im = XT_IM(xt)
+ if (im != NULL) {
+ XT_FLAG(xt) = flag
+ return (imgnlr (im, buf, v))
+ }
+
+ # If the image is not currently mapped use the stored header.
+ im = XT_HDR(xt)
+
+ # Check for EOF.
+ i = IM_NDIM(im)
+ if (v[i] > IM_LEN(im,i))
+ return (EOF)
+
+ # Check for buffered data.
+ if (XT_BUF(xt) != NULL) {
+ if (v[2] >= XT_VS(xt,2) && v[2] <= XT_VE(xt,2)) {
+ if (XT_BTYPE(xt) != TY_REAL)
+ call error (1, "Cannot mix data types")
+ nc = IM_LEN(im,1)
+ buf = XT_BUF(xt) + (v[2]-XT_VS(xt,2)) * IM_LEN(im,1)
+ XT_FLAG(xt) = flag
+ if (i == 1)
+ v[1] = nc + 1
+ else
+ j = imloop (v, unit_v, IM_LEN(im,1), unit_v, i)
+ return (nc)
+ }
+ }
+
+ # Handle more images than the maximum that can be open at one time.
+ if (nopen >= max_openim) {
+ if (option == XT_MAPUNMAP || v[2] == 0) {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+
+ # Buffer some number of lines.
+ nl = XT_BUFSIZE(xt1) / sizeof (TY_REAL) / IM_LEN(im,1)
+ if (nl > 1) {
+ nc = IM_LEN(im,1)
+ call amovl (v, XT_VS(xt1,1), IM_MAXDIM)
+ call amovl (v, XT_VE(xt1,1), IM_MAXDIM)
+ XT_VS(xt1,1) = 1
+ XT_VE(xt1,1) = nc
+ XT_VE(xt1,2) = min (XT_VS(xt1,2)+(nl-1), IM_LEN(im,2))
+ nl = XT_VE(xt1,2) - XT_VS(xt1,2) + 1
+ XT_BTYPE(xt1) = TY_REAL
+ call malloc (XT_BUF(xt1), nl*nc, XT_BTYPE(xt1))
+ ptr = imggsr (im, XT_VS(xt1,1), XT_VE(xt1,1),
+ IM_NDIM(im))
+ call amovr (Memr[ptr], Memr[XT_BUF(xt1)], nl*nc)
+ }
+
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ min_open = i + 1
+ break
+ }
+ if (index <= min_open)
+ min_open = index
+ else {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ if (XT_IM(xt1) == NULL)
+ next
+ min_open = i
+ break
+ }
+ }
+ } else {
+ # Check here because we can't catch error in immap.
+ i = open ("dev$null", READ_ONLY, BINARY_FILE)
+ call close (i)
+ if (i == LAST_FD - 1)
+ call error (SYS_FTOOMANYFILES, "Too many open files")
+ }
+ }
+
+ # Open image.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl immap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ im = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt))
+ XT_IM(xt) = im
+ call imseti (im, IM_BUFSIZE, XT_BUFSIZE(xt))
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+ nopen = nopen + 1
+ XT_CLOSEFD(xt) = YES
+ if (nopenpix < MAX_OPENPIX) {
+ XT_CLOSEFD(xt) = NO
+ nopenpix = nopenpix + 1
+ }
+ if (XT_CLOSEFD(xt) == YES)
+ call imseti (im, IM_CLOSEFD, YES)
+ XT_FLAG(xt) = flag
+
+ return (imgnlr (im, buf, v))
+end
+
+# XT_IMGNL -- Return the next line for the indexed image.
+# Possibly unmap another image if too many files are open.
+# Buffer data when an image is unmmaped to minimize the mapping of images.
+# If the requested index has not been mapped use the default pointer.
+
+int procedure xt_imgnld (imdef, index, buf, v, flag)
+
+pointer imdef #I Default pointer
+int index #I index
+pointer buf #O Data buffer
+long v[ARB] #I Line vector
+int flag #I Flag (=output line)
+
+int i, j, nc, nl, open(), imgnld(), sizeof(), imloop()
+pointer im, xt, xt1, ptr, immap(), imggsd()
+errchk open, immap, imgnld, imggsd, imunmap
+
+long unit_v[IM_MAXDIM]
+data unit_v /IM_MAXDIM * 1/
+
+include "xtimmap.com"
+
+begin
+ # Get index pointer.
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ # Use default pointer if index has not been mapped.
+ if (xt == NULL)
+ return (imgnld (imdef, buf, v))
+
+ # Close images not accessed during previous line.
+ # In normal usage this should only occur once per line over all
+ # indexed images.
+ if (flag != last_flag) {
+ do i = 1, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL || XT_FLAG(xt1) == last_flag)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ call mfree (XT_BUF(xt1), XT_BTYPE(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ }
+
+ # Optimize the file I/O.
+ do i = nalloc, 1, -1 {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ if (nopenpix < MAX_OPENPIX) {
+ if (XT_CLOSEFD(xt1) == NO)
+ next
+ XT_CLOSEFD(xt1) = NO
+ call imseti (im, IM_CLOSEFD, NO)
+ nopenpix = nopenpix + 1
+ }
+ }
+ last_flag = flag
+ }
+
+ # Use IMIO for already opened images.
+ im = XT_IM(xt)
+ if (im != NULL) {
+ XT_FLAG(xt) = flag
+ return (imgnld (im, buf, v))
+ }
+
+ # If the image is not currently mapped use the stored header.
+ im = XT_HDR(xt)
+
+ # Check for EOF.
+ i = IM_NDIM(im)
+ if (v[i] > IM_LEN(im,i))
+ return (EOF)
+
+ # Check for buffered data.
+ if (XT_BUF(xt) != NULL) {
+ if (v[2] >= XT_VS(xt,2) && v[2] <= XT_VE(xt,2)) {
+ if (XT_BTYPE(xt) != TY_DOUBLE)
+ call error (1, "Cannot mix data types")
+ nc = IM_LEN(im,1)
+ buf = XT_BUF(xt) + (v[2]-XT_VS(xt,2)) * IM_LEN(im,1)
+ XT_FLAG(xt) = flag
+ if (i == 1)
+ v[1] = nc + 1
+ else
+ j = imloop (v, unit_v, IM_LEN(im,1), unit_v, i)
+ return (nc)
+ }
+ }
+
+ # Handle more images than the maximum that can be open at one time.
+ if (nopen >= max_openim) {
+ if (option == XT_MAPUNMAP || v[2] == 0) {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+
+ # Buffer some number of lines.
+ nl = XT_BUFSIZE(xt1) / sizeof (TY_DOUBLE) / IM_LEN(im,1)
+ if (nl > 1) {
+ nc = IM_LEN(im,1)
+ call amovl (v, XT_VS(xt1,1), IM_MAXDIM)
+ call amovl (v, XT_VE(xt1,1), IM_MAXDIM)
+ XT_VS(xt1,1) = 1
+ XT_VE(xt1,1) = nc
+ XT_VE(xt1,2) = min (XT_VS(xt1,2)+(nl-1), IM_LEN(im,2))
+ nl = XT_VE(xt1,2) - XT_VS(xt1,2) + 1
+ XT_BTYPE(xt1) = TY_DOUBLE
+ call malloc (XT_BUF(xt1), nl*nc, XT_BTYPE(xt1))
+ ptr = imggsd (im, XT_VS(xt1,1), XT_VE(xt1,1),
+ IM_NDIM(im))
+ call amovd (Memd[ptr], Memd[XT_BUF(xt1)], nl*nc)
+ }
+
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ min_open = i + 1
+ break
+ }
+ if (index <= min_open)
+ min_open = index
+ else {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ if (XT_IM(xt1) == NULL)
+ next
+ min_open = i
+ break
+ }
+ }
+ } else {
+ # Check here because we can't catch error in immap.
+ i = open ("dev$null", READ_ONLY, BINARY_FILE)
+ call close (i)
+ if (i == LAST_FD - 1)
+ call error (SYS_FTOOMANYFILES, "Too many open files")
+ }
+ }
+
+ # Open image.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl immap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ im = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt))
+ XT_IM(xt) = im
+ call imseti (im, IM_BUFSIZE, XT_BUFSIZE(xt))
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+ nopen = nopen + 1
+ XT_CLOSEFD(xt) = YES
+ if (nopenpix < MAX_OPENPIX) {
+ XT_CLOSEFD(xt) = NO
+ nopenpix = nopenpix + 1
+ }
+ if (XT_CLOSEFD(xt) == YES)
+ call imseti (im, IM_CLOSEFD, YES)
+ XT_FLAG(xt) = flag
+
+ return (imgnld (im, buf, v))
+end
+
diff --git a/pkg/images/immatch/src/imcombine/src/icaclip.gx b/pkg/images/immatch/src/imcombine/src/icaclip.gx
new file mode 100644
index 00000000..de3b04d6
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icaclip.gx
@@ -0,0 +1,575 @@
+# 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 = max (0, n[1])
+ s = 0.
+ n2 = 0
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 = max (0, 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 (max (0, 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, sig, r, s, s1, one
+data one /1.0/
+$else
+PIXEL med, low, high, sig, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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)
+ sig = sqrt (s / (n2 - 1))
+ else {
+ call sfree (sp)
+ return
+ }
+
+ # Compute individual sigmas and iteratively clip.
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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) && sig > 0.) {
+ if (doscale1) {
+ for (; nl <= nh; nl = nl + 1) {
+ l = Memi[m[nl]+k]
+ s1 = sig * 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 = sig * 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 = sig * sqrt (max (one, med))
+ for (; nl <= nh; 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/icaverage.gx b/pkg/images/immatch/src/imcombine/src/icaverage.gx
new file mode 100644
index 00000000..a474bb9d
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icaverage.gx
@@ -0,0 +1,120 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+include "../icmask.h"
+
+$for (sird)
+# IC_AVERAGE -- Compute the average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_average$t (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+$if (datatype == sil)
+real average[npts] # Average (returned)
+$else
+PIXEL average[npts] # Average (returned)
+$endif
+
+int i, j, k, n1
+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/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ 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]
+ if (doaverage == YES)
+ average[i] = sum / n[i]
+ else
+ average[i] = sum
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ wt = wts[Memi[m[1]+k]]
+ sum = Mem$t[d[1]+k] * wt
+ sumwt = wt
+ do j = 2, n1 {
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + Mem$t[d[j]+k] * wt
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sum / sumwt
+ else {
+ sum = Mem$t[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mem$t[d[j]+k]
+ average[i] = sum / n1
+ }
+ } else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ sum = Mem$t[d[1]+k]
+ do j = 2, n1
+ sum = sum + Mem$t[d[j]+k]
+ if (doaverage == YES)
+ average[i] = sum / n1
+ else
+ average[i] = sum
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+$endfor
diff --git a/pkg/images/immatch/src/imcombine/src/iccclip.gx b/pkg/images/immatch/src/imcombine/src/iccclip.gx
new file mode 100644
index 00000000..5b1b724e
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/icemask.x b/pkg/images/immatch/src/imcombine/src/icemask.x
new file mode 100644
index 00000000..e29edd5e
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icemask.x
@@ -0,0 +1,115 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+
+
+# IC_EMASK -- Create exposure mask.
+
+procedure ic_emask (pm, v, id, nimages, n, wts, npts)
+
+pointer pm #I Pixel mask
+long v[ARB] #I Output vector
+pointer id[nimages] #I Image id pointers
+int nimages #I Number of images
+int n[npts] #I Number of good pixels
+real wts[npts] #I Weights
+int npts #I Number of output pixels per line
+
+int i, j, k, impnli()
+real exp
+pointer buf
+errchk impnli
+
+pointer exps # Exposure times
+pointer ev # IMIO coordinate vector
+real ezero # Integer to real zero
+real escale # Integer to real scale
+int einit # Initialization flag
+common /emask/ exps, ev, ezero, escale, einit
+
+begin
+ # Write scaling factors to the header.
+ if (einit == NO) {
+ if (ezero != 0. || escale != 1.) {
+ call imaddr (pm, "MASKZERO", ezero)
+ call imaddr (pm, "MASKSCAL", escale)
+ }
+ einit = YES
+ }
+
+ call amovl (v, Meml[ev], IM_MAXDIM)
+ i = impnli (pm, buf, Meml[ev])
+ call aclri (Memi[buf], npts)
+ do i = 1, npts {
+ exp = 0.
+ do j = 1, n[i] {
+ k = Memi[id[j]+i-1]
+ if (wts[k] > 0.)
+ exp = exp + Memr[exps+k-1]
+ }
+ Memi[buf] = nint((exp-ezero)/escale)
+ buf = buf + 1
+ }
+end
+
+
+# IC_EINIT -- Initialize exposure mask.
+
+procedure ic_einit (in, nimages, key, default, maxval)
+
+int in[nimages] #I Image pointers
+int nimages #I Number of images
+char key[ARB] #I Exposure time keyword
+real default #I Default exposure time
+int maxval #I Maximum mask value
+
+int i
+real exp, emin, emax, efrac, imgetr()
+
+pointer exps # Exposure times
+pointer ev # IMIO coordinate vector
+real ezero # Integer to real zero
+real escale # Integer to real scale
+int einit # Initialization flag
+common /emask/ exps, ev, ezero, escale, einit
+
+begin
+ call malloc (ev, IM_MAXDIM, TY_LONG)
+ call malloc (exps, nimages, TY_REAL)
+
+ emax = 0.
+ emin = MAX_REAL
+ efrac = 0
+ do i = 1, nimages {
+ iferr (exp = imgetr (in[i], key))
+ exp = default
+ exp = max (0., exp)
+ emax = emax + exp
+ if (exp > 0.)
+ emin = min (exp, emin)
+ efrac = max (abs(exp-nint(exp)), efrac)
+ Memr[exps+i-1] = exp
+ }
+
+ # Set scaling.
+ ezero = 0.
+ escale = 1.
+ if (emin < 1.) {
+ escale = emin
+ emin = emin / escale
+ emax = emax / escale
+ } else if (emin == MAX_REAL)
+ emin = 0.
+ if (efrac > 0.001 && emax-emin < 1000.) {
+ escale = escale / 1000.
+ emin = emin * 1000.
+ emax = emax * 1000.
+ }
+ while (emax > maxval) {
+ escale = escale * 10.
+ emin = emin / 10.
+ emax = emax / 10.
+ }
+ einit = NO
+end
diff --git a/pkg/images/immatch/src/imcombine/src/icgdata.gx b/pkg/images/immatch/src/imcombine/src/icgdata.gx
new file mode 100644
index 00000000..a05f5646
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icgdata.gx
@@ -0,0 +1,396 @@
+# 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[ARB] # 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
+
+PIXEL temp
+int i, j, k, l, n1, n2, npix, nin, nout, ndim, nused, mtype, xt_imgnl$t()
+real a, b
+pointer buf, dp, ip, mp
+errchk xt_cpix, xt_imgnl$t
+
+PIXEL max_pixel
+$if (datatype == s)
+data max_pixel/MAX_SHORT/
+$else $if (datatype == i)
+data max_pixel/MAX_INT/
+$else $if (datatype == r)
+data max_pixel/MAX_REAL/
+$else
+data max_pixel/MAX_DOUBLE/
+$endif $endif $endif
+
+include "../icombine.com"
+
+begin
+ # Get masks and return if there is no data
+ call ic_mget (in, out, offsets, v1, v2, m, lflag, nimages, mtype)
+ if (dflag == D_NONE) {
+ call aclri (n, npts)
+ return
+ }
+
+ # Close images which are not needed.
+ nout = IM_LEN(out[1],1)
+ ndim = IM_NDIM(out[1])
+ if (!project && ndim < 3) {
+ do i = 1, nimages {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1)
+ call xt_cpix (i)
+ if (ndim > 1) {
+ j = v1[2] - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+ }
+ }
+
+ # Get data and fill data buffers. Correct for offsets if needed.
+ 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 = xt_imgnl$t (in[i], i, d[i], v2, v1[2])
+ } else {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1) {
+ lflag[i] = D_NONE
+ next
+ }
+ k = 1 + j - offsets[i,1]
+ v2[1] = k
+ do l = 2, ndim {
+ v2[l] = v1[l] - offsets[i,l]
+ if (v2[l] < 1 || v2[l] > IM_LEN(in[i],l)) {
+ lflag[i] = D_NONE
+ break
+ }
+ }
+ if (lflag[i] == D_NONE)
+ next
+ if (project)
+ v2[ndim+1] = i
+ l = xt_imgnl$t (in[i], i, buf, v2, v1[2])
+ call amov$t (Mem$t[buf+k-1], Mem$t[dbuf[i]+j], npix)
+ d[i] = dbuf[i]
+ }
+ }
+
+ # Set values to max_pixel if needed.
+ if (mtype == M_NOVAL) {
+ do i = 1, nimages {
+ dp = d[i]; mp = m[i]
+ if (lflag[i] == D_NONE || dp == NULL)
+ next
+ else if (lflag[i] == D_MIX) {
+ do j = 1, npts {
+ if (Memi[mp] == 1)
+ Mem$t[dp] = max_pixel
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Apply threshold if needed
+ if (dothresh) {
+ do i = 1, nimages {
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ a = Mem$t[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+
+ lflag[i] = D_MIX
+ dflag = D_MIX
+ }
+ dp = dp + 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
+ }
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1) {
+ a = Mem$t[dp]
+ if (a < lthresh || a > hthresh) {
+ if (mtype == M_NOVAL)
+ Memi[m[i]+j-1] = 2
+ else
+ Memi[m[i]+j-1] = 1
+ dflag = D_MIX
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+
+ # Check for completely empty lines
+ lflag[i] = D_NONE
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ 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 {
+ a = scales[i]
+ b = -zeros[i]
+ if (lflag[i] == D_ALL) {
+ dp = d[i]
+ do j = 1, npts {
+ Mem$t[dp] = Mem$t[dp] / a + b
+ dp = dp + 1
+ }
+ } else if (lflag[i] == D_MIX) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] != 1)
+ 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
+ }
+ }
+ do i = nused+1, nimages
+ d[i] = NULL
+ 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]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ ip = id[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ Memi[ip] = l
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Mem$t[d[k]+j-1]
+ Mem$t[d[k]+j-1] = Mem$t[dp]
+ Mem$t[dp] = temp
+ Memi[ip] = Memi[id[k]+j-1]
+ Memi[id[k]+j-1] = l
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ } else
+ Memi[ip] = 0
+ 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 {
+ l = lflag[i]
+ nin = IM_LEN(in[l],1)
+ j = max (0, offsets[l,1])
+ k = min (nout, nin + offsets[l,1])
+ npix = k - j
+ n1 = 1 + j
+ n2 = n1 + npix - 1
+ dp = d[i] + n1 - 1
+ mp = m[i] + n1 - 1
+ do j = n1, n2 {
+ if (Memi[mp] == 0) {
+ n[j] = n[j] + 1
+ k = n[j]
+ if (k < i) {
+ temp = Mem$t[d[k]+j-1]
+ Mem$t[d[k]+j-1] = Mem$t[dp]
+ Mem$t[dp] = temp
+ Memi[mp] = Memi[m[k]+j-1]
+ Memi[m[k]+j-1] = 0
+ }
+ }
+ dp = dp + 1
+ mp = mp + 1
+ }
+ }
+ }
+ }
+
+ # Sort the pixels and IDs if needed
+ if (mclip) {
+ call malloc (dp, nused, TY_PIXEL)
+ if (keepids) {
+ call malloc (ip, nused, 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)
+ }
+
+ # If no good pixels set the number of usable values as -n and
+ # shift them to lower values.
+ if (mtype == M_NOVAL) {
+ if (keepids) {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ ip = id[i] + j - 1
+ if (Mem$t[dp] < max_pixel) {
+ 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] = Memi[ip]
+ }
+ }
+ }
+ }
+ } else {
+ do j = 1, npts {
+ if (n[j] > 0)
+ next
+ n[j] = 0
+ do i = 1, nused {
+ dp = d[i] + j - 1
+ if (Mem$t[dp] < max_pixel) {
+ n[j] = n[j] - 1
+ k = -n[j]
+ if (k < i)
+ Mem$t[d[k]+j-1] = Mem$t[dp]
+ }
+ }
+ }
+ }
+ }
+end
+$endfor
diff --git a/pkg/images/immatch/src/imcombine/src/icgrow.gx b/pkg/images/immatch/src/imcombine/src/icgrow.gx
new file mode 100644
index 00000000..caf7dd29
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icgrow.gx
@@ -0,0 +1,135 @@
+# 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, ncompress, 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)
+ ncompress = 0
+ }
+ 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)
+ if (l > 0) {
+ v[2] = line + l
+ if (v[2] <= nl)
+ call pmplpi (pm, v, buf[1,i], 1, npts, rop)
+ }
+ }
+ }
+ v[2] = line
+
+ if (ncompress > 10) {
+ do i = 1, nimages {
+ pm = Memi[pms+i-1]
+ call pm_compress (pm)
+ }
+ ncompress = 0
+ } else
+ ncompress = ncompress + 1
+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/images/immatch/src/imcombine/src/icgscale.x b/pkg/images/immatch/src/imcombine/src/icgscale.x
new file mode 100644
index 00000000..570697ad
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icgscale.x
@@ -0,0 +1,88 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "icombine.h"
+
+
+# IC_GSCALE -- Get scale values as directed by CL parameter.
+# Only those values which are INDEF are changed.
+# 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
+ do i = 1, nimages
+ if (IS_INDEFR(values[i]))
+ break
+ if (i <= nimages) {
+ 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
+ if (IS_INDEFR(values[i]))
+ 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 {
+ if (IS_INDEFR(values[i]))
+ 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
+ if (IS_INDEFR(values[i]))
+ values[i] = max (0.001, exptime[i])
+ }
+
+ return (type)
+end
diff --git a/pkg/images/immatch/src/imcombine/src/ichdr.x b/pkg/images/immatch/src/imcombine/src/ichdr.x
new file mode 100644
index 00000000..b4d925c1
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/ichdr.x
@@ -0,0 +1,72 @@
+include <imset.h>
+
+
+# IC_HDR -- Set output header.
+
+procedure ic_hdr (in, out, nimages)
+
+pointer in[nimages] #I Input images
+pointer out[ARB] #I Output images
+int nimages #I Number of images
+
+int i, j, imgnfn(), nowhite(), strldxs()
+pointer sp, inkey, key, str, list, imofnlu()
+bool streq()
+
+begin
+ call smark (sp)
+ call salloc (inkey, SZ_FNAME, TY_CHAR)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ call clgstr ("imcmb", Memc[inkey], SZ_FNAME)
+ i = nowhite (Memc[inkey], Memc[inkey], SZ_FNAME)
+
+ if (i > 0 && streq (Memc[inkey], "$I")) {
+ # Set new PROCID.
+ call xt_procid (out)
+
+ # Set input PROCIDs.
+ if (nimages < 100) {
+ list = imofnlu (out, "PROCID[0-9][0-9]")
+ while (imgnfn (list, Memc[key], SZ_LINE) != EOF)
+ call imdelf (out, Memc[key])
+ call imcfnl (list)
+ do i = 1, nimages {
+ call sprintf (Memc[key], 8, "PROCID%02d")
+ call pargi (i)
+ iferr (call imgstr (in[i], "PROCID", Memc[str], SZ_LINE)) {
+ iferr (call imgstr (in[i], "OBSID", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ }
+ if (Memc[str] != EOS)
+ call imastr (out, Memc[key], Memc[str])
+ }
+ }
+ }
+
+ if (i > 0 && nimages < 1000) {
+ list = imofnlu (out, "IMCMB[0-9][0-9][0-9]")
+ while (imgnfn (list, Memc[key], SZ_LINE) != EOF)
+ call imdelf (out, Memc[key])
+ call imcfnl (list)
+ do i = 1, nimages {
+ if (streq (Memc[inkey], "$I")) {
+ call imstats (in[i], IM_IMAGENAME, Memc[str], SZ_LINE)
+ j = strldxs ("/$", Memc[str])
+ if (j > 0)
+ call strcpy (Memc[str+j], Memc[str], SZ_LINE)
+ } else {
+ iferr (call imgstr (in[i], Memc[inkey], Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ }
+ if (Memc[str] == EOS)
+ next
+ call sprintf (Memc[key], SZ_LINE, "IMCMB%03d")
+ call pargi (i)
+ call imastr (out, Memc[key], Memc[str])
+ }
+ }
+
+ call sfree (sp)
+end
diff --git a/pkg/images/immatch/src/imcombine/src/icimstack.x b/pkg/images/immatch/src/imcombine/src/icimstack.x
new file mode 100644
index 00000000..d5628694
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icimstack.x
@@ -0,0 +1,186 @@
+# 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, mask)
+
+int list #I List of images
+char output[ARB] #I Name of output image
+char mask[ARB] #I Name of output mask
+
+int i, j, npix
+long line_in[IM_MAXDIM], line_out[IM_MAXDIM], line_outbpm[IM_MAXDIM]
+pointer sp, input, bpmname, key, in, out, inbpm, outbpm, buf_in, buf_out, ptr
+
+int imtgetim(), imtlen(), errget()
+int imgnls(), imgnli(), imgnll(), imgnlr(), imgnld(), imgnlx()
+int impnls(), impnli(), impnll(), impnlr(), impnld(), impnlx()
+pointer immap(), pm_newmask()
+errchk immap
+errchk imgnls, imgnli, imgnll, imgnlr, imgnld, imgnlx
+errchk impnls, impnli, impnll, impnlr, impnld, impnlx
+
+begin
+ call smark (sp)
+ call salloc (input, SZ_FNAME, TY_CHAR)
+ call salloc (bpmname, SZ_FNAME, TY_CHAR)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+
+ iferr {
+ # Add each input image to the output image.
+ out = NULL; outbpm = NULL
+ i = 0
+ while (imtgetim (list, Memc[input], SZ_FNAME) != EOF) {
+
+ i = i + 1
+ in = NULL; inbpm = 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)
+
+ if (mask[1] != EOS) {
+ ptr = immap (mask, NEW_COPY, in)
+ outbpm = ptr
+ IM_NDIM(outbpm) = IM_NDIM(outbpm) + 1
+ IM_LEN(outbpm, IM_NDIM(outbpm)) = imtlen (list)
+ call amovkl (long(1), line_outbpm, 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)
+ }
+ }
+
+ # Copy mask.
+ if (mask[1] != EOS) {
+ iferr (call imgstr (in, "bpm", Memc[bpmname], SZ_FNAME)) {
+ Memc[bpmname] = EOS
+ ptr = pm_newmask (in, 27)
+ } else
+ ptr = immap (Memc[bpmname], READ_ONLY, 0)
+ inbpm = ptr
+
+ if (IM_NDIM(inbpm) != IM_NDIM(outbpm) - 1)
+ call error (0, "Input images not consistent")
+ do j = 1, IM_NDIM(inbpm) {
+ if (IM_LEN(inbpm, j) != IM_LEN(outbpm, j))
+ call error (0, "Masks not consistent")
+ }
+
+ call amovkl (long(1), line_in, IM_MAXDIM)
+ while (imgnli (inbpm, buf_in, line_in) != EOF) {
+ if (impnli (outbpm, buf_out, line_outbpm) == EOF)
+ call error (0, "Error writing output mask")
+ call amovi (Memi[buf_in], Memi[buf_out], npix)
+ }
+
+ call sprintf (Memc[key], SZ_FNAME, "bpm%04d")
+ call pargi (i)
+ call imastr (out, Memc[key], Memc[bpmname])
+
+ call imunmap (inbpm)
+ }
+
+ call imunmap (in)
+ }
+ } then {
+ i = errget (Memc[key], SZ_FNAME)
+ call erract (EA_WARN)
+ if (outbpm != NULL) {
+ call imunmap (outbpm)
+ iferr (call imdelete (mask))
+ ;
+ }
+ if (out != NULL) {
+ call imunmap (out)
+ iferr (call imdelete (output))
+ ;
+ }
+ if (inbpm != NULL)
+ call imunmap (inbpm)
+ if (in != NULL)
+ call imunmap (in)
+ call sfree (sp)
+ call error (i, "Can't make temporary stack images")
+ }
+
+ # Finish up.
+ if (outbpm != NULL) {
+ call imunmap (outbpm)
+ call imastr (out, "bpm", mask)
+ }
+ call imunmap (out)
+ call sfree (sp)
+end
diff --git a/pkg/images/immatch/src/imcombine/src/iclog.x b/pkg/images/immatch/src/imcombine/src/iclog.x
new file mode 100644
index 00000000..53420cd5
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/iclog.x
@@ -0,0 +1,431 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <imset.h>
+include <mach.h>
+include "icombine.h"
+include "icmask.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)
+
+pointer in[nimages] # Input images
+pointer out[ARB] # 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
+
+int i, j, stack, ctor()
+real rval, imgetr()
+long clktime()
+bool prncombine, prexptime, prmode, prmedian, prmean, prmask
+bool prrdn, prgain, prsn
+pointer sp, fname, bpname, key
+errchk imgetr
+
+include "icombine.com"
+
+begin
+ if (logfd == NULL)
+ return
+
+ call smark (sp)
+ call salloc (fname, SZ_LINE, TY_CHAR)
+ call salloc (bpname, 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, ")
+ case SUM:
+ call fprintf (logfd, " combine = sum, ")
+ }
+ call fprintf (logfd, "scale = %s, zero = %s, weight = %s\n")
+ call pargstr (sname)
+ call pargstr (zname)
+ call pargstr (wname)
+ if (combine == NMODEL && reject!=CCDCLIP && reject!=CRREJECT) {
+ call fprintf (logfd,
+ " rdnoise = %s, gain = %s, snoise = %s\n")
+ call pargstr (Memc[rdnoise])
+ call pargstr (Memc[gain])
+ call pargstr (Memc[snoise])
+ }
+
+ 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)
+ if (Memc[statsec] != EOS) {
+ call fprintf (logfd, " statsec = %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ if (ICM_TYPE(icm) != M_NONE) {
+ switch (ICM_TYPE(icm)) {
+ case M_BOOLEAN, M_GOODVAL:
+ call fprintf (logfd, " masktype = goodval, maskval = %d\n")
+ call pargi (ICM_VALUE(icm))
+ case M_BADVAL:
+ call fprintf (logfd, " masktype = badval, maskval = %d\n")
+ call pargi (ICM_VALUE(icm))
+ case M_NOVAL:
+ call fprintf (logfd, " masktype = noval, maskval = %d\n")
+ call pargi (ICM_VALUE(icm))
+ case M_GOODBITS:
+ call fprintf (logfd, " masktype = goodbits, maskval = %d\n")
+ call pargi (ICM_VALUE(icm))
+ case M_BADBITS:
+ call fprintf (logfd, " masktype = badbits, maskval = %d\n")
+ call pargi (ICM_VALUE(icm))
+ case M_LTVAL:
+ call fprintf (logfd, " masktype = goodval, maskval < %d\n")
+ call pargi (ICM_VALUE(icm))
+ case M_GTVAL:
+ call fprintf (logfd, " masktype = goodval, maskval > %d\n")
+ call pargi (ICM_VALUE(icm))
+ }
+ }
+
+ # 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 (ICM_TYPE(icm) != M_NONE) {
+ if (project)
+ bpname = Memi[ICM_NAMES(icm)]
+ else
+ bpname = Memi[ICM_NAMES(icm)+i-1]
+ if (Memc[bpname] != EOS)
+ prmask = true
+ }
+ if (combine == NMODEL || 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) {
+ if (stack == YES) {
+ call sprintf (Memc[key], SZ_FNAME, "bpm%04d")
+ call pargi (i)
+ ifnoerr (call imgstr (in[i], Memc[key], Memc[fname],
+ SZ_LINE)) {
+ call fprintf (logfd, " %s")
+ call pargstr (Memc[fname])
+ } else {
+ call fprintf (logfd, " %s")
+ call pargstr (Memc[bpname])
+ }
+ } else if (ICM_TYPE(icm) != M_NONE) {
+ if (project)
+ bpname = Memi[ICM_NAMES(icm)]
+ else
+ bpname = Memi[ICM_NAMES(icm)+i-1]
+ if (Memc[bpname] != EOS) {
+ call fprintf (logfd, " %s")
+ call pargstr (Memc[bpname])
+ }
+ }
+ }
+ 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)
+ call fprintf (logfd, "\n")
+
+ if (out[2] != NULL) {
+ call imstats (out[2], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " Bad pixel mask = %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ 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[5] != NULL) {
+ call imstats (out[5], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " Number rejected mask = %s\n")
+ call pargstr (Memc[fname])
+ }
+
+ if (out[6] != NULL) {
+ call imstats (out[6], IM_IMAGENAME, Memc[fname], SZ_LINE)
+ call fprintf (logfd, " Exposure mask = %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/images/immatch/src/imcombine/src/icmask.com b/pkg/images/immatch/src/imcombine/src/icmask.com
new file mode 100644
index 00000000..baba6f6a
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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/images/immatch/src/imcombine/src/icmask.h b/pkg/images/immatch/src/imcombine/src/icmask.h
new file mode 100644
index 00000000..ffb64aa9
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icmask.h
@@ -0,0 +1,12 @@
+# ICMASK -- Data structure for IMCOMBINE mask interface.
+
+define ICM_LEN 6 # Structure length
+define ICM_TYPE Memi[$1] # Mask type
+define ICM_VALUE Memi[$1+1] # Mask value
+define ICM_IOMODE Memi[$1+2] # I/O mode
+define ICM_BUFS Memi[$1+3] # Pointer to data line buffers
+define ICM_PMS Memi[$1+4] # Pointer to array of PMIO pointers
+define ICM_NAMES Memi[$1+5] # Pointer to array of mask names
+
+define ICM_OPEN 0 # Keep masks open
+define ICM_CLOSED 1 # Keep masks closed
diff --git a/pkg/images/immatch/src/imcombine/src/icmask.x b/pkg/images/immatch/src/imcombine/src/icmask.x
new file mode 100644
index 00000000..ca9c1d02
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icmask.x
@@ -0,0 +1,685 @@
+include <imhdr.h>
+include <imset.h>
+include <pmset.h>
+include "icombine.h"
+include "icmask.h"
+
+# IC_MASK -- ICOMBINE mask interface
+#
+# IC_MOPEN -- Initialize mask interface
+# 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_MCLOSE1-- Close a mask for the specified image index
+
+
+# IC_MOPEN -- Initialize mask interface.
+
+procedure ic_mopen (in, out, nimages, offsets, iomode)
+
+pointer in[nimages] #I Input images
+pointer out[ARB] #I Output images
+int nimages #I Number of images
+int offsets[nimages,ARB] #I Offsets to output image
+int iomode #I I/O mode
+
+int mtype # Mask type
+int mvalue # Mask value
+pointer bufs # Pointer to data line buffers
+pointer pms # Pointer to array of PMIO pointers
+pointer names # Pointer to array of string pointers
+
+int i, j, k, nin, nout, npix, npms, nscan(), strdic(), ctor()
+real rval
+pointer sp, str, key, fname, title, image, pm, pm_open()
+bool invert, pm_empty()
+errchk calloc, pm_open, ic_pmload
+
+include "icombine.com"
+
+begin
+ icm = NULL
+ if (IM_NDIM(out[1]) == 0)
+ return
+
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (title, SZ_FNAME, TY_CHAR)
+ call salloc (image, 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 = M_NONE
+ call clgstr ("masktype", Memc[str], SZ_LINE)
+ call sscan (Memc[str])
+ call gargwrd (Memc[title], SZ_FNAME)
+ call gargwrd (Memc[key], SZ_FNAME)
+ i = nscan()
+ if (i > 0) {
+ if (Memc[title] == '!') {
+ if (i == 1)
+ mtype = M_GOODVAL
+ else
+ mtype = strdic (Memc[key], Memc[key], SZ_FNAME, MASKTYPES)
+ call strcpy (Memc[title+1], Memc[key], SZ_FNAME)
+ } else {
+ mtype = strdic (Memc[title], Memc[title], SZ_FNAME, MASKTYPES)
+ call strcpy ("BPM", Memc[key], SZ_FNAME)
+ }
+ if (mtype == 0) {
+ call sprintf (Memc[title], SZ_FNAME,
+ "Invalid or ambiguous masktype (%s)")
+ call pargstr (Memc[str])
+ call error (1, Memc[title])
+ }
+ }
+ npix = IM_LEN(out[1],1)
+ call calloc (pms, nimages, TY_POINTER)
+ call calloc (bufs, nimages, TY_POINTER)
+ call calloc (names, 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.
+
+ # Eventually we want to allow general expressions. For now we only
+ # allow a special '<' or '>' operator.
+
+ call clgstr ("maskvalue", Memc[title], SZ_FNAME)
+ i = 1
+ if (Memc[title] == '<') {
+ mtype = M_LTVAL
+ i = i + 1
+ } else if (Memc[title] == '>') {
+ mtype = M_GTVAL
+ i = i + 1
+ }
+ if (ctor (Memc[title], i, rval) == 0)
+ call error (1, "Bad mask value")
+ mvalue = rval
+ if (mvalue < 0)
+ call error (1, "Bad mask value")
+ else if (mvalue == 0 && mtype == M_NOVAL)
+ call error (1, "maskvalue cannot be 0 for masktype of 'novalue'")
+
+ if (mtype == 0)
+ mtype = M_NONE
+ else if (mtype == M_BADBITS && mvalue == 0)
+ mtype = M_NONE
+ else if (mvalue == 0 && (mtype == M_GOODVAL || mtype == M_GOODBITS))
+ mtype = M_BOOLEAN
+ else 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.
+
+ nout = IM_LEN(out[1],1)
+ npms = 0
+ do i = 1, nimages {
+ if (mtype != M_NONE) {
+ call malloc (Memi[names+i-1], SZ_FNAME, TY_CHAR)
+ fname = Memi[names+i-1]
+ ifnoerr (call imgstr (in[i],Memc[key],Memc[fname],SZ_FNAME)) {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+ if (npix < 1)
+ Memc[fname] = EOS
+ else {
+ pm = pm_open (NULL)
+ call ic_pmload (in[i], pm, Memc[fname], SZ_FNAME)
+ call pm_seti (pm, P_REFIM, in[i])
+ if (pm_empty (pm) && !invert)
+ Memc[fname] = EOS
+ else {
+ if (project)
+ npms = nimages
+ else
+ npms = npms + 1
+ }
+ call pm_close (pm)
+ }
+ if (project)
+ break
+ } else
+ Memc[fname] = EOS
+ }
+ }
+
+ # 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
+ }
+
+ # Set up mask structure.
+ call calloc (icm, ICM_LEN, TY_STRUCT)
+ ICM_TYPE(icm) = mtype
+ ICM_VALUE(icm) = mvalue
+ ICM_IOMODE(icm) = iomode
+ ICM_BUFS(icm) = bufs
+ ICM_PMS(icm) = pms
+ ICM_NAMES(icm) = names
+
+ call sfree (sp)
+end
+
+
+# IC_PMLOAD -- Find and load a mask.
+# This is more complicated because we want to allow a mask name specified
+# without a path to be found either in the current directory or in the
+# directory of the image.
+
+procedure ic_pmload (im, pm, fname, maxchar)
+
+pointer im #I Image pointer to be associated with mask
+pointer pm #O Mask pointer to be returned
+char fname[ARB] #U Mask name
+int maxchar #I Max size of mask name
+
+bool match
+pointer sp, str, imname, yt_pmload()
+int i, fnldir(), stridxs(), envfind()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_PATHNAME, TY_CHAR)
+
+ # First check if the specified file can be loaded.
+ match = (envfind ("pmatch", Memc[str], SZ_PATHNAME) > 0)
+ if (match) {
+ call pm_close (pm)
+ iferr (pm = yt_pmload (fname,im,"logical",Memc[str],SZ_PATHNAME))
+ pm = NULL
+ if (pm != NULL)
+ return
+ } else {
+ ifnoerr (call pm_loadf (pm, fname, Memc[str], SZ_PATHNAME))
+ return
+ ifnoerr (call pm_loadim (pm, fname, Memc[str], SZ_PATHNAME))
+ return
+ }
+
+ # Check if the file has a path in which case we return an error.
+ # Must deal with possible [] which is a VMS directory delimiter.
+ call strcpy (fname, Memc[str], SZ_PATHNAME)
+ i = stridxs ("[", Memc[str])
+ if (i > 0)
+ Memc[str+i-1] = EOS
+ if (fnldir (Memc[str], Memc[str], SZ_PATHNAME) > 0) {
+ call sprintf (Memc[str], SZ_PATHNAME,
+ "Bad pixel mask not found (%s)")
+ call pargstr (fname)
+ call error (1, Memc[str])
+ }
+
+ # Check if the image has a path. If not return an error.
+ call salloc (imname, SZ_PATHNAME, TY_CHAR)
+ call imstats (im, IM_IMAGENAME, Memc[imname], SZ_PATHNAME)
+ if (fnldir (Memc[imname], Memc[str], SZ_PATHNAME) == 0) {
+ call sprintf (Memc[str], SZ_PATHNAME,
+ "Bad pixel mask not found (%s)")
+ call pargstr (fname)
+ call error (1, Memc[str])
+ }
+
+ # Try using the image path for the mask file.
+ call strcat (fname, Memc[str], SZ_PATHNAME)
+ if (match) {
+ iferr (pm = yt_pmload (Memc[imname], im, "logical",
+ Memc[str], SZ_PATHNAME))
+ pm = NULL
+ if (pm != NULL) {
+ call strcpy (Memc[str], fname, maxchar)
+ return
+ }
+ } else {
+ ifnoerr (call pm_loadf (pm, Memc[str], Memc[imname], SZ_PATHNAME)) {
+ call strcpy (Memc[str], fname, maxchar)
+ return
+ }
+ }
+
+ # No mask found.
+ call sprintf (Memc[str], SZ_PATHNAME,
+ "Bad pixel mask not found (%s)")
+ call pargstr (fname)
+ call error (1, Memc[str])
+
+ # This will not be reached and we let the calling program free
+ # the stack. We include smark/sfree for lint detectors.
+ call sfree (sp)
+end
+
+
+
+# IC_MCLOSE -- Close the mask interface.
+
+procedure ic_mclose (nimages)
+
+int nimages # Number of images
+
+int i
+include "icombine.com"
+
+begin
+ if (icm == NULL)
+ return
+
+ do i = 1, nimages {
+ call mfree (Memi[ICM_NAMES(icm)+i-1], TY_CHAR)
+ call mfree (Memi[ICM_BUFS(icm)+i-1], TY_INT)
+ }
+ do i = 1, nimages {
+ if (Memi[ICM_PMS(icm)+i-1] != NULL)
+ call pm_close (Memi[ICM_PMS(icm)+i-1])
+ if (project)
+ break
+ }
+ call mfree (ICM_NAMES(icm), TY_POINTER)
+ call mfree (ICM_BUFS(icm), TY_POINTER)
+ call mfree (ICM_PMS(icm), TY_POINTER)
+ call mfree (icm, TY_STRUCT)
+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, mtype)
+
+pointer in[nimages] # Input image pointers
+pointer out[ARB] # 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 mtype # Mask type
+int mvalue # Mask value
+int iomode # I/O mode
+pointer bufs # Pointer to data line buffers
+pointer pms # Pointer to array of PMIO pointers
+
+char title[1]
+int i, j, k, l, ndim, nin, nout, npix, envfind()
+pointer buf, pm, names, fname, pm_open(), yt_pmload()
+bool match, pm_linenotempty()
+errchk pm_glpi, pm_open, pm_loadf, pm_loadim, yt_pmload
+
+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.
+
+ dflag = D_ALL
+ mtype = M_NONE
+ if (icm == NULL)
+ return
+ if (ICM_TYPE(icm) == M_NONE && aligned && !dothresh)
+ return
+
+ mtype = ICM_TYPE(icm)
+ mvalue = ICM_VALUE(icm)
+ iomode = ICM_IOMODE(icm)
+ bufs = ICM_BUFS(icm)
+ pms = ICM_PMS(icm)
+ names = ICM_NAMES(icm)
+ match = (envfind ("pmmatch", title, 1) > 0)
+
+ # 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 {
+ nin = IM_LEN(in[i],1)
+ j = max (0, offsets[i,1])
+ k = min (nout, nin + offsets[i,1])
+ npix = k - j
+
+ m[i] = Memi[bufs+i-1]
+ buf = Memi[bufs+i-1] + j
+ if (project) {
+ pm = Memi[pms]
+ fname = Memi[names]
+ } else {
+ pm = Memi[pms+i-1]
+ fname = Memi[names+i-1]
+ }
+
+ if (npix < 1)
+ lflag[i] = D_NONE
+ else if (npix == nout)
+ lflag[i] = D_ALL
+ else
+ lflag[i] = D_MIX
+
+ if (lflag[i] != D_NONE) {
+ v2[1] = 1 + j - offsets[i,1]
+ do l = 2, ndim {
+ v2[l] = v1[l] - offsets[i,l]
+ if (v2[l] < 1 || v2[l] > IM_LEN(in[i],l)) {
+ lflag[i] = D_NONE
+ break
+ }
+ }
+ }
+ if (project)
+ v2[ndim+1] = i
+
+ if (lflag[i] == D_NONE) {
+ if (pm != NULL && !project) {
+ call pm_close (pm)
+ Memi[pms+i-1] = NULL
+ }
+ call amovki (1, Memi[m[i]], nout)
+ next
+ } else if (lflag[i] == D_MIX) {
+ if (j > 0)
+ call amovki (1, Memi[m[i]], j)
+ if (nout-k > 0)
+ call amovki (1, Memi[m[i]+k], nout-k)
+ }
+
+ if (fname == NULL) {
+ call aclri (Memi[buf], npix)
+ next
+ } else if (Memc[fname] == EOS) {
+ call aclri (Memi[buf], npix)
+ next
+ }
+
+ # Do mask I/O and convert to appropriate values in order of
+ # expected usage.
+
+ if (pm == NULL) {
+ if (match) {
+ pm = yt_pmload (Memc[fname], in[i], "logical",
+ Memc[fname], SZ_FNAME)
+ } else {
+ pm = pm_open (NULL)
+ iferr (call pm_loadf (pm, Memc[fname], title, 1))
+ call pm_loadim (pm, Memc[fname], title, 1)
+ call pm_seti (pm, P_REFIM, in[i])
+ }
+ if (project)
+ Memi[pms] = pm
+ else
+ Memi[pms+i-1] = pm
+ }
+
+ 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_NOVAL) {
+ do j = 0, npix-1 {
+ if (Memi[buf+j] == 0)
+ next
+ if (Memi[buf+j] == mvalue)
+ Memi[buf+j] = 1
+ else
+ Memi[buf+j] = 2
+ }
+ } 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)
+ else if (mtype == M_LTVAL)
+ call abgeki (Memi[buf], mvalue, Memi[buf], npix)
+ else if (mtype == M_GTVAL)
+ call ableki (Memi[buf], mvalue, Memi[buf], npix)
+
+ lflag[i] = D_NONE
+ do j = 1, npix
+ if (Memi[buf+j-1] != 1) {
+ 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_NOVAL && mvalue != 0) ||
+ (mtype == M_GOODVAL && mvalue == 0)) {
+ call aclri (Memi[buf], npix)
+ } else if (mtype == M_LTVAL && mvalue > 0) {
+ call aclri (Memi[buf], npix)
+ } else {
+ call amovki (1, Memi[buf], npix)
+ lflag[i] = D_NONE
+ }
+ }
+
+ if (iomode == ICM_CLOSED)
+ call ic_mclose1 (i, nimages)
+ }
+
+ # 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, nimages, offset, v, m)
+
+pointer in # Input image pointer
+int image # Image index
+int nimages # Number of images
+int offset # Column offset
+long v[IM_MAXDIM] # Data vector desired
+pointer m # Pointer to mask
+
+int mtype # Mask type
+int mvalue # Mask value
+pointer bufs # Pointer to data line buffers
+pointer pms # Pointer to array of PMIO pointers
+
+char title[1]
+int i, npix, envfind()
+pointer buf, pm, names, fname, pm_open(), yt_pmload()
+bool pm_linenotempty()
+errchk pm_glpi, pm_open, pm_loadf, pm_loadim, yt_pmload
+
+include "icombine.com"
+
+begin
+ dflag = D_ALL
+ if (icm == NULL)
+ return
+ if (ICM_TYPE(icm) == M_NONE)
+ return
+
+ mtype = ICM_TYPE(icm)
+ mvalue = ICM_VALUE(icm)
+ bufs = ICM_BUFS(icm)
+ pms = ICM_PMS(icm)
+ names = ICM_NAMES(icm)
+
+ npix = IM_LEN(in,1)
+ m = Memi[bufs+image-1] + offset
+ if (project) {
+ pm = Memi[pms]
+ fname = Memi[names]
+ } else {
+ pm = Memi[pms+image-1]
+ fname = Memi[names+image-1]
+ }
+
+ if (fname == NULL)
+ return
+ if (Memc[fname] == EOS)
+ return
+
+ if (pm == NULL) {
+ if (envfind ("pmmatch", title, 1) > 0) {
+ pm = yt_pmload (Memc[fname], in, "logical", Memc[fname],
+ SZ_FNAME)
+ } else {
+ pm = pm_open (NULL)
+ iferr (call pm_loadf (pm, Memc[fname], title, 1))
+ call pm_loadim (pm, Memc[fname], title, 1)
+ call pm_seti (pm, P_REFIM, in)
+ }
+ if (project)
+ Memi[pms] = pm
+ else
+ Memi[pms+image-1] = pm
+ }
+
+ # 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_NOVAL) {
+ do i = 0, npix-1 {
+ if (Memi[buf+i] == 0)
+ next
+ if (Memi[buf+i] == mvalue)
+ Memi[buf+i] = 1
+ else
+ Memi[buf+i] = 2
+ }
+ } 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)
+ else if (mtype == M_LTVAL)
+ call abgeki (Memi[buf], mvalue, Memi[buf], npix)
+ else if (mtype == M_GTVAL)
+ call ableki (Memi[buf], mvalue, Memi[buf], npix)
+
+ dflag = D_NONE
+ do i = 1, npix
+ if (Memi[buf+i-1] != 1) {
+ dflag = D_MIX
+ break
+ }
+ } else {
+ if (mtype == M_BOOLEAN || mtype == M_BADBITS) {
+ ;
+ } else if ((mtype == M_BADVAL && mvalue != 0) ||
+ (mtype == M_NOVAL && mvalue != 0) ||
+ (mtype == M_GOODVAL && mvalue == 0)) {
+ ;
+ } else if (mtype == M_LTVAL && mvalue > 0) {
+ ;
+ } else
+ dflag = D_NONE
+ }
+end
+
+
+# IC_MCLOSE1 -- Close mask by index.
+
+procedure ic_mclose1 (image, nimages)
+
+int image # Image index
+int nimages # Number of images
+
+pointer pms, names, pm, fname
+include "icombine.com"
+
+begin
+ if (icm == NULL)
+ return
+
+ pms = ICM_PMS(icm)
+ names = ICM_NAMES(icm)
+
+ if (project) {
+ pm = Memi[pms]
+ fname = Memi[names]
+ } else {
+ pm = Memi[pms+image-1]
+ fname = Memi[names+image-1]
+ }
+
+ if (fname == NULL || pm == NULL)
+ return
+ if (Memc[fname] == EOS || pm == NULL)
+ return
+
+ call pm_close (pm)
+ if (project)
+ Memi[pms] = NULL
+ else
+ Memi[pms+image-1] = NULL
+end
+
+
+# YT_PMLOAD -- This is like yt_mappm except it returns the mask pointer.
+
+pointer procedure yt_pmload (pmname, refim, match, mname, sz_mname)
+
+char pmname[ARB] #I Pixel mask name
+pointer refim #I Reference image pointer
+char match[ARB] #I Match by physical coordinates?
+char mname[ARB] #O Expanded mask name
+int sz_mname #O Size of expanded mask name
+pointer pm #R Pixel mask pointer
+
+int imstati()
+pointer im, yt_mappm()
+errchk yt_mappm
+
+begin
+ im = yt_mappm (pmname, refim, match, mname, sz_mname)
+ if (im != NULL) {
+ pm = imstati (im, IM_PMDES)
+ call imseti (im, IM_PMDES, NULL)
+ call imunmap (im)
+ } else
+ pm = NULL
+ return (pm)
+end
diff --git a/pkg/images/immatch/src/imcombine/src/icmedian.gx b/pkg/images/immatch/src/imcombine/src/icmedian.gx
new file mode 100644
index 00000000..164140a1
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icmedian.gx
@@ -0,0 +1,246 @@
+# 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, j, k, j1, j2, n1, lo, up, lo1, up1
+bool even
+$if (datatype == silx)
+real val1, val2, val3
+$else
+PIXEL val1, val2, val3
+$endif
+PIXEL temp, wtemp
+$if (datatype == x)
+real abs_temp
+$endif
+
+include "../icombine.com"
+
+begin
+ # If no data return after possibly setting blank values.
+ if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ median[i]= blank
+ }
+ return
+ }
+
+ # If the data were previously sorted then directly compute the median.
+ if (mclip) {
+ if (dflag == D_ALL) {
+ n1 = n[1]
+ j1 = n1 / 2 + 1
+ j2 = n1 / 2
+ even = (mod(n1,2)==0 && (medtype==MEDAVG || 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]
+ }
+ return
+ } else {
+ # Check for negative n values. If found then there are
+ # pixels with no good values but with values we want to
+ # use as a substitute median. In this case ignore that
+ # the good pixels have been sorted.
+ do i = 1, npts {
+ if (n[i] < 0)
+ break
+ }
+
+ if (n[i] >= 0) {
+ do i = 1, npts {
+ k = i - 1
+ n1 = n[i]
+ if (n1 > 0) {
+ j1 = n1 / 2 + 1
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1>2)) {
+ 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
+ }
+ }
+ }
+
+ # Compute the median.
+ do i = 1, npts {
+ k = i - 1
+ n1 = abs(n[i])
+
+ # If there are more than 3 points use Wirth algorithm. This
+ # is the same as vops$amed.gx except for an even number of
+ # points it selects the middle two and averages.
+ if (n1 > 3) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2))
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Mem$t[d[j]+k]; lo1 = lo; up1 = up
+ $if (datatype == x)
+ abs_temp = abs (temp)
+ $endif
+
+ repeat {
+ $if (datatype == x)
+ while (abs (Mem$t[d[lo1]+k]) < abs_temp)
+ $else
+ while (Mem$t[d[lo1]+k] < temp)
+ $endif
+ lo1 = lo1 + 1
+ $if (datatype == x)
+ while (abs_temp < abs (Mem$t[d[up1]+k]))
+ $else
+ while (temp < Mem$t[d[up1]+k])
+ $endif
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Mem$t[d[lo1]+k]
+ Mem$t[d[lo1]+k] = Mem$t[d[up1]+k]
+ Mem$t[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+
+ median[i] = Mem$t[d[j]+k]
+
+ if (mod(n1,2)==0 && (medtype==MEDAVG || n1 > 2)) {
+ lo = 1
+ up = n1
+ j = max (lo, min (up, (up+1)/2)+1)
+
+ while (lo < up) {
+ if (! (lo < up))
+ break
+
+ temp = Mem$t[d[j]+k]; lo1 = lo; up1 = up
+ $if (datatype == x)
+ abs_temp = abs (temp)
+ $endif
+
+ repeat {
+ $if (datatype == x)
+ while (abs (Mem$t[d[lo1]+k]) < abs_temp)
+ $else
+ while (Mem$t[d[lo1]+k] < temp)
+ $endif
+ lo1 = lo1 + 1
+ $if (datatype == x)
+ while (abs_temp < abs (Mem$t[d[up1]+k]))
+ $else
+ while (temp < Mem$t[d[up1]+k])
+ $endif
+ up1 = up1 - 1
+ if (lo1 <= up1) {
+ wtemp = Mem$t[d[lo1]+k]
+ Mem$t[d[lo1]+k] = Mem$t[d[up1]+k]
+ Mem$t[d[up1]+k] = wtemp
+ lo1 = lo1 + 1; up1 = up1 - 1
+ }
+ } until (lo1 > up1)
+
+ if (up1 < j)
+ lo = lo1
+ if (j < lo1)
+ up = up1
+ }
+ median[i] = (median[i] + Mem$t[d[j]+k]) / 2
+ }
+
+ # If 3 points find the median directly.
+ } else 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
+
+ # If 2 points average.
+ } else if (n1 == 2) {
+ val1 = Mem$t[d[1]+k]
+ val2 = Mem$t[d[2]+k]
+ if (medtype == MEDAVG)
+ median[i] = (val1 + val2) / 2
+ else
+ median[i] = min (val1, val2)
+
+ # If 1 point return the value.
+ } else if (n1 == 1)
+ median[i] = Mem$t[d[1]+k]
+
+ # If no points return with a possibly blank value.
+ else if (doblank == YES)
+ median[i] = blank
+ }
+end
+$endfor
diff --git a/pkg/images/immatch/src/imcombine/src/icmm.gx b/pkg/images/immatch/src/imcombine/src/icmm.gx
new file mode 100644
index 00000000..860cb512
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icmm.gx
@@ -0,0 +1,189 @@
+# 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 = max (0, 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 = max (0, 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
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ } else {
+ Mem$t[kmax] = d1
+ k = Memi[m[jmax]+i1]
+ Memi[m[jmax]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ }
+ }
+ if (jmin < j) {
+ if (jmax != n1) {
+ Mem$t[kmin] = d1
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[n1]+i1]
+ Memi[m[n1]+i1] = k
+ } else {
+ Mem$t[kmin] = d2
+ k = Memi[m[jmin]+i1]
+ Memi[m[jmin]+i1] = Memi[m[j]+i1]
+ Memi[m[j]+i1] = k
+ }
+ }
+ } 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/images/immatch/src/imcombine/src/icnmodel.gx b/pkg/images/immatch/src/imcombine/src/icnmodel.gx
new file mode 100644
index 00000000..0e020dc9
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icnmodel.gx
@@ -0,0 +1,147 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+include "../icmask.h"
+
+$for (sird)
+# IC_NMODEL -- Compute the quadrature average (or summed) noise model.
+# Options include a weighted average/sum.
+
+procedure ic_nmodel$t (d, m, n, nm, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real nm[3,nimages] # Noise model parameters
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+$if (datatype == sil)
+real average[npts] # Average (returned)
+$else
+PIXEL average[npts] # Average (returned)
+$endif
+
+int i, j, k, n1
+real val, wt, sumwt
+$if (datatype == sil)
+real sum, zero
+data zero /0.0/
+$else
+PIXEL sum, zero
+data zero /0$f/
+$endif
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Mem$t[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ do j = 2, n[i] {
+ val = max (zero, Mem$t[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = max (zero, Mem$t[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n[i] {
+ val = max (zero, Mem$t[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Mem$t[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ wt = wts[Memi[m[1]+k]]
+ sum = val * wt**2
+ sumwt = wt
+ do j = 2, n1 {
+ val = max (zero, Mem$t[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + val * wt**2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = max (zero, Mem$t[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = Mem$t[d[1]+k]**2
+ do j = 2, n1 {
+ val = max (zero, Mem$t[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] +
+ (val*nm[3,j])**2
+ sum = sum + val
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = max (zero, Mem$t[d[1]+k])
+ val = nm[1,1] + val/nm[2,1] + (val*nm[3,1])**2
+ sum = val
+ do j = 2, n1 {
+ val = max (zero, Mem$t[d[j]+k])
+ val = nm[1,j] + val/nm[2,j] + (val*nm[3,j])**2
+ sum = sum + val
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+$endfor
diff --git a/pkg/images/immatch/src/imcombine/src/icomb.gx b/pkg/images/immatch/src/imcombine/src/icomb.gx
new file mode 100644
index 00000000..ae489158
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icomb.gx
@@ -0,0 +1,761 @@
+# 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"
+
+# The following is for compiling under V2.11.
+define IM_BUFFRAC IM_BUFSIZE
+include <imset.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, scales, zeros, wts, offsets, nimages, bufsize)
+
+pointer in[nimages] # Input images
+pointer out[ARB] # Output images
+real scales[nimages] # Scales
+real zeros[nimages] # Zeros
+real wts[nimages] # Weights
+int offsets[nimages,ARB] # Input image offsets
+int nimages # Number of input images
+int bufsize # IMIO buffer size
+
+char str[1]
+int i, j, k, npts, fd, stropen(), xt_imgnl$t()
+pointer sp, d, id, n, m, lflag, v, dbuf
+pointer im, buf, xt_opix(), impl1i()
+errchk stropen, xt_cpix, xt_opix, xt_imgnl$t, impl1i, ic_combine$t
+$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 (v, IM_MAXDIM, TY_LONG)
+ call amovki (D_ALL, Memi[lflag], nimages)
+ call amovkl (1, Meml[v], IM_MAXDIM)
+
+ # 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)
+ call aclr$t (Mem$t[Memi[dbuf+i-1]], npts)
+ }
+ } else {
+ do i = 1, nimages {
+ im = xt_opix (in[i], i, 1)
+ if (im != in[i]) {
+ call salloc (Memi[dbuf+i-1], npts, TY_PIXEL)
+ call aclr$t (Mem$t[Memi[dbuf+i-1]], npts)
+ }
+ }
+ call amovki (NULL, Memi[dbuf], nimages)
+ }
+
+ if (project) {
+ call imseti (in[1], IM_NBUFS, nimages)
+ call imseti (in[1], IM_BUFFRAC, 0)
+ call imseti (in[1], IM_BUFSIZE, bufsize)
+ do i = 1, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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, 6 {
+ if (out[i] != NULL) {
+ call imseti (out[i], IM_BUFFRAC, 0)
+ 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)
+ }
+ if (out[4] != NULL) {
+ buf = impl1i (out[4])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[5] != NULL) {
+ buf = impl1i (out[5])
+ call aclri (Memi[buf], npts)
+ }
+ if (out[6] != NULL) {
+ buf = impl1i (out[6])
+ call aclri (Memi[buf], npts)
+ }
+
+ # Do I/O for first input image line.
+ if (!project) {
+ do i = 1, nimages {
+ call xt_imseti (i, "bufsize", bufsize)
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ call xt_cpix (i)
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ call xt_cpix (i)
+ }
+
+ do i = 1, nimages {
+ j = max (0, offsets[i,1])
+ k = min (npts, IM_LEN(in[i],1) + offsets[i,1])
+ if (k - j < 1)
+ next
+ j = 1 - offsets[i,2]
+ if (j < 1 || j > IM_LEN(in[i],2))
+ next
+ iferr {
+ Meml[v+1] = j
+ j = xt_imgnl$t (in[i], i, buf, Meml[v], 1)
+ } then {
+ call imseti (im, IM_PIXFD, NULL)
+ 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, scales, zeros, 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[ARB] # 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(), errcode()
+real r, imgetr()
+pointer sp, fname, imname, v1, v2, v3, work
+pointer outdata, buf, nmod, 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, ic_emask
+errchk ic_gdata$t
+
+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, SUM, QUAD, NMODEL:
+ if (dowts)
+ keepids = true
+ else
+ keepids = false
+ case MEDIAN:
+ dowts = false
+ keepids = false
+ }
+ docombine = true
+
+ # Get noise model parameters.
+ if (combine==NMODEL) {
+ call salloc (nmod, 3*nimages, TY_REAL)
+ i = 1
+ if (ctor (Memc[rdnoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = r
+ } else {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)] = imgetr (in[i], Memc[rdnoise])
+ }
+ i = 1
+ if (ctor (Memc[gain], i, r) > 0) {
+ do i = 1, nimages {
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[gain])
+ Memr[nmod+3*(i-1)+1] = r * scales[i]
+ Memr[nmod+3*(i-1)] =
+ max ((Memr[nmod+3*(i-1)] / Memr[nmod+3*(i-1)+1]) ** 2,
+ 1e4 / MAX_REAL)
+ }
+ }
+ i = 1
+ if (ctor (Memc[snoise], i, r) > 0) {
+ do i = 1, nimages
+ Memr[nmod+3*(i-1)+2] = r
+ } else {
+ do i = 1, nimages {
+ r = imgetr (in[i], Memc[snoise])
+ Memr[nmod+3*(i-1)+2] = r
+ }
+ }
+ }
+
+ # 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 (out[6] != NULL) {
+ keepids = true
+ call ic_einit (in, nimages, Memc[expkeyword], 1., 2**27-1)
+ }
+
+ 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)
+ }
+
+# This idea turns out to has a problem with masks are used with wcs offsets.
+# the matching of masks to images based on WCS requires access to the WCS
+# of the images. For now we drop this idea but maybe a way can be identified
+# to know when this is not going to be needed.
+# # Reduce header memory use.
+# do i = 1, nimages
+# call xt_minhdr (i)
+
+ $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, nimages, npts,
+ YES, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, YES, Memr[outdata])
+ case SUM:
+ call ic_average$t (d, id, n, wts, nimages, npts,
+ YES, NO, Memr[outdata])
+ case QUAD:
+ call ic_quad$t (d, id, n, wts, nimages, npts,
+ YES, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodel$t (d, id, n, Memr[nmod], wts,
+ nimages, npts, YES, 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])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, nimages, npts,
+ YES, YES, Mem$t[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, YES, Mem$t[outdata])
+ case SUM:
+ call ic_average$t (d, id, n, wts, nimages, npts,
+ YES, NO, Mem$t[outdata])
+ case QUAD:
+ call ic_quad$t (d, id, n, wts, nimages, npts,
+ YES, YES, Mem$t[outdata])
+ case NMODEL:
+ call ic_nmodel$t (d, id, n, Memr[nmod], wts,
+ nimages, npts, YES, 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])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, nimages, npts,
+ NO, YES, Memr[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, NO, Memr[outdata])
+ case SUM:
+ call ic_average$t (d, id, n, wts, nimages, npts,
+ NO, NO, Memr[outdata])
+ case QUAD:
+ call ic_quad$t (d, id, n, wts, nimages, npts,
+ NO, YES, Memr[outdata])
+ case NMODEL:
+ call ic_nmodel$t (d, id, n, Memr[nmod], wts,
+ nimages, npts, NO, YES, Memr[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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, nimages, npts,
+ NO, YES, Mem$t[outdata])
+ case MEDIAN:
+ call ic_median$t (d, n, npts, NO, Mem$t[outdata])
+ case SUM:
+ call ic_average$t (d, id, n, wts, nimages, npts,
+ NO, NO, Mem$t[outdata])
+ case QUAD:
+ call ic_quad$t (d, id, n, wts, nimages, npts,
+ NO, YES, Mem$t[outdata])
+ case NMODEL:
+ call ic_nmodel$t (d, id, n, Memr[nmod], wts,
+ nimages, npts, NO, YES, Mem$t[outdata])
+ }
+
+ if (out[2] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[2], buf, Meml[v1])
+ do i = 1, npts {
+ if (n[i] > 0)
+ Memi[buf] = 0
+ else if (n[i] == 0)
+ Memi[buf] = 1
+ else
+ Memi[buf] = 2
+ buf = buf + 1
+ }
+ }
+
+ 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)
+
+ if (out[5] != NULL) {
+ call amovl (Meml[v2], Meml[v1], IM_MAXDIM)
+ i = impnli (out[5], buf, Meml[v1])
+ call amovki (nimages, Memi[buf], npts)
+ call asubi (Memi[buf], n, Memi[buf], npts)
+ }
+
+ if (out[6] != NULL)
+ call ic_emask (out[6], Meml[v2], id, nimages, n, wts, 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
diff --git a/pkg/images/immatch/src/imcombine/src/icombine.com b/pkg/images/immatch/src/imcombine/src/icombine.com
new file mode 100644
index 00000000..55ad308b
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icombine.com
@@ -0,0 +1,45 @@
+# ICOMBINE Common
+
+int combine # Combine algorithm
+int medtype # Median type
+int reject # Rejection algorithm
+bool project # Combine across the highest dimension?
+real blank # Blank value
+pointer expkeyword # Exposure time keyword
+pointer statsec # Statistics section
+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?
+bool verbose # Verbose?
+
+pointer icm # Mask data structure
+
+common /imccom/ combine, medtype, reject, blank, expkeyword, statsec, 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, verbose, icm
diff --git a/pkg/images/immatch/src/imcombine/src/icombine.h b/pkg/images/immatch/src/imcombine/src/icombine.h
new file mode 100644
index 00000000..51f60887
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icombine.h
@@ -0,0 +1,63 @@
+# ICOMBINE Definitions
+
+# Memory management parameters;
+define MAXMEMORY 500000000 # maximum memory
+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|lmedian|sum|quadrature|nmodel|"
+define AVERAGE 1
+define MEDIAN 2
+define LMEDIAN 3
+define SUM 4
+define QUAD 5
+define NMODEL 6
+
+# Median types:
+define MEDAVG 1 # Central average for even N
+define MEDLOW 2 # Lower value for even N
+
+# 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|novalue|"
+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_NOVAL 6 # Value selecting no value (good = 0)
+define M_LTVAL 7 # Values less than specified are good
+define M_GTVAL 8 # Values greater than specified are good
+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/images/immatch/src/imcombine/src/icombine.x b/pkg/images/immatch/src/imcombine/src/icombine.x
new file mode 100644
index 00000000..b6e5ddd4
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icombine.x
@@ -0,0 +1,520 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <imset.h>
+include <error.h>
+include <syserr.h>
+include "icombine.h"
+
+
+# ICOMBINE -- 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, output, headers, bmask, rmask, nrmask, emask,
+ sigma, logfile, scales, zeros, wts, stack, delete, listonly)
+
+int list #I List of input images
+char output[ARB] #I Output image
+char headers[ARB] #I Output header rootname
+char bmask[ARB] #I Bad pixel mask
+char rmask[ARB] #I Rejection mask
+char nrmask[ARB] #I Nreject mask
+char emask[ARB] #I Exposure mask
+char sigma[ARB] #I Sigma image (optional)
+char logfile[ARB] #I Logfile (optional)
+real scales[ARB] #I Scale factors
+real zeros[ARB] #I Offset factors
+real wts[ARB] #I Weights
+int stack #I Stack input images?
+int delete #I Delete input images?
+int listonly #I List images to combine?
+
+bool proj
+char input[SZ_FNAME], errstr[SZ_LINE]
+int i, j, nimages, intype, bufsize, oldsize, stack1, err, retry
+int maxsize, maxmemory, memory
+pointer sp, im, in1, in, out[6], offsets, key, tmp, bpmstack
+
+char clgetc()
+int clgwrd(), imtlen(), imtgetim(), imtrgetim(), getdatatype(), envgeti()
+int begmem(), errget(), open(), ty_max(), sizeof(), strmatch()
+pointer immap(), xt_immap(), ic_pmmap()
+errchk ic_imstack, immap, imunmap, xt_immap, ic_pmmap, ic_setout
+
+include "icombine.com"
+
+define retry_ 98
+define err_ 99
+
+begin
+ if (listonly == YES) {
+ # Write the output list.
+ if (output[1] == EOS) {
+ call imtrew (list)
+ while (imtgetim (list, input, SZ_FNAME)!=EOF) {
+ i = strmatch (input, "[0]") - 3
+ if (i > 0)
+ call strcpy (input[i+3], input[i], SZ_FNAME)
+ call printf ("%s\n")
+ call pargstr (input)
+ }
+ } else {
+ call sprintf (errstr, SZ_LINE, "%s.list")
+ call pargstr (output)
+ iferr (logfd = open (errstr, APPEND, TEXT_FILE))
+ call erract (EA_WARN)
+ call imtrew (list)
+ while (imtgetim (list, input, SZ_FNAME)!=EOF) {
+ i = strmatch (input, "[0]") - 3
+ if (i > 0)
+ call strcpy (input[i+3], input[i], SZ_FNAME)
+ call printf ("%s -> %s\n")
+ call pargstr (input)
+ call pargstr (errstr)
+ call fprintf (logfd, "%s\n")
+ call pargstr (input)
+ }
+ call close (logfd)
+ }
+ return
+ }
+
+ nimages = imtlen (list)
+ if (nimages == 0)
+ call error (1, "No images to combine")
+
+ if (project) {
+ if (imtgetim (list, input, SZ_FNAME) == EOF)
+ call error (1, "No image to project")
+ }
+
+ bufsize = 0
+# if (nimages > LAST_FD - 15)
+# stack1 = YES
+# else
+ stack1 = stack
+
+ retry = 0
+
+retry_
+ iferr {
+ call smark (sp)
+ call salloc (in, 1, TY_POINTER)
+
+ nimages = 0
+ in1 = NULL; Memi[in] = NULL; logfd = NULL
+ out[1] = NULL; out[2] = NULL; out[3] = NULL
+ out[4] = NULL; out[5] = NULL; out[6] = NULL
+
+ # Stack the input images.
+ if (stack1 == YES) {
+ proj = project
+ project = true
+ call salloc (bpmstack, SZ_FNAME, TY_CHAR)
+ i = clgwrd ("masktype", Memc[bpmstack], SZ_FNAME, MASKTYPES)
+ if (i == M_NONE)
+ Memc[bpmstack] = EOS
+ else {
+ call mktemp ("tmp", Memc[bpmstack], SZ_FNAME)
+ call strcat (".pl", Memc[bpmstack], SZ_FNAME)
+ }
+ call mktemp ("tmp", input, SZ_FNAME)
+ call imtrew (list)
+ call ic_imstack (list, input, Memc[bpmstack])
+ }
+
+ # Open the input image(s).
+ 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) {
+ nimages = nimages + 1
+ tmp = xt_immap (input, READ_ONLY, 0, nimages, retry)
+ Memi[in+nimages-1] = tmp
+ }
+
+ # Check sizes and set I/O option.
+ intype = 0
+ tmp = Memi[in]
+ do i = 2, nimages {
+ do j = 1, IM_NDIM(tmp) {
+ if (IM_LEN(tmp,j) != IM_LEN(Memi[in+i-1],j))
+ intype = 1
+ }
+ if (intype == 1)
+ break
+ }
+ if (intype == 1)
+ call xt_imseti (0, "option", intype)
+ }
+
+ # Check if there are no images.
+ if (nimages == 0)
+ call error (1, "No 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 / 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.
+ if (stack1 == YES) {
+ call imtrew (list)
+ i = imtgetim (list, errstr, SZ_LINE)
+ in1 = immap (errstr, READ_ONLY, 0)
+ tmp = immap (output, NEW_COPY, in1); out[1] = tmp
+ call salloc (key, SZ_FNAME, TY_CHAR)
+ do i = 1, nimages {
+ call sprintf (Memc[key], SZ_FNAME, "stck%04d")
+ call pargi (i)
+ iferr (call imdelf (out[1], Memc[key]))
+ ;
+ if (Memc[bpmstack] != EOS) {
+ call sprintf (Memc[key], SZ_FNAME, "bpm%04d")
+ call pargi (i)
+ iferr (call imdelf (out[1], Memc[key]))
+ ;
+ }
+ }
+ } else {
+ tmp = immap (output, NEW_COPY, Memi[in]); out[1] = tmp
+ if (project) {
+ IM_LEN(out[1],IM_NDIM(out[1])) = 1
+ IM_NDIM(out[1]) = IM_NDIM(out[1]) - 1
+ }
+ }
+ call salloc (offsets, nimages*IM_NDIM(out[1]), TY_INT)
+ iferr (call ic_setout (Memi[in], out, Memi[offsets], nimages)) {
+ call erract (EA_WARN)
+ call error (1, "Can't set output geometry")
+ }
+ call ic_hdr (Memi[in], out, nimages)
+ iferr (call imdelf (out, "BPM"))
+ ;
+
+ # 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 = 100, nimages {
+ j = imtrgetim (list, i, input, SZ_FNAME)
+ if (i < 999)
+ call sprintf (Memc[key], SZ_FNAME, "imcmb%d")
+ else if (i < 9999)
+ call sprintf (Memc[key], SZ_FNAME, "imcm%d")
+ else
+ call sprintf (Memc[key], SZ_FNAME, "imc%d")
+ call pargi (i)
+ call imastr (out[4], Memc[key], input)
+ }
+ }
+ } else
+ out[4] = NULL
+
+ # Open bad pixel pixel list file if given.
+ if (bmask[1] != EOS) {
+ tmp = ic_pmmap (bmask, NEW_COPY, out[1]); out[2] = tmp
+ } else
+ out[2] = NULL
+
+ # Open nreject pixel list file if given.
+ if (nrmask[1] != EOS) {
+ tmp = ic_pmmap (nrmask, NEW_COPY, out[1]); out[5] = tmp
+ } else
+ out[5] = NULL
+
+ # Open exposure mask if given.
+ if (emask[1] != EOS) {
+ tmp = ic_pmmap (emask, NEW_COPY, out[1]); out[6] = tmp
+ } else
+ out[6] = 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, Memi[offsets],
+ min(retry,1))
+
+ # 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.
+
+ iferr (maxmemory = envgeti ("imcombine_maxmemory"))
+ maxmemory = MAXMEMORY
+ memory = begmem (0, oldsize, maxsize)
+ memory = min (memory, maxsize, maxmemory)
+ bufsize = FUDGE * memory / (nimages + 1) / sizeof (intype)
+ }
+
+ # 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.
+
+ switch (ty_max (intype, IM_PIXTYPE(out[1]))) {
+ case TY_SHORT:
+ call icombines (Memi[in], out, scales, zeros,
+ wts, Memi[offsets], nimages, bufsize)
+ case TY_USHORT, TY_INT, TY_LONG:
+ call icombinei (Memi[in], out, scales, zeros,
+ wts, Memi[offsets], nimages, bufsize)
+ case TY_DOUBLE:
+ call icombined (Memi[in], out, scales, zeros,
+ wts, Memi[offsets], nimages, bufsize)
+ case TY_COMPLEX:
+ call error (1, "Complex images not allowed")
+ default:
+ call icombiner (Memi[in], out, scales, zeros,
+ wts, Memi[offsets], nimages, bufsize)
+ }
+ } then {
+ err = errget (errstr, SZ_LINE)
+ if (err == SYS_IKIOPIX && nimages < 250)
+ err = SYS_MFULL
+ call ic_mclose (nimages)
+ if (!project) {
+ do j = 2, nimages {
+ if (Memi[in+j-1] != NULL)
+ call xt_imunmap (Memi[in+j-1], j)
+ }
+ }
+ if (out[2] != NULL) {
+ iferr (call imunmap (out[2]))
+ ;
+ iferr (call imdelete (bmask))
+ ;
+ }
+ if (out[3] != NULL) {
+ iferr (call imunmap (out[3]))
+ ;
+ iferr (call imdelete (sigma))
+ ;
+ }
+ if (out[4] != NULL) {
+ iferr (call imunmap (out[4]))
+ ;
+ iferr (call imdelete (rmask))
+ ;
+ }
+ if (out[5] != NULL) {
+ iferr (call imunmap (out[5]))
+ ;
+ iferr (call imdelete (nrmask))
+ ;
+ }
+ if (out[6] != NULL) {
+ iferr (call imunmap (out[6]))
+ ;
+ iferr (call imdelete (emask))
+ ;
+ }
+ if (out[1] != NULL) {
+ iferr (call imunmap (out[1]))
+ ;
+ iferr (call imdelete (output))
+ ;
+ }
+ if (Memi[in] != NULL)
+ call xt_imunmap (Memi[in], 1)
+ if (in1 != NULL)
+ call imunmap (in1)
+ if (logfd != NULL)
+ call close (logfd)
+
+ switch (err) {
+ case SYS_MFULL:
+ if (project)
+ goto err_
+
+ if (bufsize < 10000 && retry > 2) {
+ call strcat ("- Maybe min_lenuserarea is too large",
+ errstr, SZ_LINE)
+ goto err_
+ }
+
+ bufsize = bufsize / 2
+ retry = retry + 1
+ call sfree (sp)
+ goto retry_
+ case SYS_FTOOMANYFILES, SYS_IKIOPEN, SYS_IKIOPIX, SYS_FOPEN, SYS_FWTNOACC:
+ if (project)
+ goto err_
+ stack1 = YES
+ call sfree (sp)
+ goto retry_
+ default:
+err_
+ if (stack1 == YES) {
+ iferr (call imdelete (input))
+ ;
+ if (Memc[bpmstack] != EOS) {
+ iferr (call imdelete (Memc[bpmstack]))
+ ;
+ }
+ }
+ call fixmem (oldsize)
+ while (imtgetim (list, input, SZ_FNAME)!=EOF)
+ ;
+ call sfree (sp)
+ call error (err, errstr)
+ }
+ }
+
+ # Unmap all the images, close the log file, and restore memory.
+ if (out[2] != NULL)
+ iferr (call imunmap (out[2]))
+ call erract (EA_WARN)
+ if (out[3] != NULL)
+ iferr (call imunmap (out[3]))
+ call erract (EA_WARN)
+ if (out[4] != NULL) {
+ # Close the output first so that there is no confusion with
+ # inheriting the output header. Then update the WCS for the
+ # extra dimension. Note that this may not be correct with
+ # axis reduced WCS.
+ iferr {
+ call imunmap (out[4])
+ out[4] = immap (rmask, READ_WRITE, 0)
+ i = IM_NDIM(out[4])
+ call imaddi (out[4], "WCSDIM", i)
+ call sprintf (errstr, SZ_LINE, "LTM%d_%d")
+ call pargi (i)
+ call pargi (i)
+ call imaddr (out[4], errstr, 1.)
+ call sprintf (errstr, SZ_LINE, "CD%d_%d")
+ call pargi (i)
+ call pargi (i)
+ call imaddr (out[4], errstr, 1.)
+ call imunmap (out[4])
+ } then
+ call erract (EA_WARN)
+ }
+ if (out[5] != NULL)
+ iferr (call imunmap (out[5]))
+ call erract (EA_WARN)
+ if (out[6] != NULL)
+ iferr (call imunmap (out[6]))
+ call erract (EA_WARN)
+ if (out[1] != NULL) {
+ call imunmap (out[1])
+ if (headers[1] != EOS) {
+ # Write input headers to a multiextension file if desired.
+ # This might be the same as the output image.
+ iferr {
+ do i = 1, nimages {
+ im = Memi[in+i-1]
+ call imstats (im, IM_IMAGENAME, input, SZ_FNAME)
+ if (strmatch (headers, ".fits$") == 0) {
+ call sprintf (errstr, SZ_LINE, "%s.fits[append]")
+ call pargstr (headers)
+ } else {
+ call sprintf (errstr, SZ_LINE, "%s[append]")
+ call pargstr (headers)
+ }
+ tmp = immap (errstr, NEW_COPY, im)
+ IM_NDIM(tmp) = 0
+ do j = 1, IM_NDIM(im) {
+ call sprintf (errstr, SZ_LINE, "AXLEN%d")
+ call pargi (j)
+ call imaddi (tmp, errstr, IM_LEN(im,j))
+ }
+ call imastr (tmp, "INIMAGE", input)
+ call imastr (tmp, "OUTIMAGE", output)
+ call imastr (tmp, "EXTNAME", input)
+ call imunmap (tmp)
+ }
+ if (logfd != NULL) {
+ call eprintf (" Headers = %s\n")
+ call pargstr (headers)
+ }
+ } then
+ call erract (EA_WARN)
+ }
+ }
+ if (!project) {
+ do i = 2, nimages {
+ if (Memi[in+i-1] != NULL)
+ call xt_imunmap (Memi[in+i-1], i)
+ }
+ }
+ if (Memi[in] != NULL)
+ call xt_imunmap (Memi[in], 1)
+ if (in1 != NULL)
+ call imunmap (in1)
+ if (stack1 == YES) {
+ call imdelete (input)
+ if (Memc[bpmstack] != EOS)
+ call imdelete (Memc[bpmstack])
+ project = proj
+ }
+ if (logfd != NULL)
+ call close (logfd)
+ call ic_mclose (nimages)
+ call fixmem (oldsize)
+ call sfree (sp)
+end
diff --git a/pkg/images/immatch/src/imcombine/src/icpclip.gx b/pkg/images/immatch/src/imcombine/src/icpclip.gx
new file mode 100644
index 00000000..628dca0d
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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 = max (0, 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 = max (0, 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/icpmmap.x b/pkg/images/immatch/src/imcombine/src/icpmmap.x
new file mode 100644
index 00000000..1afeedd7
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icpmmap.x
@@ -0,0 +1,34 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <pmset.h>
+
+
+# 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/images/immatch/src/imcombine/src/icquad.gx b/pkg/images/immatch/src/imcombine/src/icquad.gx
new file mode 100644
index 00000000..4ecf3aa0
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icquad.gx
@@ -0,0 +1,133 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <mach.h>
+include "../icombine.h"
+include "../icmask.h"
+
+$for (sird)
+# IC_QUAD -- Compute the quadrature average (or summed) image line.
+# Options include a weighted average/sum.
+
+procedure ic_quad$t (d, m, n, wts, nimages, npts, doblank, doaverage,
+ average)
+
+pointer d[nimages] # Data pointers
+pointer m[nimages] # Image ID pointers
+int n[npts] # Number of points
+real wts[nimages] # Weights
+int nimages # Number of images
+int npts # Number of output points per line
+int doblank # Set blank values?
+int doaverage # Do average?
+$if (datatype == sil)
+real average[npts] # Average (returned)
+$else
+PIXEL average[npts] # Average (returned)
+$endif
+
+int i, j, k, n1
+real val, wt, sumwt
+$if (datatype == sil)
+real sum
+$else
+PIXEL sum
+$endif
+
+include "../icombine.com"
+
+begin
+ # If no data has been excluded do the average/sum 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/sum
+ # to the blank value if requested.
+
+ if (dflag == D_ALL) {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ k = i - 1
+ val = Mem$t[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ do j = 2, n[i] {
+ val = Mem$t[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val * wt) ** 2
+ }
+ average[i] = sqrt(sum)
+ }
+ } else {
+ do i = 1, npts {
+ k = i - 1
+ val = Mem$t[d[1]+k]
+ sum = val**2
+ do j = 2, n[i] {
+ val = Mem$t[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n[i]
+ else
+ average[i] = sqrt(sum)
+ }
+ }
+ } else if (dflag == D_NONE) {
+ if (doblank == YES) {
+ do i = 1, npts
+ average[i] = blank
+ }
+ } else {
+ if (dowts && doaverage == YES) {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Mem$t[d[1]+k]
+ wt = wts[Memi[m[1]+k]]
+ sum = (val * wt) ** 2
+ sumwt = wt
+ do j = 2, n1 {
+ val = Mem$t[d[j]+k]
+ wt = wts[Memi[m[j]+k]]
+ sum = sum + (val* wt) ** 2
+ sumwt = sumwt + wt
+ }
+ if (doaverage == YES) {
+ if (sumwt > 0)
+ average[i] = sqrt(sum) / sumwt
+ else {
+ val = Mem$t[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Mem$t[d[j]+k]
+ sum = sum + val**2
+ }
+ average[i] = sqrt(sum) / n1
+ }
+ } else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ } else {
+ do i = 1, npts {
+ n1 = abs(n[i])
+ if (n1 > 0) {
+ k = i - 1
+ val = Mem$t[d[1]+k]
+ sum = val**2
+ do j = 2, n1 {
+ val = Mem$t[d[j]+k]
+ sum = sum + val**2
+ }
+ if (doaverage == YES)
+ average[i] = sqrt(sum) / n1
+ else
+ average[i] = sqrt(sum)
+ } else if (doblank == YES)
+ average[i] = blank
+ }
+ }
+ }
+end
+$endfor
diff --git a/pkg/images/immatch/src/imcombine/src/icrmasks.x b/pkg/images/immatch/src/imcombine/src/icrmasks.x
new file mode 100644
index 00000000..8b9a0c3d
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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/images/immatch/src/imcombine/src/icscale.x b/pkg/images/immatch/src/imcombine/src/icscale.x
new file mode 100644
index 00000000..42d62f8d
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icscale.x
@@ -0,0 +1,351 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <imset.h>
+include "icombine.h"
+
+
+# IC_SCALE -- Get and set the scaling factors.
+#
+# If the scaling parameters have been set earlier then this routine
+# just normalizes the factors and writes the log output.
+# When dealing with individual images using image statistics for scaling
+# factors this routine determines the image statistics rather than being
+# done earlier since the input images have all been mapped at this stage.
+
+procedure ic_scale (in, out, offsets, scales, zeros, wts, nimages)
+
+pointer in[nimages] # Input images
+pointer out[ARB] # 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, sumwts
+pointer sp, ncombine, exptime, modes, medians, means
+pointer section, str, sname, zname, wname, im, imref
+bool domode, domedian, domean, dozero, dos, doz, dow, snorm, znorm, wflag
+
+int imgeti(), strdic(), ic_gscale()
+real imgetr(), asumr(), asumi()
+pointer xt_opix()
+errchk ic_gscale, xt_opix, 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 (section, SZ_LINE, 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)
+
+ # Get the number of images previously combined and the exposure times.
+ # The default combine number is 1 and the default exposure is 0.
+
+ do i = 1, nimages {
+ iferr (Memi[ncombine+i-1] = imgeti (in[i], "ncombine"))
+ Memi[ncombine+i-1] = 1
+ if (Memc[expkeyword] != EOS) {
+ iferr (Memr[exptime+i-1] = imgetr (in[i], Memc[expkeyword]))
+ Memr[exptime+i-1] = 0.
+ } else
+ Memr[exptime+i-1] = 0.
+ if (project) {
+ call amovki (Memi[ncombine], Memi[ncombine], nimages)
+ call amovkr (Memr[exptime], Memr[exptime], nimages)
+ break
+ }
+ }
+
+ # Set scaling type and 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 if needed.
+ dos = ((stype==S_MODE)||(stype==S_MEDIAN)||(stype==S_MEAN))
+ doz = ((ztype==S_MODE)||(ztype==S_MEDIAN)||(ztype==S_MEAN))
+ dow = ((wtype==S_MODE)||(wtype==S_MEDIAN)||(wtype==S_MEAN))
+ if (dos) {
+ dos = false
+ do i = 1, nimages
+ if (IS_INDEFR(scales[i])) {
+ dos = true
+ break
+ }
+ }
+ if (doz) {
+ doz = false
+ do i = 1, nimages
+ if (IS_INDEFR(zeros[i])) {
+ doz = true
+ break
+ }
+ }
+ if (dow) {
+ dow = false
+ do i = 1, nimages
+ if (IS_INDEFR(wts[i])) {
+ dow = true
+ break
+ }
+ }
+
+ if (dos || doz || dow) {
+ 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))
+
+ Memc[section] = EOS
+ Memc[str] = EOS
+ call sscan (Memc[statsec])
+ 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 {
+ im = xt_opix (in[i], i, 0)
+ if (imref != out[1])
+ imref = im
+ if ((dos && IS_INDEFR(scales[i])) ||
+ (doz && IS_INDEFR(zeros[i])) ||
+ (dow && IS_INDEFR(wts[i]))) {
+ call ic_statr (im, imref, Memc[section], offsets, i,
+ nimages, domode, domedian, domean, mode, median, mean)
+ if (domode) {
+ if (stype == S_MODE && IS_INDEFR(scales[i]))
+ scales[i] = mode
+ if (ztype == S_MODE && IS_INDEFR(zeros[i]))
+ zeros[i] = mode
+ if (wtype == S_MODE && IS_INDEFR(wts[i]))
+ wts[i] = mode
+ }
+ if (domedian) {
+ if (stype == S_MEDIAN && IS_INDEFR(scales[i]))
+ scales[i] = median
+ if (ztype == S_MEDIAN && IS_INDEFR(zeros[i]))
+ zeros[i] = median
+ if (wtype == S_MEDIAN && IS_INDEFR(wts[i]))
+ wts[i] = median
+ }
+ if (domean) {
+ if (stype == S_MEAN && IS_INDEFR(scales[i]))
+ scales[i] = mean
+ if (ztype == S_MEAN && IS_INDEFR(zeros[i]))
+ zeros[i] = mean
+ if (wtype == S_MEAN && IS_INDEFR(wts[i]))
+ wts[i] = mean
+ }
+ }
+ }
+ }
+
+ # Save the image statistics if computed.
+ call amovkr (INDEFR, Memr[modes], nimages)
+ call amovkr (INDEFR, Memr[medians], nimages)
+ call amovkr (INDEFR, Memr[means], nimages)
+ if (stype == S_MODE)
+ call amovr (scales, Memr[modes], nimages)
+ if (stype == S_MEDIAN)
+ call amovr (scales, Memr[medians], nimages)
+ if (stype == S_MEAN)
+ call amovr (scales, Memr[means], nimages)
+ if (ztype == S_MODE)
+ call amovr (zeros, Memr[modes], nimages)
+ if (ztype == S_MEDIAN)
+ call amovr (zeros, Memr[medians], nimages)
+ if (ztype == S_MEAN)
+ call amovr (zeros, Memr[means], nimages)
+ if (wtype == S_MODE)
+ call amovr (wts, Memr[modes], nimages)
+ if (wtype == S_MEDIAN)
+ call amovr (wts, Memr[medians], nimages)
+ if (wtype == S_MEAN)
+ call amovr (wts, Memr[means], nimages)
+
+ # If nothing else has set the scaling factors set them to defaults.
+ do i = 1, nimages {
+ if (IS_INDEFR(scales[i]))
+ scales[i] = 1.
+ if (IS_INDEFR(zeros[i]))
+ zeros[i] = 0.
+ if (IS_INDEFR(wts[i]))
+ wts[i] = 1.
+ }
+
+ 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 factors relative to the first image.
+ 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)
+ mean = scales[1]
+ call adivkr (scales, mean, scales, nimages)
+ call adivr (zeros, scales, zeros, 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] * zeros[1] / 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.
+
+ mean = zeros[1]
+ call asubkr (zeros, mean, 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)
+ if (mean > 0.)
+ call adivkr (wts, mean, wts, nimages)
+ else {
+ call eprintf ("WARNING: Mean weight is zero -- using no weights\n")
+ call amovkr (1., wts, nimages)
+ mean = 1.
+ }
+
+ # 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
+ }
+ }
+ }
+
+ # Set the output header parameters.
+ nout = asumi (Memi[ncombine], nimages)
+ call imaddi (out[1], "ncombine", nout)
+ mean = 0.
+ sumwts = 0.
+ do i = 1, nimages {
+ ifnoerr (mode = imgetr (in[i], "ccdmean")) {
+ mean = mean + wts[i] * mode / scales[i]
+ sumwts = sumwts + wts[i]
+ }
+ }
+ if (sumwts > 0.) {
+ mean = mean / sumwts
+ ifnoerr (mode = imgetr (out[1], "ccdmean")) {
+ call imaddr (out[1], "ccdmean", mean)
+ iferr (call imdelf (out[1], "ccdmeant"))
+ ;
+ }
+ }
+ if (out[2] != NULL) {
+ call imstats (out[2], IM_IMAGENAME, Memc[str], SZ_FNAME)
+ call imastr (out[1], "BPM", Memc[str])
+ }
+
+ # Start the log here since much of the info is only available here.
+ if (verbose) {
+ i = logfd
+ logfd = STDOUT
+ 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)
+
+ logfd = i
+ }
+ 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)
+
+ doscale = (doscale || dozero)
+
+ call sfree (sp)
+end
diff --git a/pkg/images/immatch/src/imcombine/src/icsclip.gx b/pkg/images/immatch/src/imcombine/src/icsclip.gx
new file mode 100644
index 00000000..e4d8f027
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 (max (0, 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 = max (0, n[1])
+ do i = 1, npts {
+ k = i - 1
+ n1 = max (0, 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 <= nh; 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 <= nh; 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 == max (0, 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 (max (0, 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/images/immatch/src/imcombine/src/icsection.x b/pkg/images/immatch/src/imcombine/src/icsection.x
new file mode 100644
index 00000000..746c1f51
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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/images/immatch/src/imcombine/src/icsetout.x b/pkg/images/immatch/src/imcombine/src/icsetout.x
new file mode 100644
index 00000000..efe55681
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icsetout.x
@@ -0,0 +1,332 @@
+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[ARB] # Output images
+int offsets[nimages,ARB] # Offsets
+int nimages # Number of images
+
+int i, j, indim, outdim, mwdim, a, b, amin, bmax, fd, offtype, npix
+real val
+bool proj, reloff, flip, streq(), fp_equald()
+pointer sp, str, fname
+pointer ltv, lref, wref, cd, ltm, coord, shift, axno, axval, section
+pointer mw, ct, mw_openim(), mw_sctran(), xt_immap()
+int open(), fscan(), nscan(), mw_stati(), strlen(), strdic()
+errchk mw_openim, mw_gwtermd, mw_gltermd, mw_gaxmap
+errchk mw_sctran, mw_ctrand, open, xt_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 (ltv, IM_MAXDIM, TY_DOUBLE)
+ call salloc (ltm, IM_MAXDIM*IM_MAXDIM, TY_DOUBLE)
+ 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])
+ proj = (indim != outdim)
+ if (!proj) {
+ 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])
+ call mw_seti (mw, MW_USEAXMAP, NO)
+ mwdim = mw_stati (mw, MW_NPHYSDIM)
+ call mw_gwtermd (mw, Memd[lref], Memd[wref], Memd[cd], mwdim)
+ ct = mw_sctran (mw, "world", "logical", 0)
+ call mw_ctrand (ct, Memd[wref], Memd[lref], mwdim)
+ call mw_ctfree (ct)
+ if (proj)
+ 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 (proj) {
+ 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 {
+ ct = mw_sctran (mw, "world", "logical", 0)
+ call mw_ctrand (ct, Memd[wref], Memd[lref], indim)
+ 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 (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 xt_imunmap (in[i], i)
+ in[i] = xt_immap (Memc[fname], READ_ONLY, TY_CHAR, i, 0)
+ 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[ltv], indim)
+ call mw_ctfree (ct)
+ do j = 1, outdim
+ offsets[1,j] = 0
+ if (proj) {
+ ct = mw_sctran (mw, "physical", "logical", 0)
+ do i = 2, nimages {
+ Memd[ltv+outdim] = i
+ call mw_ctrand (ct, Memd[ltv], 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[ltv], 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) {
+ a = 1
+ b = 0
+ }
+ 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
+ }
+ }
+
+ # Get the output limits.
+ call clgstr ("outlimits", Memc[fname], SZ_FNAME)
+ call sscan (Memc[fname])
+ do j = 1, outdim {
+ call gargi (a)
+ call gargi (b)
+ if (nscan() < 2*j)
+ break
+ if (!IS_INDEFI(a)) {
+ do i = 1, nimages {
+ offsets[i,j] = offsets[i,j] - a + 1
+ if (offsets[i,j] != 0)
+ aligned = false
+ }
+ IM_LEN(out[1],j) = IM_LEN(out[1],j) - a + 1
+ }
+ if (!IS_INDEFI(a) && !IS_INDEFI(b))
+ IM_LEN(out[1],j) = min (IM_LEN(out[1],j), b - a + 1)
+ }
+
+ # Update the WCS.
+ if (proj || !aligned || !reloff) {
+ call mw_close (mw)
+ mw = mw_openim (out[1])
+ mwdim = mw_stati (mw, MW_NPHYSDIM)
+ call mw_gaxmap (mw, Memi[axno], Memi[axval], mwdim)
+ if (!aligned || !reloff) {
+ call mw_gltermd (mw, Memd[cd], Memd[lref], mwdim)
+ do i = 1, mwdim {
+ j = Memi[axno+i-1]
+ if (j > 0 && j <= indim)
+ Memd[lref+i-1] = Memd[lref+i-1] + offsets[1,j]
+ }
+ if (proj)
+ Memd[lref+mwdim-1] = 0.
+ call mw_sltermd (mw, Memd[cd], Memd[lref], mwdim)
+ }
+ if (proj) {
+ # Apply dimensional reduction.
+ do i = 1, mwdim {
+ j = Memi[axno+i-1]
+ if (j <= outdim)
+ next
+ else if (j > outdim+1)
+ Memi[axno+i-1] = j - 1
+ else {
+ Memi[axno+i-1] = 0
+ Memi[axval+i-1] = 0
+ }
+ }
+ call mw_saxmap (mw, Memi[axno], Memi[axval], mwdim)
+ }
+
+ # Reset physical coordinates.
+ if (offtype == WCS || offtype == WORLD) {
+ call mw_gltermd (mw, Memd[ltm], Memd[ltv], mwdim)
+ call mw_gwtermd (mw, Memd[lref], Memd[wref], Memd[cd], mwdim)
+ call mwvmuld (Memd[ltm], Memd[lref], Memd[lref], mwdim)
+ call aaddd (Memd[lref], Memd[ltv], Memd[lref], mwdim)
+ call mwinvertd (Memd[ltm], Memd[ltm], mwdim)
+ call mwmmuld (Memd[cd], Memd[ltm], Memd[cd], mwdim)
+ call mw_swtermd (mw, Memd[lref], Memd[wref], Memd[cd], mwdim)
+ call aclrd (Memd[ltv], mwdim)
+ call aclrd (Memd[ltm], mwdim*mwdim)
+ do i = 1, mwdim
+ Memd[ltm+(i-1)*(mwdim+1)] = 1.
+ call mw_sltermd (mw, Memd[ltm], Memd[ltv], mwdim)
+ }
+ call mw_saveim (mw, out)
+ }
+ call mw_close (mw)
+
+ # Throw an error if the output size is too large.
+ if (offtype != NONE) {
+ npix = IM_LEN(out[1],1)
+ do i = 2, outdim
+ npix = npix * IM_LEN(out[1],i)
+ npix = npix / 1000000000
+ if (npix > 100)
+ call error (1, "Output has more than 100 Gpixels (check offsets)")
+ }
+
+ call sfree (sp)
+end
diff --git a/pkg/images/immatch/src/imcombine/src/icsigma.gx b/pkg/images/immatch/src/imcombine/src/icsigma.gx
new file mode 100644
index 00000000..1304d940
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icsigma.gx
@@ -0,0 +1,122 @@
+# 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
+ }
+ if (sumwt > 0)
+ sigma[i] = sqrt (sum / sumwt * sigcor)
+ else {
+ 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 / n1 * 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/images/immatch/src/imcombine/src/icsort.gx b/pkg/images/immatch/src/imcombine/src/icsort.gx
new file mode 100644
index 00000000..e124da15
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/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/images/immatch/src/imcombine/src/icstat.gx b/pkg/images/immatch/src/imcombine/src/icstat.gx
new file mode 100644
index 00000000..c594182b
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/icstat.gx
@@ -0,0 +1,238 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include "../icombine.h"
+
+define NMAX 100000 # 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()
+
+$if (datatype == csir)
+real asum$t()
+$else $if (datatype == ld)
+double asum$t()
+$else
+PIXEL asum$t()
+$endif $endif
+PIXEL ic_mode$t()
+
+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, nimages, 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)
+ }
+
+ # Close mask until it is needed again.
+ call ic_mclose1 (image, nimages)
+
+ 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.7 # 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/images/immatch/src/imcombine/src/mkpkg b/pkg/images/immatch/src/imcombine/src/mkpkg
new file mode 100644
index 00000000..5f53d4b8
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/mkpkg
@@ -0,0 +1,67 @@
+# Make the IMCOMBINE library.
+
+update:
+ $checkout libimc.a lib$
+ $update libimc.a
+ $checkin libimc.a lib$
+ ;
+
+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/icquad.x, icquad.gx)
+ $(GEN) icquad.gx -o generic/icquad.x $endif
+ $ifolder (generic/icnmodel.x, icnmodel.gx)
+ $(GEN) icnmodel.gx -o generic/icnmodel.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/icomb.x, icomb.gx)
+ $(GEN) icomb.gx -o generic/icomb.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
+
+ $ifolder (generic/xtimmap.x, xtimmap.gx)
+ $(GEN) xtimmap.gx -o generic/xtimmap.x $endif
+ ;
+
+libimc.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+
+ @generic
+
+ icemask.x <imhdr.h> <mach.h>
+ icgscale.x icombine.com icombine.h
+ ichdr.x <imset.h>
+ icimstack.x <error.h> <imhdr.h>
+ iclog.x icmask.h icombine.com icombine.h <imhdr.h> <imset.h>\
+ <mach.h>
+ icmask.x icmask.h icombine.com icombine.h <imhdr.h> <pmset.h>
+ icombine.x icombine.com icombine.h <error.h> <imhdr.h> <imset.h>
+ icpmmap.x <pmset.h>
+ icrmasks.x <imhdr.h>
+ icscale.x icombine.com icombine.h <imhdr.h> <imset.h>
+ icsection.x <ctype.h>
+ icsetout.x icombine.com <imhdr.h> <imset.h> <mwset.h>
+ tymax.x <mach.h>
+ xtprocid.x
+ ;
diff --git a/pkg/images/immatch/src/imcombine/src/tymax.x b/pkg/images/immatch/src/imcombine/src/tymax.x
new file mode 100644
index 00000000..a7f4f469
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/tymax.x
@@ -0,0 +1,27 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+
+
+# 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
diff --git a/pkg/images/immatch/src/imcombine/src/xtimmap.gx b/pkg/images/immatch/src/imcombine/src/xtimmap.gx
new file mode 100644
index 00000000..2e6cfb1e
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/xtimmap.gx
@@ -0,0 +1,634 @@
+include <syserr.h>
+include <error.h>
+include <imhdr.h>
+include <imset.h>
+include <config.h>
+
+# The following is for compiling under V2.11.
+define IM_BUFFRAC IM_BUFSIZE
+include <imset.h>
+
+define VERBOSE false
+
+# These routines maintain an arbitrary number of indexed "open" images which
+# must be READ_ONLY. The calling program may use the returned pointer for
+# header accesses but must call xt_opix before I/O. Subsequent calls to
+# xt_opix may invalidate the pointer. The xt_imunmap call will free memory.
+
+define MAX_OPENIM (LAST_FD-16) # Maximum images kept open
+define MAX_OPENPIX 45 # Maximum pixel files kept open
+
+define XT_SZIMNAME 299 # Size of IMNAME string
+define XT_LEN 179 # Structure length
+define XT_IMNAME Memc[P2C($1)] # Image name
+define XT_ARG Memi[$1+150] # IMMAP header argument
+define XT_IM Memi[$1+151] # IMIO pointer
+define XT_HDR Memi[$1+152] # Copy of IMIO pointer
+define XT_CLOSEFD Memi[$1+153] # Close FD?
+define XT_FLAG Memi[$1+154] # Flag
+define XT_BUFSIZE Memi[$1+155] # Buffer size
+define XT_BUF Memi[$1+156] # Data buffer
+define XT_BTYPE Memi[$1+157] # Data buffer type
+define XT_VS Memi[$1+157+$2] # Start vector (10)
+define XT_VE Memi[$1+167+$2] # End vector (10)
+
+# Options
+define XT_MAPUNMAP 1 # Map and unmap images.
+
+# XT_IMMAP -- Map an image and save it as an indexed open image.
+# The returned pointer may be used for header access but not I/O.
+# The indexed image is closed by xt_imunmap.
+
+pointer procedure xt_immap (imname, acmode, hdr_arg, index, retry)
+
+char imname[ARB] #I Image name
+int acmode #I Access mode
+int hdr_arg #I Header argument
+int index #I Save index
+int retry #I Retry counter
+pointer im #O Image pointer (returned)
+
+int i, envgeti()
+pointer xt, xt_opix()
+errchk xt_opix
+
+int first_time
+data first_time /YES/
+
+include "xtimmap.com"
+
+begin
+ if (acmode != READ_ONLY)
+ call error (1, "XT_IMMAP: Only READ_ONLY allowed")
+
+ # Set maximum number of open images based on retry.
+ if (retry > 0)
+ max_openim = min (1024, MAX_OPENIM) / retry
+ else
+ max_openim = MAX_OPENIM
+
+ # Initialize once per process.
+ if (first_time == YES) {
+ iferr (option = envgeti ("imcombine_option"))
+ option = 1
+ min_open = 1
+ nopen = 0
+ nopenpix = 0
+ nalloc = max_openim
+ call calloc (ims, nalloc, TY_POINTER)
+ first_time = NO
+ }
+
+ # Free image if needed.
+ call xt_imunmap (NULL, index)
+
+ # Allocate structure.
+ if (index > nalloc) {
+ i = nalloc
+ nalloc = index + max_openim
+ call realloc (ims, nalloc, TY_STRUCT)
+ call amovki (NULL, Memi[ims+i], nalloc-i)
+ }
+ call calloc (xt, XT_LEN, TY_STRUCT)
+ Memi[ims+index-1] = xt
+
+ # Initialize.
+ call strcpy (imname, XT_IMNAME(xt), XT_SZIMNAME)
+ XT_ARG(xt) = hdr_arg
+ XT_IM(xt) = NULL
+ XT_HDR(xt) = NULL
+
+ # Open image.
+ last_flag = 0
+ im = xt_opix (NULL, index, 0)
+
+ # Make copy of IMIO pointer for header keyword access.
+ call malloc (XT_HDR(xt), LEN_IMDES+IM_HDRLEN(im)+1, TY_STRUCT)
+ call amovi (Memi[im], Memi[XT_HDR(xt)], LEN_IMDES)
+ call amovi (IM_MAGIC(im), IM_MAGIC(XT_HDR(xt)), IM_HDRLEN(im)+1)
+
+ return (XT_HDR(xt))
+end
+
+
+# XT_OPIX -- Open the image for I/O.
+# If the image has not been mapped return the default pointer.
+
+pointer procedure xt_opix (imdef, index, flag)
+
+int index #I index
+pointer imdef #I Default pointer
+int flag #I Flag
+
+int i, open(), imstati()
+pointer im, xt, xt1, immap()
+errchk open, immap, imunmap
+
+include "xtimmap.com"
+
+begin
+ # Get index pointer.
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ # Use default pointer if index has not been mapped.
+ if (xt == NULL)
+ return (imdef)
+
+ # Close images not accessed during previous line.
+ # In normal usage this should only occur once per line over all
+ # indexed images.
+ if (flag != last_flag) {
+ do i = 1, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL || XT_FLAG(xt1) == last_flag)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: xt_opix imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ call mfree (XT_BUF(xt1), XT_BTYPE(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ }
+
+ # Optimize the file I/O.
+ do i = nalloc, 1, -1 {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ if (nopenpix < MAX_OPENPIX) {
+ if (XT_CLOSEFD(xt1) == NO)
+ next
+ XT_CLOSEFD(xt1) = NO
+ call imseti (im, IM_CLOSEFD, NO)
+ nopenpix = nopenpix + 1
+ }
+ }
+ last_flag = flag
+ }
+
+ # Return pointer for already opened images.
+ im = XT_IM(xt)
+ if (im != NULL) {
+ XT_FLAG(xt) = flag
+ return (im)
+ }
+
+ # Handle more images than the maximum that can be open at one time.
+ if (nopen >= max_openim) {
+ if (option == XT_MAPUNMAP || flag == 0) {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ min_open = i + 1
+ break
+ }
+ if (index <= min_open)
+ min_open = index
+ else {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ break
+ }
+ }
+ } else {
+ # Check here because we can't catch error in immap.
+ i = open ("dev$null", READ_ONLY, BINARY_FILE)
+ call close (i)
+ if (i == LAST_FD - 1)
+ call error (SYS_FTOOMANYFILES, "Too many open files")
+ }
+ }
+
+ # Open image.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_opix immap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ im = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt))
+ XT_IM(xt) = im
+ if (!IS_INDEFI(XT_BUFSIZE(xt)))
+ call imseti (im, IM_BUFSIZE, XT_BUFSIZE(xt))
+ else
+ XT_BUFSIZE(xt) = imstati (im, IM_BUFSIZE)
+ nopen = nopen + 1
+ XT_CLOSEFD(xt) = YES
+ if (nopenpix < MAX_OPENPIX) {
+ XT_CLOSEFD(xt) = NO
+ nopenpix = nopenpix + 1
+ }
+ if (XT_CLOSEFD(xt) == YES)
+ call imseti (im, IM_CLOSEFD, YES)
+ XT_FLAG(xt) = flag
+
+ return (im)
+end
+
+
+# XT_CPIX -- Close image.
+
+procedure xt_cpix (index)
+
+int index #I index
+
+pointer xt
+errchk imunmap
+
+include "xtimmap.com"
+
+begin
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ if (xt == NULL)
+ return
+
+ if (XT_IM(xt) != NULL) {
+ if (VERBOSE) {
+ call eprintf ("%d: xt_cpix imunmap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ call imunmap (XT_IM(xt))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt) == NO)
+ nopenpix = nopenpix - 1
+ }
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+end
+
+
+# XT_IMSETI -- Set IMIO value.
+
+procedure xt_imseti (index, param, value)
+
+int index #I index
+int param #I IMSET parameter
+int value #I Value
+
+pointer xt
+bool streq()
+
+include "xtimmap.com"
+
+begin
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ if (xt == NULL) {
+ if (streq (param, "option"))
+ option = value
+ } else {
+ if (streq (param, "bufsize")) {
+ XT_BUFSIZE(xt) = value
+ if (XT_IM(xt) != NULL) {
+ call imseti (XT_IM(xt), IM_BUFFRAC, 0)
+ call imseti (XT_IM(xt), IM_BUFSIZE, value)
+ }
+ }
+ }
+end
+
+
+# XT_IMUNMAP -- Unmap indexed open image.
+# The header pointer is set to NULL to indicate the image has been closed.
+
+procedure xt_imunmap (im, index)
+
+int im #U IMIO header pointer
+int index #I index
+
+pointer xt
+errchk imunmap
+
+include "xtimmap.com"
+
+begin
+ # Check for an indexed image. If it is not unmap the pointer
+ # as a regular IMIO pointer.
+
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+ if (xt == NULL) {
+ if (im != NULL)
+ call imunmap (im)
+ return
+ }
+
+ # Close indexed image.
+ if (XT_IM(xt) != NULL) {
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imunmap imunmap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ iferr (call imunmap (XT_IM(xt))) {
+ XT_IM(xt) = NULL
+ call erract (EA_WARN)
+ }
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt) == NO)
+ nopenpix = nopenpix - 1
+ if (index == min_open)
+ min_open = 1
+ }
+
+ # Free any buffered memory.
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+
+ # Free header pointer. Note that if the supplied pointer is not
+ # header pointer then it is not set to NULL.
+ if (XT_HDR(xt) == im)
+ im = NULL
+ call mfree (XT_HDR(xt), TY_STRUCT)
+
+ # Free save structure.
+ call mfree (Memi[ims+index-1], TY_STRUCT)
+ Memi[ims+index-1] = NULL
+end
+
+
+# XT_MINHDR -- Minimize header assuming keywords will not be accessed.
+
+procedure xt_minhdr (index)
+
+int index #I index
+
+pointer xt
+errchk realloc
+
+include "xtimmap.com"
+
+begin
+ # Check for an indexed image. If it is not unmap the pointer
+ # as a regular IMIO pointer.
+
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+ if (xt == NULL)
+ return
+
+ # Minimize header pointer.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_minhdr %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ call realloc (XT_HDR(xt), IMU+1, TY_STRUCT)
+ if (XT_IM(xt) != NULL)
+ call realloc (XT_IM(xt), IMU+1, TY_STRUCT)
+end
+
+
+# XT_REINDEX -- Reindex open images.
+# This is used when some images are closed by xt_imunmap. It is up to
+# the calling program to reindex the header pointers and to subsequently
+# use the new index values.
+
+procedure xt_reindex ()
+
+int old, new
+
+include "xtimmap.com"
+
+begin
+ new = 0
+ do old = 0, nalloc-1 {
+ if (Memi[ims+old] == NULL)
+ next
+ Memi[ims+new] = Memi[ims+old]
+ new = new + 1
+ }
+ do old = new, nalloc-1
+ Memi[ims+old] = NULL
+end
+
+
+$for(sird)
+# XT_IMGNL -- Return the next line for the indexed image.
+# Possibly unmap another image if too many files are open.
+# Buffer data when an image is unmmaped to minimize the mapping of images.
+# If the requested index has not been mapped use the default pointer.
+
+int procedure xt_imgnl$t (imdef, index, buf, v, flag)
+
+pointer imdef #I Default pointer
+int index #I index
+pointer buf #O Data buffer
+long v[ARB] #I Line vector
+int flag #I Flag (=output line)
+
+int i, j, nc, nl, open(), imgnl$t(), sizeof(), imloop()
+pointer im, xt, xt1, ptr, immap(), imggs$t()
+errchk open, immap, imgnl$t, imggs$t, imunmap
+
+long unit_v[IM_MAXDIM]
+data unit_v /IM_MAXDIM * 1/
+
+include "xtimmap.com"
+
+begin
+ # Get index pointer.
+ xt = NULL
+ if (index <= nalloc && index > 0)
+ xt = Memi[ims+index-1]
+
+ # Use default pointer if index has not been mapped.
+ if (xt == NULL)
+ return (imgnl$t (imdef, buf, v))
+
+ # Close images not accessed during previous line.
+ # In normal usage this should only occur once per line over all
+ # indexed images.
+ if (flag != last_flag) {
+ do i = 1, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL || XT_FLAG(xt1) == last_flag)
+ next
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ call mfree (XT_BUF(xt1), XT_BTYPE(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ }
+
+ # Optimize the file I/O.
+ do i = nalloc, 1, -1 {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+ min_open = i
+ if (nopenpix < MAX_OPENPIX) {
+ if (XT_CLOSEFD(xt1) == NO)
+ next
+ XT_CLOSEFD(xt1) = NO
+ call imseti (im, IM_CLOSEFD, NO)
+ nopenpix = nopenpix + 1
+ }
+ }
+ last_flag = flag
+ }
+
+ # Use IMIO for already opened images.
+ im = XT_IM(xt)
+ if (im != NULL) {
+ XT_FLAG(xt) = flag
+ return (imgnl$t (im, buf, v))
+ }
+
+ # If the image is not currently mapped use the stored header.
+ im = XT_HDR(xt)
+
+ # Check for EOF.
+ i = IM_NDIM(im)
+ if (v[i] > IM_LEN(im,i))
+ return (EOF)
+
+ # Check for buffered data.
+ if (XT_BUF(xt) != NULL) {
+ if (v[2] >= XT_VS(xt,2) && v[2] <= XT_VE(xt,2)) {
+ if (XT_BTYPE(xt) != TY_PIXEL)
+ call error (1, "Cannot mix data types")
+ nc = IM_LEN(im,1)
+ buf = XT_BUF(xt) + (v[2]-XT_VS(xt,2)) * IM_LEN(im,1)
+ XT_FLAG(xt) = flag
+ if (i == 1)
+ v[1] = nc + 1
+ else
+ j = imloop (v, unit_v, IM_LEN(im,1), unit_v, i)
+ return (nc)
+ }
+ }
+
+ # Handle more images than the maximum that can be open at one time.
+ if (nopen >= max_openim) {
+ if (option == XT_MAPUNMAP || v[2] == 0) {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ im = XT_IM(xt1)
+ if (im == NULL)
+ next
+
+ # Buffer some number of lines.
+ nl = XT_BUFSIZE(xt1) / sizeof (TY_PIXEL) / IM_LEN(im,1)
+ if (nl > 1) {
+ nc = IM_LEN(im,1)
+ call amovl (v, XT_VS(xt1,1), IM_MAXDIM)
+ call amovl (v, XT_VE(xt1,1), IM_MAXDIM)
+ XT_VS(xt1,1) = 1
+ XT_VE(xt1,1) = nc
+ XT_VE(xt1,2) = min (XT_VS(xt1,2)+(nl-1), IM_LEN(im,2))
+ nl = XT_VE(xt1,2) - XT_VS(xt1,2) + 1
+ XT_BTYPE(xt1) = TY_PIXEL
+ call malloc (XT_BUF(xt1), nl*nc, XT_BTYPE(xt1))
+ ptr = imggs$t (im, XT_VS(xt1,1), XT_VE(xt1,1),
+ IM_NDIM(im))
+ call amov$t (Mem$t[ptr], Mem$t[XT_BUF(xt1)], nl*nc)
+ }
+
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl imunmap %s\n")
+ call pargi (i)
+ call pargstr (XT_IMNAME(xt1))
+ }
+ call imunmap (XT_IM(xt1))
+ nopen = nopen - 1
+ if (XT_CLOSEFD(xt1) == NO)
+ nopenpix = nopenpix - 1
+ min_open = i + 1
+ break
+ }
+ if (index <= min_open)
+ min_open = index
+ else {
+ do i = min_open, nalloc {
+ xt1 = Memi[ims+i-1]
+ if (xt1 == NULL)
+ next
+ if (XT_IM(xt1) == NULL)
+ next
+ min_open = i
+ break
+ }
+ }
+ } else {
+ # Check here because we can't catch error in immap.
+ i = open ("dev$null", READ_ONLY, BINARY_FILE)
+ call close (i)
+ if (i == LAST_FD - 1)
+ call error (SYS_FTOOMANYFILES, "Too many open files")
+ }
+ }
+
+ # Open image.
+ if (VERBOSE) {
+ call eprintf ("%d: xt_imgnl immap %s\n")
+ call pargi (index)
+ call pargstr (XT_IMNAME(xt))
+ }
+ im = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt))
+ XT_IM(xt) = im
+ call imseti (im, IM_BUFSIZE, XT_BUFSIZE(xt))
+ call mfree (XT_BUF(xt), XT_BTYPE(xt))
+ nopen = nopen + 1
+ XT_CLOSEFD(xt) = YES
+ if (nopenpix < MAX_OPENPIX) {
+ XT_CLOSEFD(xt) = NO
+ nopenpix = nopenpix + 1
+ }
+ if (XT_CLOSEFD(xt) == YES)
+ call imseti (im, IM_CLOSEFD, YES)
+ XT_FLAG(xt) = flag
+
+ return (imgnl$t (im, buf, v))
+end
+$endfor
diff --git a/pkg/images/immatch/src/imcombine/src/xtprocid.x b/pkg/images/immatch/src/imcombine/src/xtprocid.x
new file mode 100644
index 00000000..0a82d81b
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/src/xtprocid.x
@@ -0,0 +1,38 @@
+# XT_PROCID -- Set or ppdate PROCID keyword.
+
+procedure xt_procid (im)
+
+pointer im #I Image header
+
+int i, j, ver, patmake(), gpatmatch(), strlen(), ctoi()
+pointer sp, pat, str
+
+begin
+ call smark (sp)
+ call salloc (pat, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get current ID.
+ iferr (call imgstr (im, "PROCID", Memc[str], SZ_LINE)) {
+ iferr (call imgstr (im, "OBSID", Memc[str], SZ_LINE)) {
+ call sfree (sp)
+ return
+ }
+ }
+
+ # Set new PROCID.
+ ver = 0
+ i = patmake ("V[0-9]*$", Memc[pat], SZ_LINE)
+ if (gpatmatch (Memc[str], Memc[pat], i, j) == 0)
+ ;
+ if (j > 0) {
+ j = i+1
+ if (ctoi (Memc[str], j, ver) == 0)
+ ver = 0
+ i = i - 1
+ } else
+ i = strlen (Memc[str])
+ call sprintf (Memc[str+i], SZ_LINE, "V%d")
+ call pargi (ver+1)
+ call imastr (im, "PROCID", Memc[str])
+end
diff --git a/pkg/images/immatch/src/imcombine/t_imcombine.x b/pkg/images/immatch/src/imcombine/t_imcombine.x
new file mode 100644
index 00000000..d3774958
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/t_imcombine.x
@@ -0,0 +1,230 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <mach.h>
+include <imhdr.h>
+include "src/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, fname, output, headers, bmask, rmask, sigma, nrmask, emask, logfile
+pointer scales, zeros, wts, im
+int n, input, ilist, olist, hlist, blist, rlist, slist, nrlist, elist
+
+bool clgetb()
+real clgetr()
+int clgwrd(), clgeti(), imtopenp(), imtopen(), imtgetim(), imtlen()
+pointer immap()
+errchk immap, icombine
+
+include "src/icombine.com"
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (headers, SZ_FNAME, TY_CHAR)
+ call salloc (bmask, SZ_FNAME, TY_CHAR)
+ call salloc (rmask, SZ_FNAME, TY_CHAR)
+ call salloc (nrmask, SZ_FNAME, TY_CHAR)
+ call salloc (emask, SZ_FNAME, TY_CHAR)
+ call salloc (sigma, SZ_FNAME, TY_CHAR)
+ call salloc (expkeyword, SZ_FNAME, TY_CHAR)
+ call salloc (statsec, 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")
+ hlist = imtopenp ("headers")
+ blist = imtopenp ("bpmasks")
+ rlist = imtopenp ("rejmasks")
+ nrlist = imtopenp ("nrejmasks")
+ elist = imtopenp ("expmasks")
+ slist = imtopenp ("sigmas")
+ call clgstr ("logfile", Memc[logfile], SZ_FNAME)
+
+ project = clgetb ("project")
+ combine = clgwrd ("combine", Memc[fname], SZ_FNAME, COMBINE)
+ if (combine == MEDIAN || combine == LMEDIAN) {
+ if (combine == MEDIAN)
+ medtype = MEDAVG
+ else {
+ medtype = MEDLOW
+ combine = MEDIAN
+ }
+ }
+ reject = clgwrd ("reject", Memc[fname], SZ_FNAME, REJECT)
+ blank = clgetr ("blank")
+ call clgstr ("expname", Memc[expkeyword], SZ_FNAME)
+ call clgstr ("statsec", Memc[statsec], SZ_FNAME)
+ 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")
+ verbose = false
+
+ # 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 output images")
+ if (imtlen (hlist) != 0 && imtlen (hlist) != n)
+ call error (1, "Wrong number of header files")
+ if (imtlen (blist) != 0 && imtlen (blist) != n)
+ call error (1, "Wrong number of bad pixel masks")
+ if (imtlen (rlist) != 0 && imtlen (rlist) != n)
+ call error (1, "Wrong number of rejection masks")
+ if (imtlen (nrlist) > 0 && imtlen (nrlist) != n)
+ call error (1, "Wrong number of number rejected masks")
+ if (imtlen (elist) > 0 && imtlen (elist) != n)
+ call error (1, "Wrong number of exposure masks")
+ if (imtlen (slist) > 0 && imtlen (slist) != n)
+ call error (1, "Wrong number of sigma images")
+ } else {
+ if (imtlen (olist) != 1)
+ call error (1, "Wrong number of output images")
+ if (imtlen (hlist) > 1)
+ call error (1, "Wrong number of header files")
+ if (imtlen (blist) > 1)
+ call error (1, "Wrong number of bad pixel masks")
+ if (imtlen (rlist) > 1)
+ call error (1, "Wrong number of rejection masks")
+ if (imtlen (nrlist) > 1)
+ call error (1, "Wrong number of number rejected masks")
+ if (imtlen (elist) > 1)
+ call error (1, "Wrong number of exposure masks")
+ if (imtlen (slist) > 1)
+ call error (1, "Wrong number of sigma images")
+ }
+
+ # 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.
+ while (imtgetim (ilist, Memc[fname], SZ_FNAME) != EOF) {
+ iferr {
+ scales = NULL; input = ilist
+
+ if (imtgetim (olist, Memc[output], SZ_FNAME) == EOF) {
+ if (project) {
+ call sprintf (Memc[output], SZ_FNAME,
+ "IMCOMBINE: No output image for %s")
+ call pargstr (Memc[fname])
+ call error (1, Memc[output])
+ } else
+ call error (1, "IMCOMBINE: No output image")
+ }
+ if (imtgetim (hlist, Memc[headers], SZ_FNAME) == EOF)
+ Memc[headers] = EOS
+ if (imtgetim (blist, Memc[bmask], SZ_FNAME) == EOF)
+ Memc[bmask] = EOS
+ if (imtgetim (rlist, Memc[rmask], SZ_FNAME) == EOF)
+ Memc[rmask] = EOS
+ if (imtgetim (nrlist, Memc[nrmask], SZ_FNAME) == EOF)
+ Memc[nrmask] = EOS
+ if (imtgetim (elist, Memc[emask], SZ_FNAME) == EOF)
+ Memc[emask] = EOS
+ if (imtgetim (slist, Memc[sigma], SZ_FNAME) == EOF)
+ Memc[sigma] = EOS
+
+ # Set the input list and initialize the scaling factors.
+ if (project) {
+ im = immap (Memc[fname], READ_ONLY, 0)
+ if (IM_NDIM(im) == 1)
+ n = 0
+ else
+ n = IM_LEN(im,IM_NDIM(im))
+ call imunmap (im)
+ if (n == 0) {
+ call sprintf (Memc[output], SZ_FNAME,
+ "IMCOMBINE: Can't project one dimensional image %s")
+ call pargstr (Memc[fname])
+ call error (1, Memc[output])
+ }
+ input = imtopen (Memc[fname])
+ } else {
+ call imtrew (ilist)
+ n = imtlen (ilist)
+ input = ilist
+ }
+
+ # Allocate and initialize scaling factors.
+ call malloc (scales, 3*n, TY_REAL)
+ zeros = scales + n
+ wts = scales + 2 * n
+ call amovkr (INDEFR, Memr[scales], 3*n)
+
+ call icombine (input, Memc[output], Memc[headers], Memc[bmask],
+ Memc[rmask], Memc[nrmask], Memc[emask], Memc[sigma],
+ Memc[logfile], Memr[scales], Memr[zeros], Memr[wts],
+ NO, NO, NO)
+
+ } then
+ call erract (EA_WARN)
+
+ if (input != ilist)
+ call imtclose (input)
+ call mfree (scales, TY_REAL)
+ if (!project)
+ break
+ }
+
+ call imtclose (ilist)
+ call imtclose (olist)
+ call imtclose (hlist)
+ call imtclose (blist)
+ call imtclose (rlist)
+ call imtclose (nrlist)
+ call imtclose (elist)
+ call imtclose (slist)
+ call sfree (sp)
+end
diff --git a/pkg/images/immatch/src/imcombine/x_imcombine.x b/pkg/images/immatch/src/imcombine/x_imcombine.x
new file mode 100644
index 00000000..a85e34f6
--- /dev/null
+++ b/pkg/images/immatch/src/imcombine/x_imcombine.x
@@ -0,0 +1 @@
+task imcombine = t_imcombine