diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
commit | fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch) | |
tree | bdda434976bc09c864f2e4fa6f16ba1952b1e555 /pkg/proto/masks | |
download | iraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz |
Initial commit
Diffstat (limited to 'pkg/proto/masks')
-rw-r--r-- | pkg/proto/masks/mimstat.h | 67 | ||||
-rw-r--r-- | pkg/proto/masks/mimstat.x | 943 | ||||
-rw-r--r-- | pkg/proto/masks/mkpkg | 23 | ||||
-rw-r--r-- | pkg/proto/masks/mptools.x | 468 | ||||
-rw-r--r-- | pkg/proto/masks/mstcache.x | 100 | ||||
-rw-r--r-- | pkg/proto/masks/rsfnames.x | 549 | ||||
-rw-r--r-- | pkg/proto/masks/rskysub.h | 32 | ||||
-rw-r--r-- | pkg/proto/masks/rsmean.x | 1172 | ||||
-rw-r--r-- | pkg/proto/masks/rsmmean.x | 1673 | ||||
-rw-r--r-- | pkg/proto/masks/rsreject.x | 1220 | ||||
-rw-r--r-- | pkg/proto/masks/rsscache.x | 123 | ||||
-rw-r--r-- | pkg/proto/masks/rsstats.x | 492 | ||||
-rw-r--r-- | pkg/proto/masks/t_mimstat.x | 363 | ||||
-rw-r--r-- | pkg/proto/masks/t_mimstat.xBAK | 366 | ||||
-rw-r--r-- | pkg/proto/masks/t_rskysub.x | 248 |
15 files changed, 7839 insertions, 0 deletions
diff --git a/pkg/proto/masks/mimstat.h b/pkg/proto/masks/mimstat.h new file mode 100644 index 00000000..95bef65e --- /dev/null +++ b/pkg/proto/masks/mimstat.h @@ -0,0 +1,67 @@ +# Header file for the IMSTATMISTICS task. + +define LEN_MIMSTAT 20 + +define MIS_SUMX Memd[P2D($1)] +define MIS_SUMX2 Memd[P2D($1+2)] +define MIS_SUMX3 Memd[P2D($1+4)] +define MIS_SUMX4 Memd[P2D($1+6)] +define MIS_LO Memr[P2R($1+8)] +define MIS_HI Memr[P2R($1+9)] +define MIS_MIN Memr[P2R($1+10)] +define MIS_MAX Memr[P2R($1+11)] +define MIS_MEAN Memr[P2R($1+12)] +define MIS_MEDIAN Memr[P2R($1+13)] +define MIS_MODE Memr[P2R($1+14)] +define MIS_STDDEV Memr[P2R($1+15)] +define MIS_SKEW Memr[P2R($1+16)] +define MIS_KURTOSIS Memr[P2R($1+17)] +define MIS_NPIX Memi[$1+18] +define MIS_SW Memi[$1+19] + +define LEN_NSWITCHES 8 + +define MIS_SKURTOSIS Memi[$1] +define MIS_SSKEW Memi[$1+1] +define MIS_SSTDDEV Memi[$1+2] +define MIS_SMODE Memi[$1+3] +define MIS_SMEDIAN Memi[$1+4] +define MIS_SMEAN Memi[$1+5] +define MIS_SMINMAX Memi[$1+6] +define MIS_SNPIX Memi[$1+7] + +define MIS_FIELDS "|image|npix|min|max|mean|midpt|mode|stddev|skew|kurtosis|mask|" +define MIS_NFIELDS 11 + +define IS_FIELDS "|image|npix|min|max|mean|midpt|mode|stddev|skew|kurtosis|" + +define IS_NFIELDS 10 + +define MIS_KIMAGE "IMAGE" +define MIS_KNPIX "NPIX" +define MIS_KMIN "MIN" +define MIS_KMAX "MAX" +define MIS_KMEAN "MEAN" +define MIS_KMEDIAN "MIDPT" +define MIS_KMODE "MODE" +define MIS_KSTDDEV "STDDEV" +define MIS_KSKEW "SKEW" +define MIS_KKURTOSIS "KURTOSIS" +define MIS_KMASK "MASK" + +define MIS_FIMAGE 1 +define MIS_FNPIX 2 +define MIS_FMIN 3 +define MIS_FMAX 4 +define MIS_FMEAN 5 +define MIS_FMEDIAN 6 +define MIS_FMODE 7 +define MIS_FSTDDEV 8 +define MIS_FSKEW 9 +define MIS_FKURTOSIS 10 +define MIS_FMASK 11 + +define MIS_FCOLUMN "%10d" +define MIS_FINTEGER "%10d" +define MIS_FREAL "%10.4g" +define MIS_FSTRING "%20s" diff --git a/pkg/proto/masks/mimstat.x b/pkg/proto/masks/mimstat.x new file mode 100644 index 00000000..9207ef66 --- /dev/null +++ b/pkg/proto/masks/mimstat.x @@ -0,0 +1,943 @@ +include <mach.h> +include "mimstat.h" + + +# MST_ALLOCATE -- Allocate space for the statistics structure. + +procedure mst_allocate (mst) + +pointer mst #O the statistics descriptor + +begin + call calloc (mst, LEN_MIMSTAT, TY_STRUCT) + call malloc (MIS_SW(mst), LEN_NSWITCHES, TY_INT) +end + + +# MST_FREE -- Free the statistics structure. + +procedure mst_free (mst) + +pointer mst #O the statistics descriptor + +begin + call mfree (MIS_SW(mst), TY_INT) + call mfree (mst, TY_STRUCT) +end + + +# MST_FIELDS -- Procedure to decode the fields string into a list of the +# fields to be computed and printed. + +int procedure mst_fields (fieldstr, fields, max_nfields) + +char fieldstr[ARB] #I string containing the list of fields +int fields[ARB] #O fields array +int max_nfields #I maximum number of fields + +int nfields, flist, field +pointer sp, fname +int fntopnb(), fntgfnb(), strdic() + +begin + nfields = 0 + + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + + flist = fntopnb (fieldstr, NO) + while (fntgfnb (flist, Memc[fname], SZ_FNAME) != EOF && + (nfields < max_nfields)) { + field = strdic (Memc[fname], Memc[fname], SZ_FNAME, MIS_FIELDS) + if (field == 0) + next + nfields = nfields + 1 + fields[nfields] = field + } + call fntclsb (flist) + + call sfree (sp) + + return (nfields) +end + + +# MST_SWITCHES -- Set the processing switches. + +procedure mst_switches (mst, fields, nfields, nclip) + +pointer mst #I the statistics pointer +int fields[ARB] #I fields array +int nfields #I maximum number of fields +int nclip #I the number of clipping iterations + +pointer sw +int mst_isfield() + +begin + # Initialize. + sw = MIS_SW(mst) + call amovki (NO, Memi[sw], LEN_NSWITCHES) + + # Set the computation switches. + MIS_SNPIX(sw) = mst_isfield (MIS_FNPIX, fields, nfields) + MIS_SMEAN(sw) = mst_isfield (MIS_FMEAN, fields, nfields) + MIS_SMEDIAN(sw) = mst_isfield (MIS_FMEDIAN, fields, nfields) + MIS_SMODE(sw) = mst_isfield (MIS_FMODE, fields, nfields) + if (nclip > 0) + MIS_SSTDDEV(sw) = YES + else + MIS_SSTDDEV(sw) = mst_isfield (MIS_FSTDDEV, fields, nfields) + MIS_SSKEW(sw) = mst_isfield (MIS_FSKEW, fields, nfields) + MIS_SKURTOSIS(sw) = mst_isfield (MIS_FKURTOSIS, fields, nfields) + + # Adjust the computation switches. + if (mst_isfield (MIS_FMIN, fields, nfields) == YES) + MIS_SMINMAX(sw) = YES + else if (mst_isfield (MIS_FMAX, fields, nfields) == YES) + MIS_SMINMAX(sw) = YES + else if (MIS_SMEDIAN(sw) == YES || MIS_SMODE(sw) == YES) + MIS_SMINMAX(sw) = YES + else + MIS_SMINMAX(sw) = NO +end + + +# MST_PHEADER -- Print the banner fields. + +procedure mst_pheader (fields, nfields) + +int fields[ARB] # fields to be printed +int nfields # number of fields + +int i + +begin + call printf ("#") + do i = 1, nfields { + switch (fields[i]) { + case MIS_FIMAGE: + call printf (MIS_FSTRING) + call pargstr (MIS_KIMAGE) + case MIS_FMASK: + call printf (MIS_FSTRING) + call pargstr (MIS_KMASK) + case MIS_FNPIX: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KNPIX) + case MIS_FMIN: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KMIN) + case MIS_FMAX: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KMAX) + case MIS_FMEAN: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KMEAN) + case MIS_FMEDIAN: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KMEDIAN) + case MIS_FMODE: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KMODE) + case MIS_FSTDDEV: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KSTDDEV) + case MIS_FSKEW: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KSKEW) + case MIS_FKURTOSIS: + call printf (MIS_FCOLUMN) + call pargstr (MIS_KKURTOSIS) + } + } + + call printf ("\n") + call flush (STDOUT) +end + + +# MST_ISFIELD -- Procedure to determine whether a specified field is one +# of the selected fields or not. + +int procedure mst_isfield (field, fields, nfields) + +int field #I field to be tested +int fields[ARB] #I array of selected fields +int nfields #I number of fields + +int i, isfield + +begin + isfield = NO + do i = 1, nfields { + if (field != fields[i]) + next + isfield = YES + break + } + + return (isfield) +end + + +# MST_INITIALIZE -- Initialize the statistics computation. + +procedure mst_initialize (mst, lower, upper) + +pointer mst #I pointer to the statistics structure +real lower #I lower good data limit +real upper #I upper good data limit + +begin + if (IS_INDEFR(lower)) + MIS_LO(mst) = -MAX_REAL + else + MIS_LO(mst) = lower + if (IS_INDEFR(upper)) + MIS_HI(mst) = MAX_REAL + else + MIS_HI(mst) = upper + + MIS_NPIX(mst) = 0 + MIS_SUMX(mst) = 0.0d0 + MIS_SUMX2(mst) = 0.0d0 + MIS_SUMX3(mst) = 0.0d0 + MIS_SUMX4(mst) = 0.0d0 + + MIS_MIN(mst) = MAX_REAL + MIS_MAX(mst) = -MAX_REAL + MIS_MEAN(mst) = INDEFR + MIS_MEDIAN(mst) = INDEFR + MIS_MODE(mst) = INDEFR + MIS_STDDEV(mst) = INDEFR + MIS_SKEW(mst) = INDEFR + MIS_KURTOSIS(mst) = INDEFR +end + + +# MST_ACCUMULATE4 -- Accumulate sums up to the fourth power of the data for +# data values between lower and upper. + +procedure mst_accumulate4 (mst, x, npts, lower, upper, minmax) + +pointer mst #I pointer to the statistics structure +real x[ARB] #I the data array +int npts #I the number of data points +real lower #I lower data boundary +real upper #I upper data boundary +int minmax #I compute the minimum and maximum ? + +double xx, xx2, sumx, sumx2, sumx3, sumx4 +real lo, hi, xmin, xmax +int i, npix + +begin + lo = MIS_LO(mst) + hi = MIS_HI(mst) + npix = MIS_NPIX(mst) + sumx = 0.0 + sumx2 = 0.0 + sumx3 = 0.0 + sumx4 = 0.0 + xmin = MIS_MIN(mst) + xmax = MIS_MAX(mst) + + if (IS_INDEFR(lower) && IS_INDEFR(upper)) { + npix = npix + npts + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + sumx4 = sumx4 + xx2 * xx2 + } + } else { + do i = 1, npts { + xx = x[i] + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + sumx4 = sumx4 + xx2 * xx2 + } + } + } else { + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + npix = npix + 1 + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + sumx4 = sumx4 + xx2 * xx2 + } + } else { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + npix = npix + 1 + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + sumx4 = sumx4 + xx2 * xx2 + } + } + } + + MIS_NPIX(mst) = npix + MIS_SUMX(mst) = MIS_SUMX(mst) + sumx + MIS_SUMX2(mst) = MIS_SUMX2(mst) + sumx2 + MIS_SUMX3(mst) = MIS_SUMX3(mst) + sumx3 + MIS_SUMX4(mst) = MIS_SUMX4(mst) + sumx4 + MIS_MIN(mst) = xmin + MIS_MAX(mst) = xmax +end + + +# MST_ACCUMULATE3 -- Accumulate sums up to the third power of the data for +# data values between lower and upper. + +procedure mst_accumulate3 (mst, x, npts, lower, upper, minmax) + +pointer mst #I pointer to the statistics structure +real x[ARB] #I the data array +int npts #I the number of data points +real lower #I lower data boundary +real upper #I upper data boundary +int minmax #I compute the minimum and maximum ? + +double xx, xx2, sumx, sumx2, sumx3 +real lo, hi, xmin, xmax +int i, npix + +begin + lo = MIS_LO(mst) + hi = MIS_HI(mst) + npix = MIS_NPIX(mst) + sumx = 0.0 + sumx2 = 0.0 + sumx3 = 0.0 + xmin = MIS_MIN(mst) + xmax = MIS_MAX(mst) + + if (IS_INDEFR(lower) && IS_INDEFR(upper)) { + npix = npix + npts + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + } + } else { + do i = 1, npts { + xx = x[i] + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + } + } + } else { + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + npix = npix + 1 + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + } + } else { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + npix = npix + 1 + xx2 = xx * xx + sumx = sumx + xx + sumx2 = sumx2 + xx2 + sumx3 = sumx3 + xx2 * xx + } + } + } + + MIS_NPIX(mst) = npix + MIS_SUMX(mst) = MIS_SUMX(mst) + sumx + MIS_SUMX2(mst) = MIS_SUMX2(mst) + sumx2 + MIS_SUMX3(mst) = MIS_SUMX3(mst) + sumx3 + MIS_MIN(mst) = xmin + MIS_MAX(mst) = xmax +end + + +# MST_ACCUMULATE2 -- Accumulate sums up to the second power of the data for +# data values between lower and upper. + +procedure mst_accumulate2 (mst, x, npts, lower, upper, minmax) + +pointer mst #I pointer to the statistics structure +real x[ARB] #I the data array +int npts #I the number of data points +real lower #I lower data boundary +real upper #I upper data boundary +int minmax #I compute the minimum and maximum ? + +double xx, sumx, sumx2 +real lo, hi, xmin, xmax +int i, npix + +begin + lo = MIS_LO(mst) + hi = MIS_HI(mst) + npix = MIS_NPIX(mst) + sumx = 0.0 + sumx2 = 0.0 + xmin = MIS_MIN(mst) + xmax = MIS_MAX(mst) + + if (IS_INDEFR(lower) && IS_INDEFR(upper)) { + npix = npix + npts + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + sumx = sumx + xx + sumx2 = sumx2 + xx * xx + } + } else { + do i = 1, npts { + xx = x[i] + sumx = sumx + xx + sumx2 = sumx2 + xx * xx + } + } + } else { + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + npix = npix + 1 + sumx = sumx + xx + sumx2 = sumx2 + xx * xx + } + } else { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + npix = npix + 1 + sumx = sumx + xx + sumx2 = sumx2 + xx * xx + } + } + } + + MIS_NPIX(mst) = npix + MIS_SUMX(mst) = MIS_SUMX(mst) + sumx + MIS_SUMX2(mst) = MIS_SUMX2(mst) + sumx2 + MIS_MIN(mst) = xmin + MIS_MAX(mst) = xmax +end + + +# MST_ACCUMULATE1 -- Accumulate sums up to the first power of the data for +# data values between lower and upper. + +procedure mst_accumulate1 (mst, x, npts, lower, upper, minmax) + +pointer mst #I pointer to the statistics structure +real x[ARB] #I the data array +int npts #I the number of data points +real lower #I lower data boundary +real upper #I upper data boundary +int minmax #I compute the minimum and maximum ? + +double sumx +real lo, hi, xx, xmin, xmax +int i, npix + +begin + lo = MIS_LO(mst) + hi = MIS_HI(mst) + npix = MIS_NPIX(mst) + sumx = 0.0 + xmin = MIS_MIN(mst) + xmax = MIS_MAX(mst) + + if (IS_INDEFR(lower) && IS_INDEFR(upper)) { + npix = npix + npts + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + sumx = sumx + xx + } + } else { + do i = 1, npts + sumx = sumx + x[i] + } + } else { + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + npix = npix + 1 + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + sumx = sumx + xx + } + } else { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + npix = npix + 1 + sumx = sumx + xx + } + } + } + + MIS_NPIX(mst) = npix + MIS_SUMX(mst) = MIS_SUMX(mst) + sumx + MIS_MIN(mst) = xmin + MIS_MAX(mst) = xmax +end + + +# MST_ACCUMULATE0 -- Accumulate sums up to the 0th power of the data for +# data values between lower and upper. + +procedure mst_accumulate0 (mst, x, npts, lower, upper, minmax) + +pointer mst #I pointer to the statistics structure +real x[ARB] #I the data array +int npts #I the number of data points +real lower #I lower data boundary +real upper #I upper data boundary +int minmax #I compute the minimum and maximum ? + +int i, npix +real lo, hi, xx, xmin, xmax + +begin + lo = MIS_LO(mst) + hi = MIS_HI(mst) + npix = MIS_NPIX(mst) + xmin = MIS_MIN(mst) + xmax = MIS_MAX(mst) + + if (IS_INDEFR(lower) && IS_INDEFR(upper)) { + npix = npix + npts + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + } + } + } else { + if (minmax == YES) { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + npix = npix + 1 + if (xx < xmin) + xmin = xx + if (xx > xmax) + xmax = xx + } + } else { + do i = 1, npts { + xx = x[i] + if (xx < lo || xx > hi) + next + npix = npix + 1 + } + } + } + + MIS_NPIX(mst) = npix + MIS_MIN(mst) = xmin + MIS_MAX(mst) = xmax +end + + +# MST_STATS -- Procedure to compute the first four central moments of the +# distribution. + +procedure mst_stats (mst) + +pointer mst #I statistics structure + +double mean, var, stdev +pointer sw +bool fp_equalr() + +begin + sw = MIS_SW(mst) + + # Compute the basic statistics regardless of the switches. + if (fp_equalr (MIS_MIN(mst), MAX_REAL)) + MIS_MIN(mst) = INDEFR + if (fp_equalr (MIS_MAX(mst), -MAX_REAL)) + MIS_MAX(mst) = INDEFR + if (MIS_NPIX(mst) <= 0) + return + + mean = MIS_SUMX(mst) / MIS_NPIX(mst) + MIS_MEAN(mst) = mean + if (MIS_NPIX(mst) < 2) + return + + var = (MIS_SUMX2(mst) - MIS_SUMX(mst) * mean) / + (MIS_NPIX(mst) - 1) + if (var <= 0.0) { + MIS_STDDEV(mst) = 0.0 + return + } else { + stdev = sqrt (var) + MIS_STDDEV(mst) = stdev + } + + # Compute higher order moments if the switches are set. + if (MIS_SSKEW(sw)== YES) + MIS_SKEW(mst) = (MIS_SUMX3(mst) - 3.0d0 * MIS_MEAN(mst) * + MIS_SUMX2(mst) + 3.0d0 * mean * mean * + MIS_SUMX(mst) - MIS_NPIX(mst) * mean ** 3) / + MIS_NPIX(mst) / stdev / stdev / stdev + + if (MIS_SKURTOSIS(sw) == YES) + MIS_KURTOSIS(mst) = (MIS_SUMX4(mst) - 4.0d0 * mean * + MIS_SUMX3(mst) + 6.0d0 * mean * mean * + MIS_SUMX2(mst) - 4.0 * mean ** 3 * MIS_SUMX(mst) + + MIS_NPIX(mst) * mean ** 4) / MIS_NPIX(mst) / + stdev / stdev / stdev / stdev - 3.0d0 +end + + + +# MST_IHIST -- Initilaize the histogram of the image pixels. + +int procedure mst_ihist (mst, binwidth, hgm, nbins, hwidth, hmin, hmax) + +pointer mst #I pointer to the statistics structure +real binwidth #I histogram bin width in sigma +pointer hgm #O pointer to the histogram +int nbins #O number of bins +real hwidth #O histogram resolution +real hmin #O minimum histogram value +real hmax #O maximum histogram value + +begin + nbins = 0 + if (binwidth <= 0.0) + return (NO) + + hwidth = binwidth * MIS_STDDEV(mst) + if (hwidth <= 0.0) + return (NO) + + nbins = (MIS_MAX(mst) - MIS_MIN(mst)) / hwidth + 1 + if (nbins < 3) + return (NO) + + hmin = MIS_MIN(mst) + hmax = MIS_MAX(mst) + + call malloc (hgm, nbins, TY_INT) + + return (YES) +end + + +# MST_HMEDIAN -- Estimate the median from the histogram. + +procedure mst_hmedian (mst, hgm, nbins, hwidth, hmin, hmax) + +pointer mst #I pointer to the statistics structure +int hgm[ARB] #I histogram of the pixels +int nbins #I number of bins in the histogram +real hwidth #I resolution of the histogram +real hmin #I minimum histogram value +real hmax #I maximum histogram value + +real h1, hdiff, hnorm +pointer sp, ihgm +int i, lo, hi + +bool fp_equalr() + +begin + call smark (sp) + call salloc (ihgm, nbins, TY_REAL) + + # Integrate the histogram and normalize. + Memr[ihgm] = hgm[1] + do i = 2, nbins + Memr[ihgm+i-1] = hgm[i] + Memr[ihgm+i-2] + hnorm = Memr[ihgm+nbins-1] + call adivkr (Memr[ihgm], hnorm, Memr[ihgm], nbins) + + # Initialize the low and high bin numbers. + lo = 0 + hi = 1 + + # Search for the point which divides the integral in half. + do i = 1, nbins { + if (Memr[ihgm+i-1] > 0.5) + break + lo = i + } + hi = lo + 1 + + # Approximate the median. + h1 = hmin + lo * hwidth + if (lo == 0) + hdiff = Memr[ihgm+hi-1] + else + hdiff = Memr[ihgm+hi-1] - Memr[ihgm+lo-1] + if (fp_equalr (hdiff, 0.0)) + MIS_MEDIAN(mst) = h1 + else if (lo == 0) + MIS_MEDIAN(mst) = h1 + 0.5 / hdiff * hwidth + else + MIS_MEDIAN(mst) = h1 + (0.5 - Memr[ihgm+lo-1]) / hdiff * hwidth + + call sfree (sp) +end + + +# MST_HMODE -- Procedure to compute the mode. + +procedure mst_hmode (mst, hgm, nbins, hwidth, hmin, hmax) + +pointer mst #I pointer to the statistics strucuture +int hgm[ARB] #I histogram of the pixels +int nbins #I number of bins in the histogram +real hwidth #I resolution of the histogram +real hmin #I minimum histogram value +real hmax #I maximum histogram value + +int i, bpeak +real hpeak, dh1, dh2, denom +bool fp_equalr() + +begin + # If there is a single bin return the midpoint of that bin. + if (nbins == 1) { + MIS_MODE(mst) = hmin + 0.5 * hwidth + return + } + + # If there are two bins return the midpoint of the greater bin. + if (nbins == 2) { + if (hgm[1] > hgm[2]) + MIS_MODE(mst) = hmin + 0.5 * hwidth + else if (hgm[2] > hgm[1]) + MIS_MODE(mst) = hmin + 1.5 * hwidth + else + MIS_MODE(mst) = hmin + hwidth + return + } + + # Find the bin containing the histogram maximum. + hpeak = hgm[1] + bpeak = 1 + do i = 2, nbins { + if (hgm[i] > hpeak) { + hpeak = hgm[i] + bpeak = i + } + } + + # If the maximum is in the first bin return the midpoint of the bin. + if (bpeak == 1) { + MIS_MODE(mst) = hmin + 0.5 * hwidth + return + } + + # If the maximum is in the last bin return the midpoint of the bin. + if (bpeak == nbins) { + MIS_MODE(mst) = hmin + (nbins - 0.5) * hwidth + return + } + + # Compute the lower limit of bpeak. + bpeak = bpeak - 1 + + # Do a parabolic interpolation to find the peak. + dh1 = hgm[bpeak+1] - hgm[bpeak] + dh2 = hgm[bpeak+1] - hgm[bpeak+2] + denom = dh1 + dh2 + if (fp_equalr (denom, 0.0)) { + MIS_MODE(mst) = hmin + (bpeak + 0.5) * hwidth + } else { + MIS_MODE(mst) = bpeak + 1 + 0.5 * (dh1 - dh2) / denom + MIS_MODE(mst) = hmin + (MIS_MODE(mst) - 0.5) * hwidth + } + + #dh1 = hgm[bpeak] * (hmin + (bpeak - 0.5) * hwidth) + + #hgm[bpeak+1] * (hmin + (bpeak + 0.5) * hwidth) + + #hgm[bpeak+2] * (hmin + (bpeak + 1.5) * hwidth) + #dh2 = hgm[bpeak] + hgm[bpeak+1] + hgm[bpeak+2] +end + + +# MST_PRINT -- Print the fields using builtin format strings. + +procedure mst_print (image, mask, mst, fields, nfields) + +char image[ARB] #I image name +char mask[ARB] #I mask name +pointer mst #I pointer to the statistics structure +int fields[ARB] #I fields to be printed +int nfields #I number of fields + +int i + +begin + call printf (" ") + do i = 1, nfields { + switch (fields[i]) { + case MIS_FIMAGE: + call printf (MIS_FSTRING) + call pargstr (image) + case MIS_FMASK: + call printf (MIS_FSTRING) + call pargstr (mask) + case MIS_FNPIX: + call printf (MIS_FINTEGER) + call pargi (MIS_NPIX(mst)) + case MIS_FMIN: + call printf (MIS_FREAL) + call pargr (MIS_MIN(mst)) + case MIS_FMAX: + call printf (MIS_FREAL) + call pargr (MIS_MAX(mst)) + case MIS_FMEAN: + call printf (MIS_FREAL) + call pargr (MIS_MEAN(mst)) + case MIS_FMEDIAN: + call printf (MIS_FREAL) + call pargr (MIS_MEDIAN(mst)) + case MIS_FMODE: + call printf (MIS_FREAL) + call pargr (MIS_MODE(mst)) + case MIS_FSTDDEV: + call printf (MIS_FREAL) + call pargr (MIS_STDDEV(mst)) + case MIS_FSKEW: + call printf (MIS_FREAL) + call pargr (MIS_SKEW(mst)) + case MIS_FKURTOSIS: + call printf (MIS_FREAL) + call pargr (MIS_KURTOSIS(mst)) + } + } + + call printf ("\n") + call flush (STDOUT) +end + + +# MST_FPRINT -- Print the fields using a free format. + +procedure mst_fprint (image, mask, mst, fields, nfields) + +char image[ARB] #I image name +char mask[ARB] #I mask name +pointer mst #I pointer to the statistics structure +int fields[ARB] #I fields to be printed +int nfields #I number of fields + +int i + +begin + do i = 1, nfields { + switch (fields[i]) { + case MIS_FIMAGE: + call printf ("%s") + call pargstr (image) + case MIS_FMASK: + call printf ("%s") + call pargstr (mask) + case MIS_FNPIX: + call printf ("%d") + call pargi (MIS_NPIX(mst)) + case MIS_FMIN: + call printf ("%g") + call pargr (MIS_MIN(mst)) + case MIS_FMAX: + call printf ("%g") + call pargr (MIS_MAX(mst)) + case MIS_FMEAN: + call printf ("%g") + call pargr (MIS_MEAN(mst)) + case MIS_FMEDIAN: + call printf ("%g") + call pargr (MIS_MEDIAN(mst)) + case MIS_FMODE: + call printf ("%g") + call pargr (MIS_MODE(mst)) + case MIS_FSTDDEV: + call printf ("%g") + call pargr (MIS_STDDEV(mst)) + case MIS_FSKEW: + call printf ("%g") + call pargr (MIS_SKEW(mst)) + case MIS_FKURTOSIS: + call printf ("%g") + call pargr (MIS_KURTOSIS(mst)) + } + if (i < nfields) + call printf (" ") + } + + call printf ("\n") + call flush (STDOUT) +end diff --git a/pkg/proto/masks/mkpkg b/pkg/proto/masks/mkpkg new file mode 100644 index 00000000..21db5803 --- /dev/null +++ b/pkg/proto/masks/mkpkg @@ -0,0 +1,23 @@ +# Make the protype masks tasks MIMSTAT + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +libpkg.a: + t_mimstat.x <mach.h> <imhdr.h> <imset.h> <pmset.h> "mimstat.h" + mstcache.x <imhdr.h> <imset.h> + + t_rskysub.x <imhdr.h> "rskysub.h" + rsstats.x <mach.h> <imhdr.h> <imset.h> <pmset.h> "mimstat.h" \ + "rskysub.h" + rsmmean.x <imhdr.h> <imset.h> <pmset.h> "rskysub.h" + rsmean.x <imhdr.h> "rskysub.h" + rsscache.x <imhdr.h> <imset.h> + rsreject.x <imhdr.h> <imset.h> + rsfnames.x + + mimstat.x <mach.h> "mimstat.h" + mptools.x <ctype.h> <imhdr.h> <imset.h> <pmset.h> + ; diff --git a/pkg/proto/masks/mptools.x b/pkg/proto/masks/mptools.x new file mode 100644 index 00000000..7e08cab1 --- /dev/null +++ b/pkg/proto/masks/mptools.x @@ -0,0 +1,468 @@ +include <ctype.h> +include <imhdr.h> +include <imset.h> +include <pmset.h> + +# MP_OPEN -- Open the specified mask for image i/o +# +# Open the specified pixel mask. The input pixel mask specification may be +# +# "" The mask is undefined +# +# "EMPTY" The mask is undefined +# +# "!KEYWORD" The mask is the pixel mask pointed to by the reference +# image header keyword KEYWORD +# "!^KEYWORD" The mask is inverse of the pixel mask pointed to by the +# reference image header keyword KEYWORD +# "MASK" The mask is a pixel mask or image +# +# "^MASK" The mask is inverse of the pixel mask or image +# +# "EXPR" The mask is specified by an integer expression +# +# "@FILE" The mask is specified by the an integer expression in +# the text file FILE +# +# The input mask specification is transformed into a simple 0 and 1 mask +# internally where 0 is the pass value and 1 is the stop value. The format +# of EXPR is still a TBD but I would eventually like to support +# an algebra that includes simple image expressions as in the IMEXPR task, +# and regions descriptors similar to those defined in the PROS XRAY package. +# The latter have the problem in that they must be limited to 1D images (point, +# line egments) or 2D images (box, rectangle, ellipse, # annulus, wedge, etc). +# It maybe possible to expand this to 3D in some cases, e.g. cubes, spheres, +# ellipsoids etc although dealing with the angles may become complicated. At +# any rate I will put aside the issue of on the fly mask generation for the +# moment. If a section is specified on the input image but not on the mask +# image then imio/mio will automatically track the proper section in the mask. +# If a section is specified on the mask that section of the mask will be used, +# and it must correspond in size to the input image or image section. + +pointer procedure mp_open (pmsource, refim, pmname, sz_pmname) + +char pmsource[ARB] #I the pixel mask specificiation +pointer refim #I the reference image pointer +char pmname[ARB] #O the pixel mask name +int sz_pmname #I the maximum pixel name length + +pointer sp, fname, kfname +pointer pmim, pm +int ip, flags, invflag +pointer im_pmmap(), mp_pmmap() +int imaccess(), imstati() +bool streq() +errchk im_pmmap(), mp_pmmap(), imgstr() + +begin + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (kfname, SZ_FNAME, TY_CHAR) + + # Remove leading whitespace from the pixel source specification. + ip = 1 + while (IS_WHITE(pmsource[ip])) + ip = ip + 1 + call strcpy (pmsource[ip], Memc[fname], SZ_FNAME) + flags = 0 + pmname[1] = EOS + + # If the mask is undefined specify an empty mask. + if (Memc[fname] == EOS || streq (Memc[fname], "EMPTY")) { + + ifnoerr (pmim = im_pmmap ("EMPTY", READ_ONLY+BOOLEAN_MASK, refim)) { + call strcpy ("EMPTY", pmname, sz_pmname) + pm = imstati (pmim, IM_PMDES) + call mp_invert (pm) + call imseti (pmim, IM_PMDES, pm) + } else + pmim = NULL + + # If the mask specification is a keyword. + } else if (Memc[fname] == '!') { + + # Invert the specified mask. Note there is a bug in the + # invert mask flag which needs to be worked around. + ip = 1 + if (Memc[fname+ip] == '^') { + ip = ip + 1 + flags = BOOLEAN_MASK + invflag = NO + } else { + #flags = INVERT_MASK + BOOLEAN_MASK + flags = BOOLEAN_MASK + invflag = YES + } + + # Find the mask name. + ifnoerr (call imgstr (refim, Memc[fname+ip], Memc[kfname], + SZ_FNAME)) { + iferr (pmim = mp_pmmap (Memc[kfname], refim, flags, invflag)) { + pmim = NULL + } else if (invflag == NO) { + call strcpy ("^", pmname, sz_pmname) + call strcat (Memc[kfname], pmname, sz_pmname) + } else { + call strcpy (Memc[kfname], pmname, sz_pmname) + } + } else + pmim = NULL + + # If the mask specification is a mask / or image file. + } else if (imaccess (Memc[fname], READ_ONLY) == YES) { + + #flags = BOOLEAN_MASK+INVERT_MASK + flags = BOOLEAN_MASK + invflag = YES + call strcpy (Memc[fname], pmname, sz_pmname) + iferr (pmim = mp_pmmap (Memc[fname], refim, flags, invflag)) + pmim = NULL + else + call strcpy (Memc[fname], pmname, sz_pmname) + + } else if (Memc[fname] == '^') { + if (imaccess (Memc[fname+1], READ_ONLY) == YES) { + flags = BOOLEAN_MASK + invflag = NO + call strcpy (Memc[fname], pmname, sz_pmname) + iferr (pmim = mp_pmmap (Memc[fname+1], refim, flags, invflag)) + pmim = NULL + else + call strcpy (Memc[fname], pmname, sz_pmname) + } else + pmim = NULL + + } else { + pmim = NULL + } + + call sfree (sp) + + return (pmim) +end + + +# MP_PMMAP - Open a pixel mask READ_ONLY. The input mask may be a pixel +# list image or a non-pixel list image. The invflag is temporary, put into +# deal with the fact that mio has a bug in this flag. + + +pointer procedure mp_pmmap (pmname, refim, flags, invflag) + +char pmname[ARB] #I the pixel list or image name +pointer refim #I the reference image descriptor +int flags #I the pixel list or image flags +int invflag #I invert mask flag, remove when pmio fixed + +pointer sp, section, pmim, pm, tmp_refim +int use_section +pointer im_pmmap(), mp_immap() +int imstati() +errchk im_pmmap(), mp_immap() + +begin + # Does the pmname include an image section. + call smark (sp) + call salloc (section, SZ_FNAME, TY_CHAR) + call imgsection (pmname, Memc[section], SZ_FNAME) + if (Memc[section] == EOS) { + use_section = NO + tmp_refim = refim + } else { + use_section = YES + tmp_refim = NULL + } + + # Open the mask as a pixel list. + ifnoerr (pmim = im_pmmap (pmname, READ_ONLY+flags, tmp_refim)) { + + if (use_section == YES) + call mp_section (pmim) + if (invflag == YES) { + pm = imstati (pmim, IM_PMDES) + call mp_invert (pm) + call imseti (pmim, IM_PMDES, pm) + } + + # Open the mask as an image file. + } else ifnoerr (pmim = mp_immap (pmname)) { + + if (invflag == YES) { + pm = imstati (pmim, IM_PMDES) + call mp_invert (pm) + call imseti (pmim, IM_PMDES, pm) + } + + } else { + pmim = NULL + } + + call sfree (sp) + + return (pmim) +end + + +# MP_IMMAP -- Map an image as a pixel file + +pointer procedure mp_immap (pmname) + +char pmname[ARB] #I the pixel list or image name + +pointer sp, v1, v2, im, pm, data, pmim +int ndim, npix +pointer immap(), pm_newmask(), im_pmmapo() +int imgnli() + +begin + call smark (sp) + call salloc (v1, IM_MAXDIM, TY_LONG) + call salloc (v2, IM_MAXDIM, TY_LONG) + + call amovkl (long(1), Meml[v1], IM_MAXDIM) + call amovkl (long(1), Meml[v2], IM_MAXDIM) + + # Open the input image. + im = immap (pmname, READ_ONLY, 0) + ndim = IM_NDIM(im) + npix = IM_LEN(im,1) + + # Open the mask with a depth of 1 bit. + pm = pm_newmask (im, 1) + + # Copy the image to a mask. + while (imgnli (im, data, Meml[v1]) != EOF) { + # may need to convert negative values here ... + call pm_plpi (pm, Meml[v2], Memi[data], 0, npix, PIX_SRC) + call amovl (Meml[v1], Meml[v2], ndim) + } + call imunmap (im) + + pmim = im_pmmapo (pm, NULL) + + call sfree (sp) + + return (pmim) +end + + +# MP_SECTION -- Create the a new mask from the specified mask section. + +procedure mp_section (pmim) + +pointer pmim #U mask image descriptor + +pointer newpm, newpmim, sp, v1, v2, ibuf +pointer pl_create(), im_pmmapo() +int ndim, depth, npix +int imgnls() + +begin + call smark (sp) + call salloc (v1, IM_MAXDIM, TY_LONG) + call salloc (v2, IM_MAXDIM, TY_LONG) + call amovkl (long(1), Meml[v1], IM_MAXDIM) + call amovkl (long(1), Meml[v2], IM_MAXDIM) + + ndim = IM_NDIM(pmim) + depth = 1 + npix = IM_LEN(pmim,1) + + newpm = pl_create (ndim, IM_LEN(pmim,1), depth) + while (imgnls (pmim, ibuf, Meml[v1]) != EOF) { + call pm_plps (newpm, Meml[v2], Mems[ibuf], 1, npix, PIX_SRC) + call amovl (Meml[v1], Meml[v2], ndim) + } + + call imunmap (pmim) + newpmim = im_pmmapo (newpm, NULL) + pmim = newpmim + + call sfree (sp) +end + + +# MP_MPCOPY -- Copy the input to the output mask setting the mapping +# parameters appropriately + +procedure mp_mpcopy (im, pmim, pmout) + +pointer im #I the input image descriptor +pointer pmim #I the input mask descriptor +pointer pmout #I the output mask descriptor + +pointer sp, axlen, v, oldpm, newpm +int naxes, depth +pointer pl_create() +int imstati(), mp_samesize() + +int pm_stati() +int refim, mapstat + +begin + call smark (sp) + call salloc (axlen, IM_MAXDIM, TY_LONG) + call salloc (v, IM_MAXDIM, TY_LONG) + + # Create new mask. + oldpm = imstati (pmim, IM_PLDES) + call pl_gsize (oldpm, naxes, Meml[axlen], depth) + newpm = pl_create (naxes, Meml[axlen], depth) + + # Store old values of the input mask reference image and mapping + # descriptors here. Maybe ... + refim = pm_stati (oldpm, P_REFIM) + mapstat = pm_stati (oldpm, P_MAPXY) + + # Set the input mask mapping parameters. + call pm_seti (oldpm, P_REFIM, im) + if (mp_samesize (im, pmim) == YES) + call pm_seti (oldpm, P_MAPXY, NO) + + # Restore old values of the input mask reference image and mapping + # descriptors here. Maybe ... + + # Store old values of the output reference image and mapping descriptors + # here. Don't need to do this since this is the desired behavior. + + # Set the input mask mapping parameters. + call pm_seti (newpm, P_REFIM, im) + if (mp_samesize (im, pmim) == YES) + call pm_seti (newpm, P_MAPXY, NO) + + # Restore old values of the output mask reference image and mapping + # descriptors here. Don't need to do this since this is the + # desired behavior. + + # Copy the input to the output mask using the mapping parameters + # as appropriate + call amovkl (long(1), Meml[v], IM_MAXDIM) + call pm_rop (oldpm, Meml[v], newpm, Meml[v], Meml[axlen], PIX_SRC) + + call imseti (pmout, IM_PLDES, newpm) + call sfree (sp) +end + + +# MP_MIOPEN - Open an mio descriptor and set the mapping parameters +# appropriately. This should be done by doing pm_stati calls on +# the pm descriptor via the P_REFIM and P_MAPXY parameters and the +# corresponding PRIVATE1 / PRIVATE2 parameters in plio but this +# mechanism is not working at present. For now test im / pmim for +# equality in number of dimensions and size. + +pointer procedure mp_miopen (im, pmim) + +pointer im #I the input image descriptor +pointer pmim #I the input mask image descriptor + +pointer pm, mp +int samesize +pointer mio_openo() +int imstati(), mp_samesize() + +begin + # Open the pixel mask. + pm = imstati (pmim, IM_PLDES) + + # Open the mio descriptor which set the mapping status using + # the image descriptor, i.e. the mapping status is yes if the + # image was opened with a section. + mp = mio_openo (pm, im) + + # Turn off mapping if the image and mask are exactly the same + # size. + samesize = mp_samesize (im, pmim) + if (samesize == YES) + call pm_seti (pm, P_MAPXY, NO) + + return (mp) +end + + +# MP_SAMESIZE -- Return YES if the image and mask are the same size. + +int procedure mp_samesize (im, pmim) + +pointer im #I the input image descriptor +pointer pmim #I the input image descriptor + +int i, samesize + +begin + if (IM_NDIM(im) == IM_NDIM(pmim)) { + samesize = YES + do i = 1, IM_NDIM(im) { + if (IM_LEN(im,i) == IM_LEN(pmim,i)) + next + samesize = NO + break + } + } else { + samesize = NO + } + + return (samesize) +end + + +# MP_INVERT -- Invert a pixel mask. + +procedure mp_invert (pm) + +pointer pm #U plio descriptor + +pointer sp, axlen, v, newpm +int naxes, depth +pointer pl_create() + +begin + # Allocate some working space. + call smark (sp) + call salloc (axlen, IM_MAXDIM, TY_LONG) + call salloc (v, IM_MAXDIM, TY_LONG) + + # Get pixel mask characteristics. + call pl_gsize (pm, naxes, Meml[axlen], depth) + + # Create the new inverted mask. + newpm = pl_create (naxes, Meml[axlen], depth) + call amovkl (long(1), Meml[v], IM_MAXDIM) + call pl_rop (pm, Meml[v], newpm, Meml[v], Meml[axlen], + PIX_NOT(PIX_SRC)) + + # Close the old mask and update the mask pointer. + call pl_close (pm) + pm = newpm + + call sfree (sp) +end + + +# MP_COPY -- Make a copy of an existing pixel mask. + +pointer procedure mp_copy (oldpm) + +pointer oldpm #I old pixel mask pointer + +pointer sp, axlen, v, newpm +int naxes, depth +pointer pl_create() + +begin + call smark (sp) + call salloc (axlen, IM_MAXDIM, TY_LONG) + call salloc (v, IM_MAXDIM, TY_LONG) + + call pl_gsize (oldpm, naxes, Meml[axlen], depth) + newpm = pl_create (naxes, Meml[axlen], depth) + + call amovkl (long(1), Meml[v], IM_MAXDIM) + call pl_rop (oldpm, Meml[v], newpm, Meml[v], Meml[axlen], + PIX_SRC) + + call sfree (sp) + + return (newpm) +end + diff --git a/pkg/proto/masks/mstcache.x b/pkg/proto/masks/mstcache.x new file mode 100644 index 00000000..d8195a7d --- /dev/null +++ b/pkg/proto/masks/mstcache.x @@ -0,0 +1,100 @@ +include <imhdr.h> +include <imset.h> + +define MEMFUDGE 1.05 + +# MST_CACHE1 -- Cache 1 image in memory using the image i/o buffer sizes. + +procedure mst_cache1 (cache, im, old_size) + +int cache #I cache the image pixels in the imio buffer +pointer im #I the image descriptor +int old_size #O the old working set size + +int i, req_size, buf_size +int sizeof(), mst_memstat() + +begin + req_size = MEMFUDGE * IM_LEN(im,1) * sizeof (IM_PIXTYPE(im)) + do i = 2, IM_NDIM(im) + req_size = req_size * IM_LEN(im,i) + if (mst_memstat (cache, req_size, old_size) == YES) + call mst_pcache (im, INDEFI, buf_size) +end + + +# MST_MEMSTAT -- Figure out if there is enough memory to cache the image +# pixels. If it is necessary to request more memory and the memory is +# avalilable return YES otherwise return NO. + +int procedure mst_memstat (cache, req_size, old_size) + +int cache #I cache memory ? +int req_size #I the requested working set size in chars +int old_size #O the original working set size in chars + +int cur_size, max_size +int begmem() + +begin + # Find the default working set size. + cur_size = begmem (0, old_size, max_size) + + # If cacheing is disabled return NO regardless of the working set size. + if (cache == NO) + return (NO) + + # If the requested working set size is less than the current working + # set size return YES. + if (req_size <= cur_size) + return (YES) + + # Reset the current working set size. + cur_size = begmem (req_size, old_size, max_size) + if (req_size <= cur_size) { + return (YES) + } else { + return (NO) + } +end + + +# MST_PCACHE -- Cache the image pixels im memory by resetting the default image +# buffer size. If req_size is INDEF the size of the image is used to determine +# the size of the image i/o buffers. + +procedure mst_pcache (im, req_size, buf_size) + +pointer im #I the input image point +int req_size #I the requested working set size in chars +int buf_size #O the new image buffer size + +int i, def_size, new_imbufsize +int sizeof(), imstati() + +begin + # Find the default buffer size. + def_size = imstati (im, IM_BUFSIZE) + + # Compute the new required image i/o buffer size in chars. + if (IS_INDEFI(req_size)) { + new_imbufsize = IM_LEN(im,1) * sizeof (IM_PIXTYPE(im)) + do i = 2, IM_NDIM(im) + new_imbufsize = new_imbufsize * IM_LEN(im,i) + } else { + new_imbufsize = req_size + } + + # If the default image i/o buffer size is already bigger than + # the requested size do nothing. + if (def_size >= new_imbufsize) { + buf_size = def_size + return + } + + # Reset the image i/o buffer. + call imseti (im, IM_BUFSIZE, new_imbufsize) + call imseti (im, IM_BUFFRAC, 0) + buf_size = new_imbufsize +end + diff --git a/pkg/proto/masks/rsfnames.x b/pkg/proto/masks/rsfnames.x new file mode 100644 index 00000000..2a7c2d5a --- /dev/null +++ b/pkg/proto/masks/rsfnames.x @@ -0,0 +1,549 @@ + +define RS_EXTNLIST "|imh|fits|pl|qpoe|hhh|" + + +# RS_IMLIST -- Create a list of input masks using the input image list and an +# output template string. + +int procedure rs_imlist (inlist, output, defaultstr, extstr) + +int inlist #I the input image list descriptor +char output[ARB] #I the input output file list +char defaultstr[ARB] #I the defaults id string +char extstr[ARB] #I the extension string + +pointer sp, fname, image, dirname, otemplate +int i, outlist, len_dir, len_otemplate, strfd +int imtopen(), imtlen(), imtrgetim(), fnldir(), strncmp(), strlen() +int stropen(), strmatch() +errchk imtopen() + +begin + # Return if the ouyput file list is empty. + iferr (outlist = imtopen (output)) + outlist = imtopen ("") + if (output[1] == EOS || imtlen (outlist) <= 0) + return (outlist) + + # Return if the output image list is the wrong length. + if ((imtlen (outlist) > 1) && (imtlen (outlist) != imtlen(inlist))) { + call imtclose (outlist) + outlist = imtopen ("") + return (outlist) + } + + # Get working space. + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (dirname, SZ_FNAME, TY_CHAR) + + # Get the directory name. + if (imtrgetim (outlist, 1, Memc[fname], SZ_FNAME) == EOF) + Memc[fname] = EOS + len_dir = fnldir (Memc[fname], Memc[dirname], SZ_FNAME) + + # Get the default output file names. There will be one output image per + # input image. + if (strncmp (defaultstr, Memc[fname+len_dir], + strlen (defaultstr)) == 0 || len_dir == strlen (Memc[fname])) { + + # Create a temporary list string. + call imtclose (outlist) + len_otemplate = imtlen (inlist) * SZ_FNAME + 1 + call salloc (otemplate, len_otemplate, TY_CHAR) + Memc[otemplate] = EOS + + # Loop over the input image list. + strfd = stropen (Memc[otemplate], len_otemplate, NEW_FILE) + do i = 1, imtlen (inlist) { + + # Get the root image name. + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) + ; + + # Construct the default name. + call rs_oimname (Memc[image], Memc[dirname], extstr, + Memc[fname], SZ_FNAME) + if (strmatch (Memc[fname], ".pl$") == 0) + call strcat (".pl", Memc[fname], SZ_FNAME) + + + # Record the file name. + call fprintf (strfd, "%s,") + call pargstr (Memc[fname]) + } + call close (strfd) + + # Create the final list. + if (Memc[otemplate] != EOS) + Memc[otemplate+strlen(Memc[otemplate])-1] = EOS + outlist = imtopen (Memc[otemplate]) + + # Get the user output names. + } else { + + # Create a temporary list string. + len_otemplate = imtlen (outlist) * SZ_FNAME + 1 + call salloc (otemplate, len_otemplate, TY_CHAR) + Memc[otemplate] = EOS + + strfd = stropen (Memc[otemplate], len_otemplate, NEW_FILE) + # Loop over the fields. + do i = 1, imtlen (inlist) { + + if (imtrgetim (outlist, i, Memc[fname], SZ_FNAME) == EOF) + break + if (strmatch (Memc[fname], ".pl$") == 0) + call strcat (".pl", Memc[fname], SZ_FNAME) + + # Add the output name to the list. + call fprintf (strfd, "%s,") + call pargstr (Memc[fname]) + } + call close (strfd) + + if (Memc[otemplate] != EOS) + Memc[otemplate+strlen(Memc[otemplate])-1] = EOS + call imtclose (outlist) + outlist = imtopen (Memc[otemplate]) + } + + call sfree (sp) + + return (outlist) +end + + +# RS_OLIST -- Create a list of output images using the input image list and an +# output template string. + +int procedure rs_olist (inlist, output, defaultstr, extstr) + +int inlist #I the input image list descriptor +char output[ARB] #I the input output file list +char defaultstr[ARB] #I the defaults id string +char extstr[ARB] #I the extension string + +pointer sp, fname, image, dirname, otemplate +int i, outlist, len_dir, len_otemplate, strfd +int imtopen(), imtlen(), imtrgetim(), fnldir(), strncmp(), strlen() +int stropen() +errchk imtopen() + +begin + # Return if the input file list is empty. + iferr (outlist = imtopen (output)) + outlist = imtopen ("") + if (output[1] == EOS || imtlen (outlist) <= 0) + return (outlist) + + # Return if the output image list is the wrong length. + if ((imtlen (outlist) > 1) && (imtlen (outlist) != imtlen(inlist))) { + call imtclose (outlist) + outlist = imtopen ("") + return (outlist) + } + + # Get working space. + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (dirname, SZ_FNAME, TY_CHAR) + + # Get the directory name. + if (imtrgetim (outlist, 1, Memc[fname], SZ_FNAME) == EOF) + Memc[fname] = EOS + len_dir = fnldir (Memc[fname], Memc[dirname], SZ_FNAME) + + # Get the default output file names. There will be one output image per + # input image. + if (strncmp (defaultstr, Memc[fname+len_dir], + strlen (defaultstr)) == 0 || len_dir == strlen (Memc[fname])) { + + # Create a temporary list string. + call imtclose (outlist) + len_otemplate = imtlen (inlist) * SZ_FNAME + 1 + call salloc (otemplate, len_otemplate, TY_CHAR) + Memc[otemplate] = EOS + + # Loop over the input image list. + strfd = stropen (Memc[otemplate], len_otemplate, NEW_FILE) + do i = 1, imtlen (inlist) { + + # Get the root image name. + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) + ; + + # Construct the default name. + call rs_oimname (Memc[image], Memc[dirname], extstr, + Memc[fname], SZ_FNAME) + + # Record the file name. + call fprintf (strfd, "%s,") + call pargstr (Memc[fname]) + } + call close (strfd) + + # Create the final list. + if (Memc[otemplate] != EOS) + Memc[otemplate+strlen(Memc[otemplate])-1] = EOS + outlist = imtopen (Memc[otemplate]) + + # Get the user output names. + } else { + + # Create a temporary list string. + len_otemplate = imtlen (outlist) * SZ_FNAME + 1 + call salloc (otemplate, len_otemplate, TY_CHAR) + Memc[otemplate] = EOS + + strfd = stropen (Memc[otemplate], len_otemplate, NEW_FILE) + # Loop over the fields. + do i = 1, imtlen (inlist) { + + # Get the output file name. + if (imtrgetim (outlist, i, Memc[fname], SZ_FNAME) == EOF) + break + + # Add the output name to the list. + call fprintf (strfd, "%s,") + call pargstr (Memc[fname]) + } + call close (strfd) + + if (Memc[otemplate] != EOS) + Memc[otemplate+strlen(Memc[otemplate])-1] = EOS + call imtclose (outlist) + outlist = imtopen (Memc[otemplate]) + } + + call sfree (sp) + + return (outlist) +end + + +# RS_OMLIST -- Create a list of output masks using the input image list and an +# output template string. + +int procedure rs_omlist (inlist, output, defaultstr, extstr) + +int inlist #I the input image list descriptor +char output[ARB] #I the input output file list +char defaultstr[ARB] #I the defaults id string +char extstr[ARB] #I the extension string + +pointer sp, fname, image, dirname, otemplate +int i, outlist, len_dir, len_otemplate, strfd +int imtopen(), imtlen(), imtrgetim(), fnldir(), strncmp(), strlen() +int stropen(), strmatch() +errchk imtopen() + +begin + # Return if the input file list is empty. + iferr (outlist = imtopen (output)) + outlist = imtopen ("") + if (output[1] == EOS || imtlen (outlist) <= 0) + return (outlist) + + # Return if the output image list is the wrong length. + if ((imtlen (outlist) > 1) && (imtlen (outlist) != imtlen(inlist))) { + call imtclose (outlist) + outlist = imtopen ("") + return (outlist) + } + + # Get working space. + call smark (sp) + call salloc (fname, SZ_FNAME, TY_CHAR) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (dirname, SZ_FNAME, TY_CHAR) + + # Get the directory name. + if (imtrgetim (outlist, 1, Memc[fname], SZ_FNAME) == EOF) + Memc[fname] = EOS + len_dir = fnldir (Memc[fname], Memc[dirname], SZ_FNAME) + + # Get the default output file names. There will be one output image per + # input image. + if (strncmp (defaultstr, Memc[fname+len_dir], + strlen (defaultstr)) == 0 || len_dir == strlen (Memc[fname])) { + + # Create a temporary list string. + call imtclose (outlist) + len_otemplate = imtlen (inlist) * SZ_FNAME + 1 + call salloc (otemplate, len_otemplate, TY_CHAR) + Memc[otemplate] = EOS + + # Loop over the input image list. + strfd = stropen (Memc[otemplate], len_otemplate, NEW_FILE) + do i = 1, imtlen (inlist) { + + # Get the root image name. + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) + ; + + # Construct the default name. + call rs_oimname (Memc[image], Memc[dirname], extstr, + Memc[fname], SZ_FNAME) + if (strmatch (Memc[fname], ".pl$") == 0) + call strcat (".pl", Memc[fname], SZ_FNAME) + + + # Record the file name. + call fprintf (strfd, "%s,") + call pargstr (Memc[fname]) + } + call close (strfd) + + # Create the final list. + if (Memc[otemplate] != EOS) + Memc[otemplate+strlen(Memc[otemplate])-1] = EOS + outlist = imtopen (Memc[otemplate]) + + # Get the user output names. + } else { + + # Create a temporary list string. + len_otemplate = imtlen (outlist) * SZ_FNAME + 1 + call salloc (otemplate, len_otemplate, TY_CHAR) + Memc[otemplate] = EOS + + strfd = stropen (Memc[otemplate], len_otemplate, NEW_FILE) + # Loop over the fields. + do i = 1, imtlen (inlist) { + + # Get the output file name. + if (imtrgetim (outlist, i, Memc[fname], SZ_FNAME) == EOF) + break + if (strmatch (Memc[fname], ".pl$") == 0) + call strcat (".pl", Memc[fname], SZ_FNAME) + + # Add the output name to the list. + call fprintf (strfd, "%s,") + call pargstr (Memc[fname]) + } + call close (strfd) + + if (Memc[otemplate] != EOS) + Memc[otemplate+strlen(Memc[otemplate])-1] = EOS + call imtclose (outlist) + outlist = imtopen (Memc[otemplate]) + } + + call sfree (sp) + + return (outlist) +end + + +# RS_OUTNAME -- Construct an output file name. If output is null or a +# directory, a name is constructed from the root of the image name and the +# extension. The disk is searched to avoid name collisions. + +procedure rs_outname (image, output, ext, name, maxch) + +char image[ARB] #I input image name +char output[ARB] #I input output directory or name +char ext[ARB] #I input extension +char name[ARB] #O output file name +int maxch #I maximum size of name + +pointer sp, root, str +int ndir, nimdir, clindex, clsize, nextn +int fnldir(), strlen(), strldx(), strdic() +char period + +begin + call smark (sp) + call salloc (root, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + ndir = fnldir (output, name, maxch) + if (strlen (output) == ndir) { + call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME, + Memc[str], SZ_FNAME, clindex, clsize) + nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME) + period = '.' + nextn = strldx (period, Memc[root]) + if (nextn > 0) { + if (strdic (Memc[root+nextn], Memc[str], SZ_FNAME, + RS_EXTNLIST) > 0) + Memc[root+nextn-1] = EOS + } + if (clindex >= 0) { + if (ext[1] == EOS) { + call sprintf (name[ndir+1], maxch, "%s%d.*") + call pargstr (Memc[root+nimdir]) + call pargi (clindex) + } else { + call sprintf (name[ndir+1], maxch, "%s%d.%s.*") + call pargstr (Memc[root+nimdir]) + call pargi (clindex) + call pargstr (ext) + } + } else { + if (ext[1] == EOS) { + call sprintf (name[ndir+1], maxch, "%s.*") + call pargstr (Memc[root+nimdir]) + } else { + call sprintf (name[ndir+1], maxch, "%s.%s.*") + call pargstr (Memc[root+nimdir]) + call pargstr (ext) + } + } + call rs_oversion (name, name, maxch) + } else + call strcpy (output, name, maxch) + + call sfree (sp) +end + + +# RS_OVERSION -- Compute the next available version number of a given file +# name template and output the new file name. + +procedure rs_oversion (template, filename, maxch) + +char template[ARB] #I the input name template +char filename[ARB] #O the output name +int maxch #I the maximum number of characters + +char period +int newversion, version, len +pointer sp, list, name +int fntgfnb() strldx(), ctoi(), fntopnb() +errchk fntopnb() + +begin + # Allocate temporary space + call smark (sp) + call salloc (name, maxch, TY_CHAR) + period = '.' + iferr (list = fntopnb (template, NO)) + list = fntopnb ("", NO) + + # Loop over the names in the list searchng for the highest version. + newversion = 0 + while (fntgfnb (list, Memc[name], maxch) != EOF) { + len = strldx (period, Memc[name]) + len = len + 1 + if (ctoi (Memc[name], len, version) <= 0) + next + newversion = max (newversion, version) + } + + # Make new output file name. + len = strldx (period, template) + call strcpy (template, filename, len) + call sprintf (filename[len+1], maxch, "%d") + call pargi (newversion + 1) + + call fntclsb (list) + call sfree (sp) +end + + +# RS_OIMNAME -- Construct an output image name. If output is null or a +# directory a name is constructed from the root of the image name and the +# extension. The disk is searched to avoid name collisions. + +procedure rs_oimname (image, output, ext, name, maxch) + +char image[ARB] #I the input image name +char output[ARB] #I the output directory or ouput image name +char ext[ARB] #I the output image extension +char name[ARB] #O the final output image name +int maxch #I maximum size of name + +int ndir, nimdir, clindex, clsize +pointer sp, root, str +int fnldir(), strlen() + +begin + # Allocate some temporary space. + call smark (sp) + call salloc (root, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Determine the length of the directory spec. + ndir = fnldir (output, name, maxch) + + # If the file spec is a directory create a name from the directory and + # the route image name, otherwise use the output name directly. + if (strlen (output) == ndir) { + call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME, + Memc[str], SZ_FNAME, clindex, clsize) + nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME) + if (clindex >= 0) { + if (ext[1] == EOS) { + call sprintf (name[ndir+1], maxch, "%s%d.*") + call pargstr (Memc[root+nimdir]) + call pargi (clindex) + } else { + call sprintf (name[ndir+1], maxch, "%s%d.%s.*") + call pargstr (Memc[root+nimdir]) + call pargi (clindex) + call pargstr (ext) + } + } else { + if (ext[1] == EOS) { + call sprintf (name[ndir+1], maxch, "%s.*") + call pargstr (Memc[root+nimdir]) + } else { + call sprintf (name[ndir+1], maxch, "%s.%s.*") + call pargstr (Memc[root+nimdir]) + call pargstr (ext) + } + } + call rs_oimversion (name, name, maxch) + } else + call strcpy (output, name, maxch) + + call sfree (sp) +end + + +# RS_OIMVERSION -- Determine the next available version number for a given +# image name template and output the new image name. + +procedure rs_oimversion (template, filename, maxch) + +char template[ARB] #I the image name template +char filename[ARB] #O the output image name +int maxch #I the maximum number of characters + +char period +int newversion, version, len +pointer sp, list, name +int imtopen(), imtgetim(), strldx(), ctoi() + +begin + # Allocate temporary space + call smark (sp) + call salloc (name, maxch, TY_CHAR) + period = '.' + list = imtopen (template) + + # Loop over the names in the list searchng for the highest version. + newversion = 0 + while (imtgetim (list, Memc[name], maxch) != EOF) { + len = strldx (period, Memc[name]) + Memc[name+len-1] = EOS + len = strldx (period, Memc[name]) + len = len + 1 + if (ctoi (Memc[name], len, version) <= 0) + next + newversion = max (newversion, version) + } + + # Make new output file name. + len = strldx (period, template) + call strcpy (template, filename, len) + call sprintf (filename[len+1], maxch, "%d") + call pargi (newversion + 1) + + call imtclose (list) + call sfree (sp) +end diff --git a/pkg/proto/masks/rskysub.h b/pkg/proto/masks/rskysub.h new file mode 100644 index 00000000..7c14dfe0 --- /dev/null +++ b/pkg/proto/masks/rskysub.h @@ -0,0 +1,32 @@ +# Define the sky subtraction structure + + +define LEN_RSKYSUB 20 + 5 * SZ_FNAME + +define RS_LOWER Memr[P2R($1)] # lower good data limit +define RS_UPPER Memr[P2R($1+1)] # upper good data limit +define RS_LNSIGREJ Memr[P2R($1+2)] # low side clipping factor +define RS_UNSIGREJ Memr[P2R($1+3)] # high side clipping factor +define RS_BINWIDTH Memr[P2R($1+4)] # histogram binwidth +define RS_BLANK Memr[P2R($1+5)] # undefined pixel value +define RS_RESCALE Memi[$1+6] # recompute scaling factor ? +define RS_RESUBTRACT Memi[$1+7] # compute the subtracted image +define RS_NCOMBINE Memi[$1+8] # number of images to combine +define RS_NMIN Memi[$1+9] # min images to combine +define RS_MAXITER Memi[$1+11] # maximum number of iterations +define RS_COMBINE Memi[$1+12] # combining method +define RS_NLOREJ Memi[$1+13] # low side pixels to reject +define RS_NHIREJ Memi[$1+14] # high side pixels to reject +define RS_KYFSCALE Memc[P2C($1+15)] # scaling factor keyword +define RS_ISCALES Memc[P2C($1+15+SZ_FNAME)] # scaling method +define RS_STATSEC Memc[P2C($1+15+2*SZ_FNAME)] # statistics section +define RS_KYSKYSUB Memc[P2C($1+15+3*SZ_FNAME)] # sky subtraction keyword +define RS_KYHMASK Memc[P2C($1+15+4*SZ_FNAME)] # holes mask keyword + + +# Define the sky combining options + +define RS_COMBINESTR "|average|median|" + +define RS_MEAN 1 +define RS_MEDIAN 2 diff --git a/pkg/proto/masks/rsmean.x b/pkg/proto/masks/rsmean.x new file mode 100644 index 00000000..a39973bb --- /dev/null +++ b/pkg/proto/masks/rsmean.x @@ -0,0 +1,1172 @@ +include <imhdr.h> +include "rskysub.h" + +# RS_MSUB -- Perform a running mean sky subtraction on a list of images +# with no masking or rejection. + +procedure rs_msub (inlist, outlist, rs, cache, verbose) + +int inlist #I the input image list +int outlist #I the output image list +pointer rs #I the sky subtraction descriptor +bool cache #I cache temp image buffer in memory ? +bool verbose #I print task statistics + +real fscale +pointer sp, image, outimage, tmpimage, str +pointer im, outim, tmpim +int i, nimages, nlo, nhi, ostart, ofinish, start, finish, imno, oldsize +int bufsize, first, last +pointer immap() +int imtlen(), imtrgetim(), btoi(), imaccess() +errchk immap() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (outimage, SZ_FNAME, TY_CHAR) + call salloc (tmpimage, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Check image status. If resubtract is yes then delete the output + # images if they already exist. Otherwise determine whether the + # images already exist and if so whether or not they need to be + # sky subtracted again. + + nimages = imtlen (inlist) + if (RS_RESUBTRACT(rs) == NO) { + first = 0 + last = 0 + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == NO) { + if (first == 0) { + first = i + last = i + } else + last = i + } else { + outim = immap (Memc[outimage], READ_ONLY, 0) + iferr (call imgstr (outim, RS_KYSKYSUB(rs), Memc[str], + SZ_FNAME)) { + if (first == 0) { + first = i + last = i + } else + last = i + } + call imunmap (outim) + } + } + } else { + first = 1 + last = nimages + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == YES) + call imdelete (Memc[outimage]) + } + } + + # Check the sky subtraction status. + if (first <= 0 && last <= 0) { + if (verbose) { + call printf ( + "The output images have already been sky subtracted \n") + } + call sfree (sp) + return + } + + # Create the temporary image. + call mktemp ("_rsum", Memc[tmpimage], SZ_FNAME) + tmpim = immap (Memc[tmpimage], NEW_IMAGE, 0) + + # Compute the sliding mean parameters. + nlo = RS_NCOMBINE(rs) / 2 + nhi = RS_NCOMBINE(rs) - nlo + + # Loop over the images. + ostart = 0 + ofinish = 0 + do imno = 1, nimages { + + # Skip over beginning and ending images that have already been + # sky subtracted. + + if (imno < first || imno > last) { + if (verbose) { + if (imtrgetim (outlist, imno, Memc[outimage], + SZ_FNAME) == EOF) { + call printf ( + "The sky subtracted image %s already exists\n") + call pargstr (Memc[outimage]) + } + } + next + } + + # Determine which images will contribute to the sky image. + # Start and finish set the endpoints of the sequence. Imno + # is the current image which is to be sky subtracted. + + if ((imno - nlo) < 1) { + start = 1 + finish = min (nimages, max (2 * imno - 1, RS_NMIN(rs) + 1)) + } else if ((imno + nhi) > nimages) { + start = max (1, min (2 * imno - nimages, nimages - RS_NMIN(rs))) + finish = nimages + } else { + start = imno - nlo + finish = imno + nhi + } + + # Check that the minimum number of images exists. + if ((finish - start) < RS_NMIN(rs)) { + call eprintf ("There are too few images for sky subtraction\n") + break + } + + # Open the current input image. + if (imtrgetim (inlist, imno, Memc[image], SZ_FNAME) == EOF) { + call eprintf ("Error reading input image list\n") + break + } + iferr (im = immap (Memc[image], READ_ONLY, 0)) { + call eprintf ("Error opening input image %s\n") + call pargstr (Memc[image]) + break + } + + # Open the output image. + if (imtrgetim (outlist, imno, Memc[outimage], SZ_FNAME) == EOF) { + call eprintf ("Error reading output image list\n") + call imunmap (im) + break + } + iferr (outim = immap (Memc[outimage], NEW_COPY, im)) { + call eprintf ("Error opening output image %s\n") + call pargstr (Memc[outimage]) + call imunmap (im) + break + } + + if (verbose) { + call printf ("Sky subtracting image %s and writing to %s\n") + call pargstr (Memc[image]) + call pargstr (Memc[outimage]) + call flush (STDOUT) + } + + # Accumulate the running mean. The first time through the loop + # the number of dimensions, size, and pixel type of the temporary + # storage image are set and the first set of images are + # accumulated into the temporary image. + + if (imno == first) { + IM_NDIM(tmpim) = IM_NDIM(im) + call amovl (IM_LEN(im,1), IM_LEN(tmpim,1), IM_MAXDIM) + IM_PIXTYPE(tmpim) = TY_REAL + call rs_cachen (btoi(cache), 1, tmpim, oldsize) + call rs_minit (inlist, tmpim, start, finish, RS_KYFSCALE(rs)) + } else if ((ostart > 0 && start > ostart) || (ofinish > 0 && + finish > ofinish)) { + call rs_maddsub (inlist, tmpim, start, finish, ostart, ofinish, + RS_KYFSCALE(rs)) + } + + # Attempt to cache the input and output images. Try to cache + # the output image first since it will be accessed more + # frequently. + call rs_cachen (btoi(cache), 2, outim, bufsize) + call rs_cachen (btoi(cache), 3, im, bufsize) + + # Compute the new normalization factor. + call rs_mnorm (rs, im, tmpim, outim, finish - start + 1, fscale) + + # Write the output image. + call rs_mout (im, tmpim, outim, finish - start + 1, fscale, + RS_KYFSCALE(rs), RS_KYSKYSUB(rs)) + + # Close up images. + call imunmap (outim) + call imunmap (im) + + ostart = start + ofinish = finish + + } + + # Close and delete temporary image. + call imunmap (tmpim) + call imdelete (Memc[tmpimage]) + + call fixmem (oldsize) + + call sfree (sp) +end + + +# RS_RRMSUB -- Perform a running mean sky subtraction on a list of images +# with no masking but with minmax rejection opening and closing the input +# images for each set. + +procedure rs_rrmsub (inlist, outlist, rs, cache, verbose) + +int inlist #I the input image list +int outlist #I the output image list +pointer rs #I the sky subtraction descriptor +bool cache #I cache temp image buffer in memory ? +bool verbose #I print task statistics + +real fscale +pointer sp, image, outimage, tmpimage, imptrs, imids, str +pointer im, tmpim, outim +int i, imno, nlo, nhi, ostart, ofinish, start, finish, nimages +int oldsize, bufsize, first, last +pointer immap() +int imtlen(), imtrgetim(), btoi(), imaccess() +errchk immap(), imgstr() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (outimage, SZ_FNAME, TY_CHAR) + call salloc (tmpimage, SZ_FNAME, TY_CHAR) + call salloc (imptrs, RS_NCOMBINE(rs) + 1, TY_POINTER) + call salloc (imids, RS_NCOMBINE(rs) + 1, TY_INT) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Check image status. If resubtract is yes then delete the output + # images if they already exist. Otherwise determine whether the + # images already exist and if so whether or not they need to be + # sky subtracted again. + + nimages = imtlen (inlist) + if (RS_RESUBTRACT(rs) == NO) { + first = 0 + last = 0 + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == NO) { + if (first == 0) { + first = i + last = i + } else + last = i + } else { + outim = immap (Memc[outimage], READ_ONLY, 0) + iferr (call imgstr (outim, RS_KYSKYSUB(rs), Memc[str], + SZ_FNAME)) { + if (first == 0) { + first = i + last = i + } else + last = i + } + call imunmap (outim) + } + } + } else { + first = 1 + last = nimages + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == YES) + call imdelete (Memc[outimage]) + } + } + + # Check the sky subtraction status. + if (first <= 0 && last <= 0) { + if (verbose) { + call printf ( + "The output images have already been sky subtracted \n") + } + call sfree (sp) + return + } + + # Create the temporary image. + call mktemp ("_rsum", Memc[tmpimage], SZ_FNAME) + tmpim = immap (Memc[tmpimage], NEW_IMAGE, 0) + + # Compute the sliding mean parameters. + nlo = RS_NCOMBINE(rs) / 2 + nhi = RS_NCOMBINE(rs) - nlo + + # Loop over the images. + ostart = 0 + ofinish = 0 + do imno = 1, nimages { + + # Skip over beginning and ending images that have already been + # sky subtracted. + + if (imno < first || imno > last) { + if (verbose) { + if (imtrgetim (outlist, imno, Memc[outimage], + SZ_FNAME) == EOF) { + call printf ( + "The sky subtracted image %s already exists\n") + call pargstr (Memc[outimage]) + } + } + next + } + + # Determine which images will contribute to the sky image. + # Start and finish set the endpoints of the sequence. Imno + # is the current image which is to be sky subtracted. + + if ((imno - nlo) < 1) { + start = 1 + finish = min (nimages, max (2 * imno - 1, RS_NMIN(rs) + 1)) + } else if ((imno + nhi) > nimages) { + start = max (1, min (2 * imno - nimages, nimages - RS_NMIN(rs))) + finish = nimages + } else { + start = imno - nlo + finish = imno + nhi + } + + # Check that the minimum number of images exists. + if ((finish - start) < RS_NMIN(rs)) { + call eprintf ("There are too few images for sky subtraction\n") + break + } + + # Get the input image name. + if (imtrgetim (inlist, imno, Memc[image], SZ_FNAME) == EOF) { + call eprintf ("Error reading input image list\n") + break + } + + # Open the output image name. + if (imtrgetim (outlist, imno, Memc[outimage], SZ_FNAME) == EOF) { + call eprintf ("Error reading output image list\n") + break + } + + if (verbose) { + call printf ("Sky subtracting image %s and writing to %s\n") + call pargstr (Memc[image]) + call pargstr (Memc[outimage]) + call flush (STDOUT) + } + + # Determine which images are to be open at any given time. + + if (imno == first) { + call rs_iptrs (inlist, Memi[imptrs], Memi[imids], start, + finish, cache, oldsize) + IM_NDIM(tmpim) = IM_NDIM(Memi[imptrs]) + call amovl (IM_LEN(Memi[imptrs],1), IM_LEN(tmpim,1), IM_MAXDIM) + IM_PIXTYPE(tmpim) = TY_REAL + call rs_cachen (btoi(cache), finish - start + 2, tmpim, + bufsize) + } else { + call rs_asptrs (inlist, Memi[imptrs], Memi[imids], + start, finish, ostart, ofinish, cache) + } + + # Determine which image is the input image. + im = NULL + do i = 1, finish - start + 1 { + if (Memi[imids+i-1] != imno) + next + im = Memi[imptrs+i-1] + break + } + + # Open the output image and cache it. + iferr { + outim = immap (Memc[outimage], NEW_COPY, im) + } then { + call eprintf ("Error opening output image %s\n") + call pargstr (Memc[outimage]) + } else { + + # Cache the output image. + call rs_cachen (btoi(cache), finish - start + 3, outim, bufsize) + + # Combine images with rejection. + if (RS_COMBINE(rs) == RS_MEAN) + call rs_asumr (Memi[imptrs], Memi[imids], tmpim, start, + finish, imno, RS_NLOREJ(rs), RS_NHIREJ(rs), + RS_KYFSCALE(rs)) + else + call rs_asumr (Memi[imptrs], Memi[imids], tmpim, start, + finish, imno, INDEFI, INDEFI, RS_KYFSCALE(rs)) + + # Compute the normalization factor. + call rs_rmnorm (rs, im, tmpim, outim, fscale) + + # Write output image. + call rs_rmout (im, tmpim, outim, fscale, RS_KYSKYSUB(rs)) + + # Close up images. + call imunmap (outim) + } + + # Unmap the remaining image pointers. + if (imno == last) { + do i = 1, finish - start + 1 + call imunmap (Memi[imptrs+i-1]) + } + + ostart = start + ofinish = finish + } + + # Close and delete temporary image. + call imunmap (tmpim) + call imdelete (Memc[tmpimage]) + + call fixmem (oldsize) + + call sfree (sp) +end + + +# RS_RMSUB -- Perform a running mean sky subtraction on a list of images +# with no masking but with rejection. + +procedure rs_rmsub (inlist, outlist, rs, cache, verbose) + +int inlist #I the input image list +int outlist #I the output image list +pointer rs #I the sky subtraction descriptor +bool cache #I cache temp image buffer in memory ? +bool verbose #I print task statistics + +real fscale +pointer sp, image, outimage, tmpimage, str +pointer im, outim, tmpim +int i, nimages, nlo, nhi, ostart, ofinish, start, finish, imno, oldsize +int newsize, first, last +pointer immap() +int imtlen(), imtrgetim(), btoi(), imaccess() +errchk immap() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (outimage, SZ_FNAME, TY_CHAR) + call salloc (tmpimage, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Check image status. If resubtract is yes then delete the output + # images if they already exist. Otherwise determine whether the + # images already exist and if so whether or not they need to be + # sky subtracted again. + + nimages = imtlen (inlist) + if (RS_RESUBTRACT(rs) == NO) { + first = 0 + last = 0 + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == NO) { + if (first == 0) { + first = i + last = i + } else + last = i + } else { + outim = immap (Memc[outimage], READ_ONLY, 0) + iferr (call imgstr (outim, RS_KYSKYSUB(rs), Memc[str], + SZ_FNAME)) { + if (first == 0) { + first = i + last = i + } else + last = i + } + call imunmap (outim) + } + } + } else { + first = 1 + last = nimages + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == YES) + call imdelete (Memc[outimage]) + } + } + + # Check the sky subtraction status. + if (first <= 0 && last <= 0) { + if (verbose) { + call printf ( + "The output images have already been sky subtracted \n") + } + call sfree (sp) + return + } + + # Create the temporary image. + call mktemp ("_rsum", Memc[tmpimage], SZ_FNAME) + tmpim = immap (Memc[tmpimage], NEW_IMAGE, 0) + + # Compute the sliding mean parameters. + nlo = RS_NCOMBINE(rs) / 2 + nhi = RS_NCOMBINE(rs) - nlo + + # Loop over the images. + ostart = 0 + ofinish = 0 + do imno = 1, nimages { + + # Skip over beginning and ending images that have already been + # sky subtracted. + + if (imno < first || imno > last) { + if (verbose) { + if (imtrgetim (outlist, imno, Memc[outimage], + SZ_FNAME) == EOF) { + call printf ( + "The sky subtracted image %s already exists\n") + call pargstr (Memc[outimage]) + } + } + next + } + + # Determine which images will contribute to the sky image. + # Start and finish set the endpoints of the sequence. Imno + # is the current image which is to be sky subtracted. + + if ((imno - nlo) < 1) { + start = 1 + finish = min (nimages, max (2 * imno - 1, RS_NMIN(rs) + 1)) + } else if ((imno + nhi) > nimages) { + start = max (1, min (2 * imno - nimages, nimages - RS_NMIN(rs))) + finish = nimages + } else { + start = imno - nlo + finish = imno + nhi + } + + # Check that the minimum number of images exists. + if ((finish - start) < RS_NMIN(rs)) { + call eprintf ("There are too few images for sky subtraction\n") + break + } + + # Open the current input image. + if (imtrgetim (inlist, imno, Memc[image], SZ_FNAME) == EOF) { + call eprintf ("Error reading input image list\n") + break + } + iferr (im = immap (Memc[image], READ_ONLY, 0)) { + call eprintf ("Error opening input image %s\n") + call pargstr (Memc[image]) + break + } + + # Open the output image. + + if (imtrgetim (outlist, imno, Memc[outimage], SZ_FNAME) == EOF) { + call eprintf ("Error reading output image list\n") + call imunmap (im) + break + } + iferr (outim = immap (Memc[outimage], NEW_COPY, im)) { + call eprintf ("Error opening output image %s\n") + call pargstr (Memc[outimage]) + call imunmap (im) + break + } + + if (verbose) { + call printf ("Sky subtracting image %s and writing to %s\n") + call pargstr (Memc[image]) + call pargstr (Memc[outimage]) + call flush (STDOUT) + } + + # Set the size of the temporary image. + if (imno == first) { + IM_NDIM(tmpim) = IM_NDIM(im) + call amovl (IM_LEN(im,1), IM_LEN(tmpim,1), IM_MAXDIM) + IM_PIXTYPE(tmpim) = TY_REAL + call rs_cachen (btoi(cache), 1, tmpim, oldsize) + } + + # Accumulate the temporary image. + if (RS_COMBINE(rs) == RS_MEAN) + call rs_sumr (inlist, tmpim, start, finish, imno, RS_NLOREJ(rs), + RS_NHIREJ(rs), RS_KYFSCALE(rs)) + else + call rs_sumr (inlist, tmpim, start, finish, imno, INDEFI, + INDEFI, RS_KYFSCALE(rs)) + + # Cache the output image. + call rs_cachen (btoi(cache), 2, outim, newsize) + + # Compute the normalization factor. + call rs_rmnorm (rs, im, tmpim, outim, fscale) + + # Write the output image. + call rs_rmout (im, tmpim, outim, fscale, RS_KYSKYSUB(rs)) + + # Close up images. + call imunmap (outim) + call imunmap (im) + + ostart = start + ofinish = finish + + } + + # Close and delete temporary image. + call imunmap (tmpim) + call imdelete (Memc[tmpimage]) + + call fixmem (oldsize) + + call sfree (sp) +end + + +# RS_MINIT -- Initialize the accumulation buffer for the running median +# in the case of no masks. + +procedure rs_minit (inlist, tmpim, start, finish, skyscale) + +int inlist #I the input image list +pointer tmpim #I the output storage image +int start #I the starting image in the list +int finish #I the ending image in the list +#real normsum #U the normalization accumulator +char skyscale[ARB] #I the scaling factor keyword + +pointer sp, image, imptrs, imnorm, vin, vout, obuf, ibuf +int i, j, nin, npix +real imgetr() +pointer immap() +int imtrgetim(), impnlr(), imgnlr() +errchk imgetr() + +begin + nin = finish - start + 1 + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imptrs, nin, TY_POINTER) + call salloc (imnorm, nin, TY_REAL) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vin, nin * IM_MAXDIM, TY_LONG) + + # Open the input images + j = 1 + #normsum = 0.0 + do i = start, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) == EOF) + ; + Memi[imptrs+j-1] = immap (Memc[image], READ_ONLY, 0) + iferr (Memr[imnorm+j-1] = imgetr (Memi[imptrs+j-1], skyscale)) + Memr[imnorm+j-1] = 1.0 + #normsum = normsum + 1.0 + #else + #normsum = normsum + Memr[imnorm+j-1] + j = j + 1 + } + + call amovkl (long(1), Meml[vin], IM_MAXDIM * nin) + call amovkl (long(1), Meml[vout], IM_MAXDIM) + npix = IM_LEN(tmpim,1) + while (impnlr (tmpim, obuf, Meml[vout]) != EOF) { + call amovkr (0.0, Memr[obuf], npix) + do j = 1, nin { + if (imgnlr (Memi[imptrs+j-1], ibuf, + Meml[vin+(j-1)*IM_MAXDIM]) == EOF) + ; + call amulkr (Memr[ibuf], Memr[imnorm+j-1], Memr[ibuf], npix) + call aaddr (Memr[ibuf], Memr[obuf], Memr[obuf], npix) + } + } + + # Close the input images. + do j = 1, nin + call imunmap (Memi[imptrs+j-1]) + + call sfree (sp) +end + + +# RS_MNORM -- Compute the normalization factor for the new output image. + +procedure rs_mnorm (rs, im, tmpim, outim, nin, fscale) + +pointer rs #I the sky subtraction descriptor +pointer im #I the input image descriptor +pointer tmpim #I the storage image descriptor +pointer outim #I the output image descriptor +int nin #I the number of images +real fscale #I the scaling factor + + +real norm1, normf, rmin, rmax +pointer sp, vin, vout, vtmp, obuf, ibuf, tbuf +int i, npix +real imgetr() +int impnlr(), imgnlr() +errchk imgetr() + +begin + + call smark (sp) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + + iferr (norm1 = imgetr (im, RS_KYFSCALE(rs))) + norm1 = 1.0 + normf = 1.0 / (nin - 1) + npix = IM_LEN(im,1) + + # Compute the normalized image. + while (impnlr (outim, obuf, Meml[vout]) != EOF && imgnlr (im, ibuf, + Meml[vin]) != EOF && imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF) { + do i = 1, npix { + Memr[obuf+i-1] = normf * (Memr[tbuf+i-1] - norm1 * + Memr[ibuf+i-1]) + if (Memr[obuf+i-1] == 0.0) + Memr[obuf+i-1] = Memr[ibuf+i-1] + else + Memr[obuf+i-1] = Memr[ibuf+i-1] / Memr[obuf+i-1] + } + } + + # Compute the statistic. + rmin = RS_LOWER(rs) + rmax = RS_UPPER(rs) + RS_LOWER(rs) = INDEFR + RS_UPPER(rs) = INDEFR + call rs_med (outim, rs, fscale) + RS_LOWER(rs) = rmin + RS_UPPER(rs) = rmax + + call sfree (sp) + +end + + +# RS_MOUT -- Write the output image. Subtract the normalized input +# image from the accumulation buffer before computing the final average. + +procedure rs_mout (im, tmpim, outim, nin, fscale, skyscale, skysub) + +pointer im #I the input image descriptor +pointer tmpim #I the storage image descriptor +pointer outim #I the output image descriptor +int nin #I the number of images +real fscale #I the normalization factor +char skyscale[ARB] #I the sky scaling keyword +char skysub[ARB] #I the sky subtraction keyword + +real norm1, normf +pointer sp, vin, vout, vtmp, str, obuf, ibuf, tbuf +int i, npix +real imgetr() +int impnlr(), imgnlr() +errchk imgetr() + +begin + call smark (sp) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Write a sky subtraction flag to the output image. + call sprintf (Memc[str], SZ_FNAME, + "Sky subtracting with scale factor %g") + call pargr (fscale) + call imastr (outim, skysub, Memc[str]) + + # Get and set the normalization factors + iferr (norm1 = imgetr (im, skyscale)) + norm1 = 1.0 + normf = fscale / (nin - 1) + norm1 = 1.0 + normf * norm1 + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + npix = IM_LEN(im,1) + while (impnlr (outim, obuf, Meml[vout]) != EOF && imgnlr (im, ibuf, + Meml[vin]) != EOF && imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF) { + do i = 1, npix + Memr[obuf+i-1] = norm1 * Memr[ibuf+i-1] - normf * Memr[tbuf+i-1] + } + + call sfree (sp) +end + + +# RS_MADDSUB -- Add images to and subtract images from the accumulation +# buffer. + +procedure rs_maddsub (inlist, tmpim, start, finish, ostart, ofinish, skyscale) + +int inlist #I the input image list +pointer tmpim #I the storage image descriptor +int start #I the current starting image +int finish #I the current ending image +int ostart #I the previous starting image +int ofinish #I the previous ending image +#real normsum #I the norm factor accumulator +char skyscale #I the sky scaling keyword + +pointer sp, image, vin, vsub, vadd, vout, imsub, imadd, norma, norms +pointer ibuf, obuf, sbuf, abuf +int i, j, nsub, nadd, npix, doadd, dosub +real imgetr() +pointer immap() +int imtrgetim(), impnlr(), imgnlr() +errchk imgetr() + +begin + if (start == ostart && finish == ofinish) + return + nsub = start - ostart + nadd = finish - ofinish + + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (imsub, nsub, TY_INT) + call salloc (norms, nsub, TY_REAL) + call salloc (vsub, nsub * IM_MAXDIM, TY_LONG) + call salloc (imadd, nadd, TY_INT) + call salloc (vadd, nadd * IM_MAXDIM, TY_LONG) + call salloc (norma, nadd, TY_REAL) + + # Open the images to be subtracted. In most cases there will be + # one such image. + if (ostart < start) { + dosub = YES + j = 1 + do i = ostart, start - 1 { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + Memi[imsub+j-1] = immap (Memc[image], READ_ONLY, 0) + iferr (Memr[norms+j-1] = imgetr (Memi[imsub+j-1], skyscale)) + Memr[norms+j-1] = 1.0 + #normsum = normsum - Memr[norms+j-1] + } + j = j + 1 + } + } else + dosub = NO + + # Open the images to be added. In most cases there will be one + # such image. + if (finish > ofinish) { + doadd = YES + j = 1 + do i = ofinish + 1, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + Memi[imadd+j-1] = immap (Memc[image], READ_ONLY, 0) + iferr (Memr[norma+j-1] = imgetr (Memi[imadd+j-1], skyscale)) + Memr[norma+j-1] = 1.0 + #normsum = normsum + Memr[norma+j-1] + } + j = j + 1 + } + } else + doadd = NO + + # Make the vector operators in-line code later if necessary. + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vsub], nsub * IM_MAXDIM) + call amovkl (long(1), Meml[vadd], nadd * IM_MAXDIM) + call amovkl (long(1), Meml[vout], IM_MAXDIM) + npix = IM_LEN(tmpim,1) + while (impnlr (tmpim, obuf, Meml[vout]) != EOF && + imgnlr (tmpim, ibuf, Meml[vin]) != EOF) { + if (dosub == YES && doadd == YES) { + do i = 1, nsub { + if (imgnlr (Memi[imsub+i-1], sbuf, + Meml[vsub+(i-1)*nsub]) != EOF) { + call amulkr (Memr[sbuf], Memr[norms+i-1], Memr[sbuf], + npix) + if (i == 1) + call asubr (Memr[ibuf], Memr[sbuf], Memr[obuf], + npix) + else + call asubr (Memr[obuf], Memr[sbuf], Memr[obuf], + npix) + } + } + do i = 1, nadd { + if (imgnlr (Memi[imadd+i-1], abuf, + Meml[vadd+(i-1)*nadd]) != EOF) { + call amulkr (Memr[abuf], Memr[norma+i-1], Memr[abuf], + npix) + call aaddr (Memr[obuf], Memr[abuf], Memr[obuf], npix) + } + } + } else if (dosub == YES) { + do i = 1, nsub { + if (imgnlr (Memi[imsub+i-1], sbuf, + Meml[vsub+(i-1)*nsub]) != EOF) { + call amulkr (Memr[sbuf], Memr[norms+i-1], Memr[sbuf], + npix) + if (i == 1) + call asubr (Memr[ibuf], Memr[sbuf], Memr[obuf], + npix) + else + call asubr (Memr[obuf], Memr[sbuf], Memr[obuf], + npix) + } + } + } else if (doadd == YES) { + do i = 1, nadd { + if (imgnlr (Memi[imadd+i-1], abuf, + Meml[vadd+(i-1)*nadd]) != EOF) { + call amulkr (Memr[abuf], Memr[norma+i-1], Memr[abuf], + npix) + if ( i == 1) + call aaddr (Memr[ibuf], Memr[abuf], Memr[obuf], + npix) + else + call aaddr (Memr[obuf], Memr[abuf], Memr[obuf], + npix) + } + } + } + } + + # Close the images to be added or subtracted. + do i = 1, nsub { + call imunmap (Memi[imsub+i-1]) + } + do i = 1, nadd { + call imunmap (Memi[imadd+i-1]) + } + + call sfree (sp) +end + + +# RS_IPTRS -- Get the initial set of image points. + +procedure rs_iptrs (inlist, imptrs, imids, start, finish, cache, oldsize) + +int inlist #I the input image list +pointer imptrs[ARB] #O the input image pointers +int imids[ARB] #O the input image ids +int start #I the starting image in the series +int finish #I the ending image in the serious +bool cache #I cache the image in memory ? +int oldsize #O the original working set size + +pointer sp, image +int n, i, bufsize +pointer immap() +int imtrgetim(), btoi() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + + n = 1 + do i = start, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + imids[n] = i + imptrs[n] = immap (Memc[image], READ_ONLY, 0) + call rs_cachen (btoi(cache), n, imptrs[n], bufsize) + if (n == 1) + oldsize = bufsize + n = n + 1 + } + } + + call sfree (sp) +end + + +# RS_ASPTRS -- Advance the image pointer and id buffers for the next +# current image. + +procedure rs_asptrs (inlist, imptrs, imids, start, finish, ostart, ofinish, + cache) + +int inlist #I the input image list +pointer imptrs[ARB] #U the input image pointers +int imids[ARB] #U the input image ids +int start #I the starting image in the series +int finish #I the ending image in the serious +int ostart #I the old starting image in the series +int ofinish #I the old ending image in the serious +bool cache #I cache image buffers ? + +pointer sp, image +int i, n, nold, nsub, nadd, bufsize +pointer immap() +int imtrgetim(), btoi() + +begin + # No new images are added or deleted. + if (start == ostart && finish == ofinish) + return + + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + + nold = ofinish - start + 1 + + # Delete some images from the combine list. + nsub = start - ostart + if (nsub > 0) { + # Unmap the images to be deleted. + do i = 1, nsub { + call imunmap (imptrs[i]) + } + # Rotate the image pointer buffer. + do i = 1, nold { + imptrs[i] = imptrs[i+nsub] + imids[i] = imids[i+nsub] + } + } + + # Add new images to the combine list. Note that the cacheing + # mechanism must include the temporary image hence a request for + # n + 1 cached image buffers is issued instead of a request for n. + nadd = finish - ofinish + if (nadd > 0) { + n = nold + 1 + do i = ofinish + 1, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + imptrs[n] = immap (Memc[image], READ_ONLY, 0) + imids[n] = i + if ((finish - start) > (ofinish - ostart)) + call rs_cachen (btoi(cache), n+1, imptrs[n], bufsize) + n = n + 1 + } + } + } + + call sfree (sp) +end + + +# RS_RMNORM -- Compute the normalization factor for the new output image. + +procedure rs_rmnorm (rs, im, tmpim, outim, fscale) + +pointer rs #I the sky subtraction structure +pointer im #I the input image descriptor +pointer tmpim #I the storage image descriptor +pointer outim #I the output image descriptor +real fscale #O the scaling factor + +real rmin, rmax +pointer sp, vout, vin, vtmp, obuf, tmpbuf, ibuf +int i, npix +int impnlr(), imgnlr() + +begin + call smark (sp) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + + # Compute the normalized input image. + npix = IM_LEN(im,1) + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (tmpim, tmpbuf, Meml[vtmp]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF) { + do i = 1, npix { + if (Memr[tmpbuf+i-1] == 0.0) + Memr[obuf+i-1] = Memr[ibuf+i-1] + else + Memr[obuf+i-1] = Memr[ibuf+i-1] / Memr[tmpbuf+i-1] + } + } + + # Compute the normalization factor. Set the good data limits to + # INDEF for this case + rmin = RS_LOWER(rs) + rmax = RS_UPPER(rs) + RS_LOWER(rs) = INDEFR + RS_UPPER(rs) = INDEFR + call rs_med (outim, rs, fscale) + RS_LOWER(rs) = rmin + RS_UPPER(rs) = rmax + + call sfree (sp) +end + + +# RS_RMOUT -- Compute the output sky subtracted image. + +procedure rs_rmout (im, tmpim, outim, fscale, skysub) + +pointer im #I the input image descriptor +pointer tmpim #I the temporary image descriptor +pointer outim #I the output image descriptor +real fscale #I the scaling factor +char skysub[ARB] #I the skyscale keyword + +pointer sp, vout, vtmp, vin, str, obuf, tmpbuf, ibuf +int npix +int imgnlr(), impnlr() + +begin + call smark (sp) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + call salloc (str, SZ_FNAME, TY_CHAR) + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + + # Add keyword to image header. + call sprintf (Memc[str], SZ_FNAME, + "Sky subtracted with scale factor = %g") + call pargr (fscale) + call imastr (outim, skysub, Memc[str]) + + # Normalize the output image. + npix = IM_LEN(im,1) + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (tmpim, tmpbuf, Meml[vtmp]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF) { + call amulkr (Memr[tmpbuf], fscale, Memr[obuf], npix) + call asubr (Memr[ibuf], Memr[obuf], Memr[obuf], npix) + } + + call sfree (sp) +end + + +# RS_DIVERR -- Function for divide by zero error. + +#real procedure rs_diverr (rval) + +#real rval #I input return value. + +#begin +# return (rval) +#end diff --git a/pkg/proto/masks/rsmmean.x b/pkg/proto/masks/rsmmean.x new file mode 100644 index 00000000..a6ea102b --- /dev/null +++ b/pkg/proto/masks/rsmmean.x @@ -0,0 +1,1673 @@ +include <imhdr.h> +include <imset.h> +include <pmset.h> +include "rskysub.h" + +# RS_PRRMSUB -- Perform a running mean sky subtraction on a list of images +# with masking and minmax rejection using a cylindrical buffer of image +# pointers. + +procedure rs_prrmsub (inlist, msklist, outlist, hmsklist, rs, msk_invert, + cache, verbose) + +int inlist #I the input image list +int msklist #I the input mask list +int outlist #I the output image list +int hmsklist #I the output holes mask list +pointer rs #I the sky subtraction descriptor +bool msk_invert #I invert the input masks ? +bool cache #I cache temp image buffer in memory ? +bool verbose #I print task statistics + +real flow, fhigh, fscale +pointer sp, image, imask, outimage, tmpimage, tmpmask, imptrs, mskptrs, str +pointer hmask, imids, tmpim, tmpmsk, im, pmim, outim, hmim +int i, imno, nlo, nhi, ostart, ofinish, start, finish, nimages, old_size +int new_size, first, last, hstat +pointer immap(), im_pmmap() +int imtlen(), imtrgetim(), btoi(), imaccess(), rs_prmout(), imstati() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imask, SZ_FNAME, TY_CHAR) + call salloc (outimage, SZ_FNAME, TY_CHAR) + call salloc (hmask, SZ_FNAME, TY_CHAR) + call salloc (tmpimage, SZ_FNAME, TY_CHAR) + call salloc (tmpmask, SZ_FNAME, TY_CHAR) + call salloc (imptrs, RS_NCOMBINE(rs) + 1, TY_POINTER) + call salloc (mskptrs, RS_NCOMBINE(rs) + 1, TY_POINTER) + call salloc (imids, RS_NCOMBINE(rs) + 1, TY_INT) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Check image status. If resubtract is yes then delete the output + # images if they already exist. Otherwise determine whether the + # images already exist and if so whether or not they need to be + # sky subtracted again. + + nimages = imtlen (inlist) + if (RS_RESUBTRACT(rs) == NO) { + first = 0 + last = 0 + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == NO) { + if (first == 0) { + first = i + last = i + } else + last = i + } else { + outim = immap (Memc[outimage], READ_ONLY, 0) + iferr (call imgstr (outim, RS_KYSKYSUB(rs), Memc[str], + SZ_FNAME)) { + if (first == 0) { + first = i + last = i + } else + last = i + } + call imunmap (outim) + } + } + } else { + first = 1 + last = nimages + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == YES) + call imdelete (Memc[outimage]) + if (imtrgetim (hmsklist, i, Memc[hmask], SZ_FNAME) == EOF) + next + if (imaccess (Memc[hmask], 0) == YES) + call imdelete (Memc[hmask]) + } + } + + # Check the sky subtraction status. + if (first <= 0 && last <= 0) { + if (verbose) { + call printf ( + "The output images have already been sky subtracted \n") + } + call sfree (sp) + return + } + + # Create the temporary image. + call mktemp ("_rsum", Memc[tmpimage], SZ_FNAME) + tmpim = immap (Memc[tmpimage], NEW_IMAGE, 0) + + # Make temporary mask image. Use pmmap instead of immap ? Set mask + # to 8 bits deep to save space. This assumes no more than 255 + # images are averaged. This mask will get converted to a 1 bit + # holes masks if holes mask are saved. + call mktemp ("_rnpts", Memc[tmpmask], SZ_FNAME) + tmpmsk = immap (Memc[tmpmask], NEW_IMAGE, 0) + + # Compute the sliding mean parameters. + nlo = RS_NCOMBINE(rs) / 2 + nhi = RS_NCOMBINE(rs) - nlo + + # Loop over the images. + ostart = 0 + ofinish = 0 + do imno = 1, nimages { + + # Skip over beginning and ending images that have already been + # sky subtracted. + + if (imno < first || imno > last) { + if (verbose) { + if (imtrgetim (outlist, imno, Memc[outimage], + SZ_FNAME) == EOF) { + call printf ( + "The sky subtracted image %s already exists\n") + call pargstr (Memc[outimage]) + } + } + next + } + + # Determine which images will contribute to the sky image. + # Start and finish set the endpoints of the sequence. Imno + # is the current image which is to be sky subtracted. + + if ((imno - nlo) < 1) { + start = 1 + finish = min (nimages, max (2 * imno - 1, RS_NMIN(rs) + 1)) + } else if ((imno + nhi) > nimages) { + start = max (1, min (2 * imno - nimages, nimages - RS_NMIN(rs))) + finish = nimages + } else { + start = imno - nlo + finish = imno + nhi + } + + # Check that the minimum number of images exists. + if ((finish - start) < RS_NMIN(rs)) { + call eprintf ("There are too few images for sky subtraction\n") + break + } + + # Get the input image name. + if (imtrgetim (inlist, imno, Memc[image], SZ_FNAME) == EOF) { + call eprintf ("Error reading input image list\n") + break + } + + # Get the input mask name. + if (imtrgetim (msklist, imno, Memc[imask], SZ_FNAME) == EOF) { + call eprintf ("Error reading input mask list\n") + break + } + + # Get the output image name. + if (imtrgetim (outlist, imno, Memc[outimage], SZ_FNAME) == EOF) { + call eprintf ("Error reading output image list\n") + break + } + + # Get the holes mask name. + if (imtrgetim (hmsklist, imno, Memc[hmask], SZ_FNAME) == EOF) + Memc[hmask] = EOS + + if (verbose) { + call printf ( + "Sky subtracting image %s using mask %s and writing to %s\n") + call pargstr (Memc[image]) + call pargstr (Memc[imask]) + call pargstr (Memc[outimage]) + call flush (STDOUT) + } + + # Accumulate the running mean. The first time through the loop + # the number of dimensions, size, and pixel type of the temporary + # storage image and mask are set and the first set of images are + # accumulated into the temporary image. Attempt to cache the + # input image. It is probably not necessary to cache the mask + # since it is already in memory ... + if (imno == start) { + call rs_piptrs (inlist, msklist, Memi[imptrs], Memi[mskptrs], + Memi[imids], start, finish, msk_invert, cache, old_size) + IM_NDIM(tmpim) = IM_NDIM(Memi[imptrs]) + call amovl (IM_LEN(Memi[imptrs],1), IM_LEN(tmpim,1), IM_MAXDIM) + IM_PIXTYPE(tmpim) = TY_REAL + call rs_cachen (btoi(cache), (finish - start + 2), tmpim, + new_size) + IM_NDIM(tmpmsk) = IM_NDIM(Memi[imptrs]) + call amovl (IM_LEN(Memi[imptrs],1), IM_LEN(tmpmsk,1), IM_MAXDIM) + IM_PIXTYPE(tmpmsk) = TY_INT + call rs_cachen (btoi(cache), (finish - start + 3), tmpmsk, + new_size) + } else { + call rs_pasptrs (inlist, msklist, Memi[imptrs], Memi[mskptrs], + Memi[imids], start, finish, ostart, ofinish, msk_invert, + cache) + } + + # Determine the input image and mask pointers. + im = NULL + pmim = NULL + do i = 1, finish - start + 1 { + if (Memi[imids+i-1] != imno) + next + im = Memi[imptrs+i-1] + pmim = Memi[mskptrs+i-1] + break + } + + iferr { + outim = immap (Memc[outimage], NEW_COPY, im) + } then { + call eprintf ("Error opening output image %s\n") + call pargstr (Memc[outimage]) + + } else { + + # Cache the output image. + call rs_cachen (btoi(cache), (finish - start + 3), outim, + new_size) + + if (Memc[hmask] == EOS) + hmim = NULL + else { + hmim = im_pmmap (Memc[hmask], NEW_IMAGE, 0) + call pm_ssize (imstati(hmim, IM_PLDES), IM_NDIM(outim), + IM_LEN(outim,1), 1) + } + + # Accumulate the sky image. + if (RS_COMBINE(rs) == RS_MEAN) { + flow = RS_NLOREJ(rs) + if (RS_NLOREJ(rs) >= 1) + flow = flow / (finish - start) + else + flow = 0.0 + fhigh = RS_NHIREJ(rs) + if (RS_NHIREJ(rs) >= 1) + fhigh = fhigh / (finish - start) + else + fhigh = 0.0 + call rs_apsumr (Memi[imptrs], Memi[mskptrs], Memi[imids], + tmpim, tmpmsk, start, finish, imno, flow, fhigh, + RS_KYFSCALE(rs)) + } else { + call rs_apsumr (Memi[imptrs], Memi[mskptrs], Memi[imids], + tmpim, tmpmsk, start, finish, imno, INDEFR, INDEFR, + RS_KYFSCALE(rs)) + } + + # Compute the new normalization factor. + call rs_prmnorm (rs, im, pmim, tmpim, tmpmsk, outim, fscale) + + # Write the output image. + hstat = rs_prmout (im, tmpim, tmpmsk, outim, hmim, + RS_BLANK(rs), fscale, RS_KYSKYSUB(rs)) + + # Close up images. + if (hmim != NULL) { + if (hstat == YES) { + call pm_savef (imstati (hmim, IM_PLDES), Memc[hmask], + "", 0) + call imastr (outim, RS_KYHMASK(rs), Memc[hmask]) + } + call imunmap (hmim) + } + call imunmap (outim) + } + + # Close up remaining buffered images + if (imno == last) { + do i = 1, finish - start + 1 + call imunmap (Memi[mskptrs+i-1]) + call imunmap (Memi[imptrs+i-1]) + } + + ostart = start + ofinish = finish + + } + + # Close and delete temporary image. + call imunmap (tmpmsk) + call imunmap (tmpim) + call imdelete (Memc[tmpimage]) + call imdelete (Memc[tmpmask]) + + call fixmem (old_size) + + call sfree (sp) +end + + +# RS_PRMSUB -- Perform a running mean sky subtraction on a list of images +# with masking and minmax rejection using input and output image lists. + +procedure rs_prmsub (inlist, msklist, outlist, hmsklist, rs, msk_invert, + cache, verbose) + +int inlist #I the input image list +int msklist #I the input mask list +int outlist #I the output image list +int hmsklist #I the output mask list +pointer rs #I the sky subtraction descriptor +bool msk_invert #I invert the input masks ? +bool cache #I cache temp image buffer in memory ? +bool verbose #I print task statistics + +real flow, fhigh, fscale +pointer sp, image, imask, outimage, tmpimage, tmpmask, hmask, str +pointer tmpim, tmpmsk, im, pmim, outim, hmim +int i, imno, nlo, nhi, ostart, ofinish, start, finish, nimages, old_size +int new_size, first, last, hstat +pointer immap(), im_pmmap(), mp_open() +int imtlen(), imtrgetim(), btoi(), imaccess(), rs_prmout(), imstati() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imask, SZ_FNAME, TY_CHAR) + call salloc (outimage, SZ_FNAME, TY_CHAR) + call salloc (hmask, SZ_FNAME, TY_CHAR) + call salloc (tmpimage, SZ_FNAME, TY_CHAR) + call salloc (tmpmask, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Check image status. If resubtract is yes then delete the output + # images if they already exist. Otherwise determine whether the + # images already exist and if so whether or not they need to be + # sky again. + + nimages = imtlen (inlist) + if (RS_RESUBTRACT(rs) == NO) { + first = 0 + last = 0 + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == NO) { + if (first == 0) { + first = i + last = i + } else + last = i + } else { + outim = immap (Memc[outimage], READ_ONLY, 0) + iferr (call imgstr (outim, RS_KYSKYSUB(rs), Memc[str], + SZ_FNAME)) { + if (first == 0) { + first = i + last = i + } else + last = i + } + call imunmap (outim) + } + } + } else { + first = 1 + last = nimages + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == YES) + call imdelete (Memc[outimage]) + if (imtrgetim (hmsklist, i, Memc[hmask], SZ_FNAME) == EOF) + next + if (imaccess (Memc[hmask], 0) == YES) + call imdelete (Memc[hmask]) + } + } + + # Check the sky subtraction status. + if (first <= 0 && last <= 0) { + if (verbose) { + call printf ( + "The output images have already been sky subtracted \n") + } + call sfree (sp) + return + } + + # Create the temporary image. + call mktemp ("_rsum", Memc[tmpimage], SZ_FNAME) + tmpim = immap (Memc[tmpimage], NEW_IMAGE, 0) + + # Make temporary mask image. Use pmmap instead of immap? Set mask + # to 8 bits deep to save space. This assumes no more than 255 + # images are averaged. This mask will get converted to a 1 bit + # holes masks if holes mask are saved. + call mktemp ("_rnpts", Memc[tmpmask], SZ_FNAME) + tmpmsk = immap (Memc[tmpmask], NEW_IMAGE, 0) + + # Compute the sliding mean parameters. + nlo = RS_NCOMBINE(rs) / 2 + nhi = RS_NCOMBINE(rs) - nlo + + # Loop over the images. + ostart = 0 + ofinish = 0 + do imno = 1, nimages { + + # Skip over beginning and ending images that have already been + # sky subtracted. + + if (imno < first || imno > last) { + if (verbose) { + if (imtrgetim (outlist, imno, Memc[outimage], + SZ_FNAME) == EOF) { + call printf ( + "The sky subtracted image %s already exists\n") + call pargstr (Memc[outimage]) + } + } + next + } + + # Determine which images will contribute to the sky image. + # Start and finish set the endpoints of the sequence. Imno + # is the current image which is to be sky subtracted. + + if ((imno - nlo) < 1) { + start = 1 + finish = min (nimages, max (2 * imno - 1, RS_NMIN(rs) + 1)) + } else if ((imno + nhi) > nimages) { + start = max (1, min (2 * imno - nimages, nimages - RS_NMIN(rs))) + finish = nimages + } else { + start = imno - nlo + finish = imno + nhi + } + + # Check that the minimum number of images exists. + if ((finish - start) < RS_NMIN(rs)) { + call eprintf ("There are too few images for sky subtraction\n") + break + } + + # Open the current input image. + if (imtrgetim (inlist, imno, Memc[image], SZ_FNAME) == EOF) { + call eprintf ("Error reading input image list\n") + break + } + iferr (im = immap (Memc[image], READ_ONLY, 0)) { + call eprintf ("Error opening input image %s\n") + call pargstr (Memc[image]) + break + } + + # Open the current input mask. + if (imtrgetim (msklist, imno, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + pmim = mp_open (Memc[str], im, Memc[imask], SZ_FNAME) + } else + pmim = mp_open (Memc[str+1], im, Memc[imask], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], SZ_FNAME) != EOF) { + pmim = mp_open (Memc[str], im, Memc[imask], SZ_FNAME) + } else { + call printf ("Error reading mask for image %s ...\n") + call pargstr (Memc[image]) + call imunmap (im) + break + } + + # Open the output image. At present this is the combined sky image. + # Eventually it will be the sky subtracted input image. Assume + # that the input and output lists are now the same size. + + if (imtrgetim (outlist, imno, Memc[outimage], SZ_FNAME) == EOF) { + call eprintf ("Error reading output image list\n") + call imunmap (im) + break + } + iferr (outim = immap (Memc[outimage], NEW_COPY, im)) { + call eprintf ("Error opening output image %s\n") + call pargstr (Memc[outimage]) + call imunmap (pmim) + call imunmap (im) + break + } + call rs_cachen (btoi(cache), 1, outim, old_size) + + # Open the holes mask as a virtual mask. + if (imtrgetim (hmsklist, imno, Memc[hmask], SZ_FNAME) != EOF) { + hmim = im_pmmap (Memc[hmask], NEW_IMAGE, 0) + call pm_ssize (imstati(hmim, IM_PLDES), IM_NDIM(outim), + IM_LEN(outim,1), 1) + } else { + hmim = NULL + } + + if (verbose) { + call printf ( + "Sky subtracting image %s using mask %s and writing to %s\n") + call pargstr (Memc[image]) + call pargstr (Memc[imask]) + call pargstr (Memc[outimage]) + call flush (STDOUT) + } + + # Accumulate the running mean. The first time through the loop + # the number of dimensions, size, and pixel type of the temporary + # storage image and mask are set and the first set of images are + # accumulated into the temporary image. Attempt to cache the + # input image. It is probably not necessary to cache the mask + # since it is already in memory ... + if (imno == first) { + IM_NDIM(tmpim) = IM_NDIM(im) + call amovl (IM_LEN(im,1), IM_LEN(tmpim,1), IM_MAXDIM) + IM_PIXTYPE(tmpim) = TY_REAL + call rs_cachen (btoi(cache), 2, tmpim, new_size) + IM_NDIM(tmpmsk) = IM_NDIM(im) + call amovl (IM_LEN(im,1), IM_LEN(tmpmsk,1), IM_MAXDIM) + IM_PIXTYPE(tmpmsk) = TY_INT + call rs_cachen (btoi(cache), 3, tmpmsk, new_size) + } + + # Accumulate the sky image. + if (RS_COMBINE(rs) == RS_MEAN) { + flow = RS_NLOREJ(rs) + if (RS_NLOREJ(rs) >= 1) + flow = flow / (finish - start) + else + flow = 0.0 + fhigh = RS_NHIREJ(rs) + if (RS_NHIREJ(rs) >= 1) + fhigh = fhigh / (finish - start) + else + fhigh = 0.0 + call rs_psumr (inlist, msklist, tmpim, tmpmsk, start, finish, + imno, flow, fhigh, msk_invert, RS_KYFSCALE(rs)) + } else + call rs_psumr (inlist, msklist, tmpim, tmpmsk, start, finish, + imno, INDEFR, INDEFR, msk_invert, RS_KYFSCALE(rs)) + + + # Compute the new normalization factor. + call rs_prmnorm (rs, im, pmim, tmpim, tmpmsk, outim, fscale) + + # Write the output image. + hstat = rs_prmout (im, tmpim, tmpmsk, outim, hmim, RS_BLANK(rs), + fscale, RS_KYSKYSUB(rs)) + + # Close up images. + if (hmim != NULL) { + if (hstat == YES) { + call pm_savef (imstati (hmim, IM_PLDES), Memc[hmask], "", 0) + call imastr (outim, RS_KYHMASK(rs), Memc[hmask]) + } + call imunmap (hmim) + } + call imunmap (outim) + call imunmap (pmim) + call imunmap (im) + + ostart = start + ofinish = finish + + } + + # Close and delete temporary image. + call imunmap (tmpmsk) + call imunmap (tmpim) + call imdelete (Memc[tmpimage]) + call imdelete (Memc[tmpmask]) + + call fixmem (old_size) + + call sfree (sp) +end + + +# RS_PMSUB -- Perform a running mean sky subtraction on a list of images +# with masking but no rejection. + +procedure rs_pmsub (inlist, msklist, outlist, hmsklist, rs, msk_invert, + cache, verbose) + +int inlist #I the input image list +int msklist #I the input mask list +int outlist #I the output image list +int hmsklist #I the output holes mask list +pointer rs #I the sky subtraction descriptor +bool msk_invert #I invert the input masks ? +bool cache #I cache temp image buffer in memory ? +bool verbose #I print task statistics + +real fscale +pointer sp, image, imask, outimage, hmask, tmpimage, tmpmask, str +pointer tmpim, tmpmsk, im, pmim, outim, hmim +int i, imno, nlo, nhi, ostart, ofinish, start, finish, nimages, old_size +int new_size, first, last, hstat +pointer immap(), mp_open(), im_pmmap() +int imtlen(), imtrgetim(), btoi(), imaccess(), imstati(), rs_pmout() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imask, SZ_FNAME, TY_CHAR) + call salloc (outimage, SZ_FNAME, TY_CHAR) + call salloc (hmask, SZ_FNAME, TY_CHAR) + call salloc (tmpimage, SZ_FNAME, TY_CHAR) + call salloc (tmpmask, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Check image status. If resubtract is yes then delete the output + # images if they already exist. Otherwise determine whether the + # images already exist and if so whether or not they need to be + # sky again. + + nimages = imtlen (inlist) + if (RS_RESUBTRACT(rs) == NO) { + first = 0 + last = 0 + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == NO) { + if (first == 0) { + first = i + last = i + } else + last = i + } else { + outim = immap (Memc[outimage], READ_ONLY, 0) + iferr (call imgstr (outim, RS_KYSKYSUB(rs), Memc[str], + SZ_FNAME)) { + if (first == 0) { + first = i + last = i + } else + last = i + } + call imunmap (outim) + } + } + } else { + first = 1 + last = nimages + do i = 1, nimages { + if (imtrgetim (outlist, i, Memc[outimage], SZ_FNAME) == EOF) + break + if (imaccess (Memc[outimage], 0) == YES) + call imdelete (Memc[outimage]) + if (imtrgetim (hmsklist, i, Memc[hmask], SZ_FNAME) == EOF) + next + if (imaccess (Memc[hmask], 0) == YES) + call imdelete (Memc[hmask]) + } + } + + # Check the sky subtraction status. + if (first <= 0 && last <= 0) { + if (verbose) { + call printf ( + "The output images have already been sky subtracted \n") + } + call sfree (sp) + return + } + + + # Create the temporary image. + call mktemp ("_rsum", Memc[tmpimage], SZ_FNAME) + tmpim = immap (Memc[tmpimage], NEW_IMAGE, 0) + + # Make temporary mask image. Use pmmap instead of immap? Set mask + # to 8 bits deep to save space. This assumes no more than 255 + # images are averaged. This mask will get converted to a 1 bit + # holes masks if holes mask are saved. + call mktemp ("_rnpts", Memc[tmpmask], SZ_FNAME) + tmpmsk = immap (Memc[tmpmask], NEW_IMAGE, 0) + + # Compute the sliding mean parameters. + nlo = RS_NCOMBINE(rs) / 2 + nhi = RS_NCOMBINE(rs) - nlo + + # Loop over the images. + ostart = 0 + ofinish = 0 + do imno = 1, nimages { + + # Skip over beginning and ending images that have already been + # sky subtracted. + + if (imno < first || imno > last) { + if (verbose) { + if (imtrgetim (outlist, imno, Memc[outimage], + SZ_FNAME) == EOF) { + call printf ( + "The sky subtracted image %s already exists\n") + call pargstr (Memc[outimage]) + } + } + next + } + + # Determine which images will contribute to the sky image. + # Start and finish set the endpoints of the sequence. Imno + # is the current image which is to be sky subtracted. + + if ((imno - nlo) < 1) { + start = 1 + finish = min (nimages, max (2 * imno - 1, RS_NMIN(rs) + 1)) + } else if ((imno + nhi) > nimages) { + start = max (1, min (2 * imno - nimages, nimages - RS_NMIN(rs))) + finish = nimages + } else { + start = imno - nlo + finish = imno + nhi + } + + # Check that the minimum number of images exists. + if ((finish - start) < RS_NMIN(rs)) { + call eprintf ("There are too few images for sky subtraction\n") + break + } + + # Open the current input image. + if (imtrgetim (inlist, imno, Memc[image], SZ_FNAME) == EOF) { + call eprintf ("Error reading input image list\n") + break + } + iferr (im = immap (Memc[image], READ_ONLY, 0)) { + call eprintf ("Error opening input image %s\n") + call pargstr (Memc[image]) + break + } + + # Get the input mask. + if (imtrgetim (msklist, imno, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + pmim = mp_open (Memc[str], im, Memc[imask], SZ_FNAME) + } else + pmim = mp_open (Memc[str+1], im, Memc[imask], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], SZ_FNAME) != EOF) { + pmim = mp_open (Memc[str], im, Memc[imask], SZ_FNAME) + } else { + call printf ("Error reading mask for image %s ...\n") + call pargstr (Memc[image]) + call imunmap (im) + break + } + + # Open the output image. + if (imtrgetim (outlist, imno, Memc[outimage], SZ_FNAME) == EOF) { + call eprintf ("Error reading output image list\n") + call imunmap (pmim) + call imunmap (im) + break + } + iferr (outim = immap (Memc[outimage], NEW_COPY, im)) { + call eprintf ("Error opening output image %s\n") + call pargstr (Memc[outimage]) + call imunmap (pmim) + call imunmap (im) + break + } + + # Open the holes mask as a virtual mask. + if (imtrgetim (hmsklist, imno, Memc[hmask], SZ_FNAME) != EOF) { + hmim = im_pmmap (Memc[hmask], NEW_IMAGE, 0) + call pm_ssize (imstati(hmim, IM_PLDES), IM_NDIM(outim), + IM_LEN(outim,1), 1) + } else { + hmim = NULL + } + + if (verbose) { + call printf ( + "Sky subtracting image %s using mask %s and writing to %s\n") + call pargstr (Memc[image]) + call pargstr (Memc[imask]) + call pargstr (Memc[outimage]) + call flush (STDOUT) + } + + # Accumulate the running mean. The first time through the loop + # the number of dimensions, size, and pixel type of the temporary + # storage image and mask are set and the first set of images are + # accumulated into the temporary image. Attempt to cache the + # input image. It is probably not necessary to cache the mask + # since it is already in memory ... + if (imno == first) { + IM_NDIM(tmpim) = IM_NDIM(im) + call amovl (IM_LEN(im,1), IM_LEN(tmpim,1), IM_MAXDIM) + IM_PIXTYPE(tmpim) = TY_REAL + call rs_cache1 (btoi(cache), tmpim, old_size) + IM_NDIM(tmpmsk) = IM_NDIM(im) + call amovl (IM_LEN(im,1), IM_LEN(tmpmsk,1), IM_MAXDIM) + IM_PIXTYPE(tmpmsk) = TY_INT + call rs_cachen (btoi(cache), 2, tmpmsk, new_size) + call rs_pminit (inlist, msklist, msk_invert, tmpim, tmpmsk, + start, finish, RS_KYFSCALE(rs)) + } else if ((ostart > 0 && start > ostart) || (ofinish > 0 && + finish > ofinish)) { + call rs_pmaddsub (inlist, msklist, msk_invert, tmpim, tmpmsk, + start, finish, ostart, ofinish, RS_KYFSCALE(rs)) + } + + # Cache the input and output images. + call rs_cachen (btoi(cache), 3, im, new_size) + call rs_cachen (btoi(cache), 4, outim, new_size) + + # Compute the normalization factor. + call rs_pmnorm (rs, im, pmim, tmpim, tmpmsk, outim, fscale) + + # Write the output image. + hstat = rs_pmout (im, pmim, tmpim, tmpmsk, outim, hmim, + RS_BLANK(rs), fscale, RS_KYFSCALE(rs), RS_KYSKYSUB(rs)) + + # Close up images. + if (hmim != NULL) { + if (hstat == YES) + call pm_savef (imstati(hmim, IM_PLDES), Memc[hmask], "", 0) + call imunmap (hmim) + } + call imunmap (outim) + call imunmap (pmim) + call imunmap (im) + + ostart = start + ofinish = finish + + } + + # Close and delete temporary image. + call imunmap (tmpmsk) + call imunmap (tmpim) + call imdelete (Memc[tmpimage]) + call imdelete (Memc[tmpmask]) + + call fixmem (old_size) + + call sfree (sp) +end + + +# RS_PMINIT -- Initialize the accumulation buffer for the running median +# using masks. + +procedure rs_pminit (inlist, msklist, msk_invert, tmpim, tmpmsk, start, + finish, skyscale) + +int inlist #I the input image list +int msklist #I the input mask list +bool msk_invert #I invert the input masks +pointer tmpim #I the output storage image +pointer tmpmsk #I the output mask counts image +int start #I the starting image in the list +int finish #I the ending image in the list +#real normsum #U the normalization accumulator +char skyscale[ARB] #I the scaling factor keyword + +pointer sp, image, imask, imptrs, mkptrs, mpptrs, imnorm +pointer vout, mvout, vs, ve, vin +pointer str, obuf, ibuf, ombuf +int i, j, nin, npix, mval, npts +real imgetr() +pointer immap(), mp_open(), mio_openo() +int imtrgetim(), impnlr(), impnli(), mio_glsegr(), imstati() +errchk imgetr() + +begin + nin = finish - start + 1 + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imask, SZ_FNAME, TY_CHAR) + call salloc (imptrs, nin, TY_INT) + call salloc (imnorm, nin, TY_REAL) + call salloc (mkptrs, nin, TY_INT) + call salloc (mpptrs, nin, TY_INT) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (mvout, IM_MAXDIM, TY_LONG) + call salloc (vs, IM_MAXDIM, TY_LONG) + call salloc (ve, IM_MAXDIM, TY_LONG) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Open the initial input images and masks. + j = 1 + #normsum = 0.0 + do i = start, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) == EOF) + ; + Memi[imptrs+j-1] = immap (Memc[image], READ_ONLY, 0) + if (imtrgetim (msklist, i, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + Memi[mkptrs+j-1] = mp_open (Memc[str], Memi[imptrs+j-1], + Memc[imask], SZ_FNAME) + } else { + Memi[mkptrs+j-1] = mp_open (Memc[str+1], Memi[imptrs+j-1], + Memc[imask], SZ_FNAME) + } + } else if (imtrgetim (msklist, 1, Memc[str], SZ_FNAME) != EOF) { + Memi[mkptrs+j-1] = mp_open (Memc[str], Memi[imptrs+j-1], + Memc[imask], SZ_FNAME) + } else { + Memi[mkptrs+j-1] = mp_open ("", Memi[imptrs+j-1], Memc[imask], + SZ_FNAME) + } + Memi[mpptrs+j-1] = mio_openo (imstati(Memi[mkptrs+j-1], IM_PLDES), + Memi[imptrs+j-1]) + iferr (Memr[imnorm+j-1] = imgetr (Memi[imptrs+j-1], skyscale)) + Memr[imnorm+j-1] = 1.0 + #normsum = normsum + 1.0 + #else + #normsum = normsum + Memr[imnorm+j-1] + j = j + 1 + } + + # Initialize image and mask i/o. + npix = IM_LEN(tmpim,1) + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[mvout], IM_MAXDIM) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + call amovkl (long(1), Meml[ve], IM_MAXDIM) + Meml[ve] = npix + + # Do the initial accumulation of counts and numbers of pixels. + while (impnlr (tmpim, obuf, Meml[vout]) != EOF && + impnli (tmpmsk, ombuf, Meml[mvout]) != EOF) { + call amovkr (0.0, Memr[obuf], npix) + call amovki (0, Memi[ombuf], npix) + do j = 1, nin { + call mio_setrange (Memi[mpptrs+j-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[imptrs+j-1])) + call amovl (Meml[vs], Meml[vin], IM_MAXDIM) + while (mio_glsegr (Memi[mpptrs+j-1], ibuf, mval, + Meml[vin], npts) != EOF) { + call amulkr (Memr[ibuf], Memr[imnorm+j-1], Memr[ibuf], + npts) + call aaddr (Memr[ibuf], Memr[obuf+Meml[vin]-1], + Memr[obuf+Meml[vin]-1], npts) + call aaddki (Memi[ombuf+Meml[vin]-1], 1, + Memi[ombuf+Meml[vin]-1], npts) + } + } + call amovl (Meml[vout], Meml[vs], IM_MAXDIM) + call amovl (Meml[vout], Meml[ve], IM_MAXDIM) + Meml[vs] = 1 + Meml[ve] = npix + } + + # Close the input images. + do j = 1, nin { + call mio_close (Memi[mpptrs+j-1]) + call imunmap (Memi[mkptrs+j-1]) + call imunmap (Memi[imptrs+j-1]) + } + + call sfree (sp) +end + + +# RS_PMNORM -- Compute the normalized image and the new normalization factor. + +procedure rs_pmnorm (rs, im, pmim, tmpim, tmpmsk, outim, fscale) + +pointer rs #I the sky subtraction descriptor +pointer im #I the input image descriptor +pointer pmim #I pointer to the input mask +pointer tmpim #I the storage image descriptor +pointer tmpmsk #I the counter image descriptor +pointer outim #I the output image descriptor +real fscale #O the new normalization factor + +real norm1, pout, rmin, rmax +pointer sp, vin, vmin, vout, vtmp, vmtmp +pointer obuf, ibuf, imbuf, tbuf, tmbuf +int i, npix, npout +real imgetr() +int impnlr(), imgnlr(), imgnli() +errchk imgetr() + +begin + call smark (sp) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vmin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + call salloc (vmtmp, IM_MAXDIM, TY_LONG) + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vmin], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + call amovkl (long(1), Meml[vmtmp], IM_MAXDIM) + + # Accumulate the normalized input image. + iferr (norm1 = imgetr (im, RS_KYFSCALE(rs))) + norm1 = 1.0 + npix = IM_LEN(im,1) + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF && + imgnli (pmim, imbuf, Meml[vmin]) != EOF && + imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF && + imgnli (tmpmsk, tmbuf, Meml[vmtmp]) != EOF) { + + do i = 1, npix { + if (Memi[imbuf+i-1] > 0) { + pout = Memr[tbuf+i-1] - norm1 * Memr[ibuf+i-1] + npout = Memi[tmbuf+i-1] - 1 + } else { + pout = Memr[tbuf+i-1] + npout = Memi[tmbuf+i-1] + } + if (npout <= 0 || pout == 0.0) + Memr[obuf+i-1] = Memr[ibuf+i-1] + else + Memr[obuf+i-1] = Memr[ibuf+i-1] / (pout / npout) + } + + } + + # Compute the new normalization factor. + rmin = RS_LOWER(rs) + rmax = RS_UPPER(rs) + RS_LOWER(rs) = INDEFR + RS_UPPER(rs) = INDEFR + call rs_mmed (outim, outim, pmim, NULL, rs, fscale) + RS_LOWER(rs) = rmin + RS_UPPER(rs) = rmax + + call sfree (sp) +end + + +# RS_PMOUT -- Write the output image. Subtract the normalized current input +# image and mask from the accumulation buffers before computing the final +# average. + +int procedure rs_pmout (im, pmim, tmpim, tmpmsk, outim, hmim, blank, + fscale, skyscale, skysub) + +pointer im #I the input image descriptor +pointer pmim #I pointer to the input mask +pointer tmpim #I the storage image descriptor +pointer tmpmsk #I the counter image descriptor +pointer outim #I the output image descriptor +pointer hmim #I the output holes mask descriptor +real blank #I the undefined pixel value +real fscale #I the new normalization factor +char skyscale[ARB] #I the sky scaling keyword +char skysub[ARB] #I the sky subtraction keyword + +real norm1, pout +pointer sp, vin, vmin, vout, vtmp, vmtmp, vs, str +pointer obuf, ibuf, imbuf, tbuf, tmbuf, hbuf +int i, npix, npout, stat +real imgetr() +int impnlr(), imgnlr(), imgnli(), imstati() +errchk imgetr() + +begin + call smark (sp) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vmin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + call salloc (vmtmp, IM_MAXDIM, TY_LONG) + call salloc (str, SZ_FNAME, TY_CHAR) + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vmin], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + call amovkl (long(1), Meml[vmtmp], IM_MAXDIM) + + call sprintf (Memc[str], SZ_FNAME, + "Sky subtracted with scale factor = %g") + call pargr (fscale) + call imastr (outim, skysub, Memc[str]) + + iferr (norm1 = imgetr (im, skyscale)) + norm1 = 1.0 + stat = NO + npix = IM_LEN(im,1) + if (hmim == NULL) { + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF && + imgnli (pmim, imbuf, Meml[vmin]) != EOF && + imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF && + imgnli (tmpmsk, tmbuf, Meml[vmtmp]) != EOF) { + + do i = 1, npix { + if (Memi[imbuf+i-1] > 0) { + pout = Memr[tbuf+i-1] - norm1 * Memr[ibuf+i-1] + npout = Memi[tmbuf+i-1] - 1 + } else { + pout = Memr[tbuf+i-1] + npout = Memi[tmbuf+i-1] + } + if (npout <= 0) { + stat = YES + Memr[obuf+i-1] = blank + } else { + Memr[obuf+i-1] = fscale * (pout / npout) + } + } + call asubr (Memr[ibuf], Memr[obuf], Memr[obuf], npix) + } + } else { + call salloc (vs, IM_MAXDIM, TY_LONG) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + call salloc (hbuf, npix, TY_SHORT) + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF && + imgnli (pmim, imbuf, Meml[vmin]) != EOF && + imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF && + imgnli (tmpmsk, tmbuf, Meml[vmtmp]) != EOF) { + + do i = 1, npix { + if (Memi[imbuf+i-1] > 0) { + pout = Memr[tbuf+i-1] - norm1 * Memr[ibuf+i-1] + npout = Memi[tmbuf+i-1] - 1 + } else { + pout = Memr[tbuf+i-1] + npout = Memi[tmbuf+i-1] + } + if (npout <= 0) { + stat = YES + Mems[hbuf+i-1] = 0 + Memr[obuf+i-1] = blank + } else { + Mems[hbuf+i-1] = 1 + Memr[obuf+i-1] = fscale * (pout / npout) + } + } + call asubr (Memr[ibuf], Memr[obuf], Memr[obuf], npix) + + call pm_plps (imstati(hmim, IM_PLDES), Meml[vs], Mems[hbuf], + 1, npix, PIX_SRC) + call amovl (Meml[vin], Meml[vs], IM_MAXDIM) + } + } + + call sfree (sp) + + return (stat) +end + + +# RS_PMADDSUB -- Add images to and subtract images from the accumulation +# buffer using masks. + +procedure rs_pmaddsub (inlist, msklist, msk_invert, tmpim, tmpmsk, start, + finish, ostart, ofinish, skyscale) + +int inlist #I the input image list +int msklist #I the input mask list +bool msk_invert #I invert the input masks +pointer tmpim #I the storage image descriptor +pointer tmpmsk #I the storage counter image +int start #I the current starting image +int finish #I the current ending image +int ostart #I the previous starting image +int ofinish #I the previous ending image +#real normsum #I the norm factor accumulator +char skyscale[ARB] #I the sky scaling keyword + +pointer sp, image, vin, vout, v, imsub, imadd, norma, norms +pointer imask, str, mksub, mkadd, vs, ve, mpsub, mpadd, mvin, mvout +pointer ibuf, obuf, mibuf, mobuf, sbuf, abuf +int i, j, nsub, nadd, npix, doadd, dosub, npts, mval +real imgetr() +pointer immap(), mp_open(), mio_openo() +int imtrgetim(), impnlr(), imgnlr(), impnli(), imgnli(), imstati() +int mio_glsegr() +errchk imgetr() + +begin + if (start == ostart && finish == ofinish) + return + nsub = start - ostart + nadd = finish - ofinish + + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imask, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (mvin, IM_MAXDIM, TY_LONG) + call salloc (mvout, IM_MAXDIM, TY_LONG) + call salloc (vs, IM_MAXDIM, TY_LONG) + call salloc (ve, IM_MAXDIM, TY_LONG) + call salloc (v, IM_MAXDIM, TY_LONG) + + call salloc (imsub, nsub, TY_INT) + call salloc (mksub, nsub, TY_INT) + call salloc (mpsub, nsub, TY_INT) + call salloc (norms, nsub, TY_REAL) + call salloc (imadd, nadd, TY_INT) + call salloc (mkadd, nadd, TY_INT) + call salloc (mpadd, nadd, TY_INT) + call salloc (norma, nadd, TY_REAL) + + # Open the images to be subtracted. In most cases there will be + # one such image. + if (ostart < start) { + dosub = YES + j = 1 + do i = ostart, start - 1 { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + Memi[imsub+j-1] = immap (Memc[image], READ_ONLY, 0) + if (imtrgetim (msklist, i, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + Memi[mksub+j-1] = mp_open (Memc[str], + Memi[imsub+j-1], Memc[imask], SZ_FNAME) + } else + Memi[mksub+j-1] = mp_open (Memc[str+1], + Memi[imsub+j-1], Memc[imask], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], + SZ_FNAME) != EOF) { + Memi[mksub+j-1] = mp_open (Memc[str], Memi[imsub+j-1], + Memc[imask], SZ_FNAME) + } else { + Memi[mksub+j-1] = mp_open ("", Memi[imsub+j-1], + Memc[imask], SZ_FNAME) + } + Memi[mpsub+j-1] = mio_openo (imstati(Memi[mksub+j-1], + IM_PLDES), Memi[imsub+j-1]) + iferr (Memr[norms+j-1] = imgetr (Memi[imsub+j-1], skyscale)) + Memr[norms+j-1] = 1.0 + #normsum = normsum - Memr[norms+j-1] + } + j = j + 1 + } + } else + dosub = NO + + # Open the images to be added. In most cases there will be one + # such image. + if (finish > ofinish) { + doadd = YES + j = 1 + do i = ofinish + 1, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + Memi[imadd+j-1] = immap (Memc[image], READ_ONLY, 0) + if (imtrgetim (msklist, i, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + Memi[mkadd+j-1] = mp_open (Memc[str], + Memi[imadd+j-1], Memc[imask], SZ_FNAME) + } else + Memi[mkadd+j-1] = mp_open (Memc[str+1], + Memi[imadd+j-1], Memc[imask], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], + SZ_FNAME) != EOF) { + Memi[mkadd+j-1] = mp_open (Memc[str], Memi[imadd+j-1], + Memc[imask], SZ_FNAME) + } else { + Memi[mkadd+j-1] = mp_open ("", Memi[imadd+j-1], + Memc[imask], SZ_FNAME) + } + Memi[mpadd+j-1] = mio_openo (imstati(Memi[mkadd+j-1], + IM_PLDES), Memi[imadd+j-1]) + iferr (Memr[norma+j-1] = imgetr (Memi[imadd+j-1], skyscale)) + Memr[norma+j-1] = 1.0 + #normsum = normsum + Memr[norma+j-1] + } + j = j + 1 + } + } else + doadd = NO + + # Make the vector operators in-line code later if necessary. + npix = IM_LEN(tmpim,1) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[mvin], IM_MAXDIM) + call amovkl (long(1), Meml[mvout], IM_MAXDIM) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + call amovkl (long(1), Meml[ve], IM_MAXDIM) + Meml[ve] = npix + + while (impnlr (tmpim, obuf, Meml[vout]) != EOF && + impnli (tmpmsk, mobuf, Meml[mvout]) != EOF && + imgnlr (tmpim, ibuf, Meml[vin]) != EOF && + imgnli (tmpmsk, mibuf, Meml[mvin]) != EOF) { + call amovr (Memr[ibuf], Memr[obuf], npix) + call amovi (Memi[mibuf], Memi[mobuf], npix) + if (dosub == YES && doadd == YES) { + do i = 1, nsub { + call mio_setrange (Memi[mpsub+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[imsub+i-1])) + call amovl (Meml[vs], Meml[v], IM_MAXDIM) + while (mio_glsegr (Memi[mpsub+i-1], sbuf, mval, Meml[v], + npts) != EOF) { + call amulkr (Memr[sbuf], Memr[norms+i-1], Memr[sbuf], + npts) + call asubr (Memr[obuf+Meml[v]-1], Memr[sbuf], + Memr[obuf+Meml[v]-1], npts) + call asubki (Memi[mobuf+Meml[v]-1], 1, + Memi[mobuf+Meml[v]-1], npts) + } + } + do i = 1, nadd { + call mio_setrange (Memi[mpadd+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[imadd+i-1])) + call amovl (Meml[vs], Meml[v], IM_MAXDIM) + while (mio_glsegr (Memi[mpadd+i-1], abuf, mval, Meml[v], + npts) != EOF) { + call amulkr (Memr[abuf], Memr[norma+i-1], Memr[abuf], + npts) + call aaddr (Memr[obuf+Meml[v]-1], Memr[abuf], + Memr[obuf+Meml[v]-1], npts) + call aaddki (Memi[mobuf+Meml[v]-1], 1, + Memi[mobuf+Meml[v]-1], npts) + } + } + } else if (dosub == YES) { + do i = 1, nsub { + call mio_setrange (Memi[mpsub+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[imsub+i-1])) + call amovl (Meml[vs], Meml[v], IM_MAXDIM) + while (mio_glsegr (Memi[mpsub+i-1], sbuf, mval, Meml[v], + npts) != EOF) { + call amulkr (Memr[sbuf], Memr[norms+i-1], Memr[sbuf], + npts) + call asubr (Memr[obuf+Meml[v]-1], Memr[sbuf], + Memr[obuf+Meml[v]-1], npts) + call asubki (Memi[mobuf+Meml[v]-1], 1, + Memi[mobuf+Meml[v]-1], npts) + } + } + } else if (doadd == YES) { + do i = 1, nadd { + call mio_setrange (Memi[mpadd+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[imadd+i-1])) + call amovl (Meml[vs], Meml[v], IM_MAXDIM) + while (mio_glsegr (Memi[mpadd+i-1], abuf, mval, Meml[v], + npts) != EOF) { + call amulkr (Memr[abuf], Memr[norma+i-1], Memr[abuf], + npts) + call aaddr (Memr[ibuf+Meml[v]-1], Memr[abuf], + Memr[obuf+Meml[v]-1], npts) + call aaddki (Memi[mibuf+Meml[v]-1], 1, + Memi[mobuf+Meml[v]-1], npts) + } + } + } + call amovl (Meml[vout], Meml[vs], IM_MAXDIM) + call amovl (Meml[vout], Meml[ve], IM_MAXDIM) + Meml[vs] = 1 + Meml[ve] = npix + } + + # Close the images to be added or subtracted. + do i = 1, nsub { + call mio_close (Memi[mpsub+i-1]) + call imunmap (Memi[mksub+i-1]) + call imunmap (Memi[imsub+i-1]) + } + do i = 1, nadd { + call mio_close (Memi[mpadd+i-1]) + call imunmap (Memi[mkadd+i-1]) + call imunmap (Memi[imadd+i-1]) + } + + call sfree (sp) +end + + +# RS_PRMNORM -- Compute the new normalization factor. + +procedure rs_prmnorm (rs, im, pmim, tmpim, tmpmsk, outim, fscale) + +pointer rs #I the sky subtraction descriptor +pointer im #I the input image descriptor +pointer pmim #I the input image mask descriptor +pointer tmpim #I the storage image descriptor +pointer tmpmsk #I the counter image descriptor +pointer outim #I the output image descriptor +real fscale #O the new scale factor + +real rmin, rmax +pointer sp, vin, vout, vtmp, vmtmp +pointer obuf, ibuf, tbuf, tmbuf +int i, npix +int impnlr(), imgnlr(), imgnli() + +begin + call smark (sp) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + call salloc (vmtmp, IM_MAXDIM, TY_LONG) + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + call amovkl (long(1), Meml[vmtmp], IM_MAXDIM) + + # Accumulate the normalized image. + npix = IM_LEN(im,1) + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF && + imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF && + imgnli (tmpmsk, tmbuf, Meml[vmtmp]) != EOF) { + + do i = 1, npix { + if (Memi[tmbuf+i-1] > 0) + Memr[obuf+i-1] = Memr[ibuf+i-1] / Memr[tbuf+i-1] + else + Memr[obuf+i-1] = Memr[ibuf+i-1] + } + + } + + # Compute the new normalization factor. + rmin = RS_LOWER(rs) + rmax = RS_UPPER(rs) + RS_LOWER(rs) = INDEFR + RS_UPPER(rs) = INDEFR + call rs_mmed (outim, outim, pmim, NULL, rs, fscale) + RS_LOWER(rs) = rmin + RS_UPPER(rs) = rmax + + call sfree (sp) +end + + +# RS_PRMOUT -- Write the output image. Currently this is the sky image itself +# not the sky subtracted input image. Note that normsum is not actually +# required (I think I have now got the normalization correct) so we may be +# able to eliminate it from the code eventually. For now keep it in case there +# is a mistake. + +int procedure rs_prmout (im, tmpim, tmpmsk, outim, hmim, blank, fscale, skysub) + +pointer im #I the input image descriptor +pointer tmpim #I the storage image descriptor +pointer tmpmsk #I the counter image descriptor +pointer outim #I the output image descriptor +pointer hmim #I the output mask descriptor +real blank #I the undefined pixel value +real fscale #I the normalization factor +char skysub[ARB] #I the sky subtraction keyword + +pointer sp, vin, vout, vtmp, vmtmp, vs, str, obuf, ibuf, tbuf, tmbuf, hbuf +int i, npix, stat +int impnlr(), imgnlr(), imgnli(), imstati() + +begin + call smark (sp) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (vtmp, IM_MAXDIM, TY_LONG) + call salloc (vmtmp, IM_MAXDIM, TY_LONG) + call salloc (str, SZ_FNAME, TY_CHAR) + + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[vin], IM_MAXDIM) + call amovkl (long(1), Meml[vtmp], IM_MAXDIM) + call amovkl (long(1), Meml[vmtmp], IM_MAXDIM) + + call sprintf (Memc[str], SZ_FNAME, + "Sky subtracted with scale factor = %g") + call pargr (fscale) + call imastr (outim, skysub, Memc[str]) + + stat = NO + npix = IM_LEN(im,1) + if (hmim != NULL) { + call salloc (hbuf, npix, TY_SHORT) + call salloc (vs, IM_MAXDIM, TY_LONG) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF && + imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF && + imgnli (tmpmsk, tmbuf, Meml[vmtmp]) != EOF) { + + do i = 1, npix { + if (Memi[tmbuf+i-1] > 0) { + Mems[hbuf+i-1] = 1 + Memr[obuf+i-1] = fscale * Memr[tbuf+i-1] + } else { + stat = YES + Mems[hbuf+i-1] = 0 + Memr[obuf+i-1] = blank + } + } + call asubr (Memr[ibuf], Memr[obuf], Memr[obuf], npix) + + call pm_plps (imstati(hmim, IM_PLDES), Meml[vs], Mems[hbuf], + 1, npix, PIX_SRC) + call amovl (Meml[vin], Meml[vs], IM_MAXDIM) + } + } else { + while (impnlr (outim, obuf, Meml[vout]) != EOF && + imgnlr (im, ibuf, Meml[vin]) != EOF && + imgnlr (tmpim, tbuf, Meml[vtmp]) != EOF && + imgnli (tmpmsk, tmbuf, Meml[vmtmp]) != EOF) { + + do i = 1, npix { + if (Memi[tmbuf+i-1] > 0) { + Memr[obuf+i-1] = fscale * Memr[tbuf+i-1] + } else { + stat = YES + Memr[obuf+i-1] = blank + } + } + call asubr (Memr[ibuf], Memr[obuf], Memr[obuf], npix) + } + } + + call sfree (sp) + + return (stat) +end + + +# RS_PIPTRS -- Get the initial set of image and mask pointers. + +procedure rs_piptrs (inlist, msklist, imptrs, mskptrs, imids, start, finish, + msk_invert, cache, old_size) + +int inlist #I the input image list +int msklist #I the input mask list +pointer imptrs[ARB] #O the input image pointers +pointer mskptrs[ARB] #O the output mask pointers +int imids[ARB] #O the input image ids +int start #I the starting image in the series +int finish #I the ending image in the serious +bool msk_invert #I invert the input masks +bool cache #I cache the image in memory ? +int old_size #O the original working set size + +pointer sp, image, str +int n, i, bufsize +pointer immap(), mp_open() +int imtrgetim(), btoi() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + n = 1 + do i = start, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + imids[n] = i + imptrs[n] = immap (Memc[image], READ_ONLY, 0) + if (imtrgetim (msklist, i, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + mskptrs[n] = mp_open (Memc[str], imptrs[n], + Memc[image], SZ_FNAME) + } else + mskptrs[n] = mp_open (Memc[str+1], imptrs[n], + Memc[image], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], SZ_FNAME) != EOF) { + mskptrs[n] = mp_open (Memc[str], imptrs[n], Memc[image], + SZ_FNAME) + } else { + mskptrs[n] = mp_open ("", imptrs[n], Memc[image], SZ_FNAME) + } + call rs_cachen (btoi(cache), n, imptrs[n], bufsize) + if (n == 1) + old_size = bufsize + n = n + 1 + } + } + + call sfree (sp) +end + + +# RS_PASPTRS -- Advance the image pointer and id buffers for the next +# current image. + +procedure rs_pasptrs (inlist, msklist, imptrs, mskptrs, imids, start, finish, + ostart, ofinish, msk_invert, cache) + +int inlist #I the input image list +int msklist #I the input mask list +pointer imptrs[ARB] #U the input image pointers +pointer mskptrs[ARB] #U the input mask pointers +int imids[ARB] #U the input image ids +int start #I the starting image in the series +int finish #I the ending image in the serious +int ostart #I the old starting image in the series +int ofinish #I the old ending image in the serious +bool msk_invert #I invert the input masks +bool cache #I cache image buffers ? + +pointer sp, image, str +int i, n, nold, nsub, nadd, bufsize +pointer immap(), mp_open() +int imtrgetim(), btoi() + +begin + # No new images are added or deleted. + if (start == ostart && finish == ofinish) + return + + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + nold = ofinish - start + 1 + + # Delete some images and masks from the combine list. + nsub = start - ostart + if (nsub > 0) { + # Unmap the images to be deleted. + do i = 1, nsub { + call imunmap (mskptrs[i]) + call imunmap (imptrs[i]) + } + # Rotate the image pointer buffer. + do i = 1, nold { + imptrs[i] = imptrs[i+nsub] + mskptrs[i] = mskptrs[i+nsub] + imids[i] = imids[i+nsub] + } + } + + # Add new images to the combine list. Note that the cacheing + # mechanism must include the temporarys image hence a request for + # n + 2 cached image buffers is issued instead of a request for n. + nadd = finish - ofinish + if (nadd > 0) { + n = nold + 1 + do i = ofinish + 1, finish { + if (imtrgetim (inlist, i, Memc[image], SZ_FNAME) != EOF) { + imids[n] = i + imptrs[n] = immap (Memc[image], READ_ONLY, 0) + if (imtrgetim (msklist, i, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + mskptrs[n] = mp_open (Memc[str], imptrs[n], + Memc[image], SZ_FNAME) + } else + mskptrs[n] = mp_open (Memc[str+1], imptrs[n], + Memc[image], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], + SZ_FNAME) != EOF) { + mskptrs[n] = mp_open (Memc[str], imptrs[n], Memc[image], + SZ_FNAME) + } else { + mskptrs[n] = mp_open ("", imptrs[n], Memc[image], + SZ_FNAME) + } + if ((finish - start) > (ofinish - ostart)) + call rs_cachen (btoi(cache), n+2, imptrs[n], bufsize) + n = n + 1 + } + } + } + + call sfree (sp) +end + diff --git a/pkg/proto/masks/rsreject.x b/pkg/proto/masks/rsreject.x new file mode 100644 index 00000000..c7a41d2a --- /dev/null +++ b/pkg/proto/masks/rsreject.x @@ -0,0 +1,1220 @@ +include <imhdr.h> +include <imset.h> + +define TMINSW 1.00 # Relative timings for nvecs = 5 +define TMXMNSW 1.46 +define TMED3 0.18 +define TMED5 0.55 + +# RS_APSUMR -- Sum or average images using input masks with optional high and +# low pixel rejection. This version of the routines takes a list of image and +# mask pointers as input. +# +# This procedure is a modified version of code used by the imsum task which +# was easy to modify for the present purposes. + +procedure rs_apsumr (imptrs, mskptrs, imids, im_out, msk_out, start, finish, + current, flow, fhigh, skyscale) + +pointer imptrs[ARB] #I the input image pointers +pointer mskptrs[ARB] #I the input mask pointers +int imids[ARB] #I the list of image ids +pointer im_out #I Output image descriptor +pointer msk_out #I Output "mask" descriptor +int start #I The starting image for the sum +int finish #I The ending image for the sum +int current #I The current image to be skipped +real flow #I Number of low pixels to reject +real fhigh #I Number of high pixels to reject +char skyscale[ARB] #I Keyword containing scaling factor + +pointer sp, im, mpim, norm, vout, mvout, vs, ve, vin +pointer buf_out, buf_msk, buf_in, pbuf +int i, n, nimages, npix, npts, mval + +real imgetr() +pointer mio_openo() +int impnlr(), impnli(), mio_glsegr(), imstati() +errchk imgetr() + +begin + # Initialize. + nimages = finish - start + npix = IM_LEN(im_out, 1) + + # Allocate memory. + call smark (sp) + call salloc (im, nimages, TY_INT) + call salloc (mpim, nimages, TY_INT) + call salloc (norm, nimages, TY_REAL) + call salloc (vs, IM_MAXDIM, TY_LONG) + call salloc (ve, IM_MAXDIM, TY_LONG) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (mvout, IM_MAXDIM, TY_LONG) + + # If there are no pixels to be rejected avoid calls to reject pixels. + # This case will not actually be used in the rskysub task because it + # is handled more efficiently in a different module but is included + # for completeness. + + if ((flow <= 0.0) && (fhigh <= 0.0)) { + + # Open the images. + n = 0 + do i = 1, finish - start + 1 { + if (imids[i] == current) + next + Memi[im+n] = imptrs[i] + iferr (Memr[norm+n] = imgetr (imptrs[i], skyscale)) + Memr[norm+n] = 1.0 + Memi[mpim+n] = mio_openo (imstati(mskptrs[i], IM_PLDES), + imptrs[i]) + n = n + 1 + } + + # Initialize i/o. + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[mvout], IM_MAXDIM) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + call amovkl (long(1), Meml[ve], IM_MAXDIM) + Meml[ve] = npix + + # For each input line compute an output line. + while (impnlr (im_out, buf_out, Meml[vout]) != EOF && + impnli (msk_out, buf_msk, Meml[mvout]) != EOF) { + + # Clear the output buffer. + call aclrr (Memr[buf_out], npix) + call aclri (Memi[buf_msk], npix) + + # Accumulate lines from each input image. + do i = 1, n { + call mio_setrange (Memi[mpim+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[im+i-1])) + call amovl (Meml[vs], Meml[vin], IM_MAXDIM) + while (mio_glsegr (Memi[mpim+i-1], buf_in, mval, + Meml[vin], npts) != EOF) { + call awsur (Memr[buf_in], Memr[buf_out+Meml[vin]-1], + Memr[buf_out+Meml[vin]-1], npts, Memr[norm+i-1], + 1.0) + call aaddki (Memi[buf_msk+Meml[vin]-1], 1, + Memi[buf_msk+Meml[vin]-1], npts) + } + } + + # Compute the average. + do i = 1, npix { + if (Memi[buf_msk+i-1] > 1) + Memr[buf_out+i-1] = Memr[buf_out+i-1] / + Memi[buf_msk+i-1] + } + + # Set the i/o parameters. + call amovl (Meml[vout], Meml[vs], IM_MAXDIM) + call amovl (Meml[vout], Meml[ve], IM_MAXDIM) + Meml[vs] = 1 + Meml[ve] = npix + } + + # Unmap the images. + do i = 1, n + call mio_close (Memi[mpim+i-1]) + + # Finish up. + call sfree (sp) + return + } + + # Pixel rejection is turned on. + + # Collect the images to be combined and open them for masked i/o. + n = 0 + do i = 1, finish - start + 1 { + if (imids[i] == current) + next + Memi[im+n] = imptrs[i] + iferr (Memr[norm+n] = imgetr (imptrs[i], skyscale)) + Memr[norm+n] = 1.0 + Memi[mpim+n] = mio_openo (imstati(mskptrs[i], IM_PLDES), imptrs[i]) + n = n + 1 + } + + # Allocate additional buffer space. + call salloc (pbuf, nimages * npix, TY_REAL) + + # Initialize the i/o. + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[mvout], IM_MAXDIM) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + call amovkl (long(1), Meml[ve], IM_MAXDIM) + Meml[ve] = npix + + # Compute output lines for each input line. + while (impnlr (im_out, buf_out, Meml[vout]) != EOF && + impnli (msk_out, buf_msk, Meml[mvout]) != EOF) { + + # Initialize the output image. + call aclri (Memi[buf_msk], npix) + + # Read lines from the input images. + for (i = 1; i <= n; i = i + 1) { + call mio_setrange (Memi[mpim+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[im+i-1])) + call amovl (Meml[vs], Meml[vin], IM_MAXDIM) + while (mio_glsegr (Memi[mpim+i-1], buf_in, mval, Meml[vin], + npts) != EOF) { + call rs_accumr (Memr[buf_in], npts, Meml[vin] - 1, + Memr[norm+i-1], Memr[pbuf], Memi[buf_msk], npix) + } + } + + # Reject pixels. + call rs_mmrejr (Memr[pbuf], Memi[buf_msk], Memr[buf_out], npix, + flow, fhigh) + + # If averaging divide the sum by the number of images averaged. + do i = 1, npix { + if (Memi[buf_msk+i-1] > 1) + Memr[buf_out+i-1] = Memr[buf_out+i-1] / Memi[buf_msk+i-1] + } + + # Set the i/o parameters. + call amovl (Meml[vout], Meml[vs], IM_MAXDIM) + call amovl (Meml[vout], Meml[ve], IM_MAXDIM) + Meml[vs] = 1 + Meml[ve] = npix + } + + # Finish up. + do i = 1, n + call mio_close (Memi[mpim+i-1]) + + call sfree (sp) +end + + +# RS_PSUMR -- Sum or average images using input masks with optional high and +# low pixel rejection. This version of the routines takes a list of images and +# masks as input. +# +# This procedure is a modified version of code used by the imsum task which +# was easy to modify for the present purposes. + +procedure rs_psumr (list, msklist, im_out, msk_out, start, finish, current, + flow, fhigh, msk_invert, skyscale) + +int list #I List of input images +int msklist #I List of input masks +pointer im_out #I Output image descriptor +pointer msk_out #I Output "mask" descriptor +int start #I The starting image for the sum +int finish #I The ending image for the sum +int current #I The current image to be skipped +real flow #I Number of low pixels to reject +real fhigh #I Number of high pixels to reject +bool msk_invert #I inver the input mask ? +char skyscale[ARB] #I Keyword containing scaling factor + +pointer sp, input, str, im, mkim, mpim, norm, vout, mvout, vs, ve, vin +pointer buf_out, buf_msk, buf_in, pbuf +int i, n, nimages, npix, npts, mval + +real imgetr() +pointer immap(), mp_open(), mio_openo() +int imtrgetim(), impnlr(), impnli(), mio_glsegr(), imstati() +errchk imgetr() + +begin + # Initialize. + nimages = finish - start + npix = IM_LEN(im_out, 1) + + # Allocate memory. + call smark (sp) + call salloc (input, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + call salloc (im, nimages, TY_INT) + call salloc (mkim, nimages, TY_INT) + call salloc (mpim, nimages, TY_INT) + call salloc (norm, nimages, TY_REAL) + call salloc (vs, IM_MAXDIM, TY_LONG) + call salloc (ve, IM_MAXDIM, TY_LONG) + call salloc (vin, IM_MAXDIM, TY_LONG) + call salloc (vout, IM_MAXDIM, TY_LONG) + call salloc (mvout, IM_MAXDIM, TY_LONG) + + # If there are no pixels to be rejected avoid calls to reject pixels. + # This case will not actually be used in the rskysub task because it + # is handled more efficiently in a different module but is included + # for completeness. + + if (flow <= 0.0 && fhigh <= 0.0) { + + # Open the images. + n = 0 + do i = start, finish { + if (i == current) + next + if (imtrgetim (list, i, Memc[input], SZ_FNAME) != EOF) { + Memi[im+n] = immap (Memc[input], READ_ONLY, 0) + iferr (Memr[norm+n] = imgetr (Memi[im+n], skyscale)) + Memr[norm+n] = 1.0 + if (imtrgetim (msklist, i, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + Memi[mkim+n] = mp_open (Memc[str], Memi[im+n], + Memc[input], SZ_FNAME) + } else + Memi[mkim+n] = mp_open (Memc[str+1], Memi[im+n], + Memc[input], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], + SZ_FNAME) != EOF) { + Memi[mkim+n] = mp_open (Memc[str], Memi[im+n], + Memc[input], SZ_FNAME) + } else { + Memi[mkim+n] = mp_open ("", Memi[im+n], Memc[input], + SZ_FNAME) + } + Memi[mpim+n] = mio_openo (imstati(Memi[mkim+n], IM_PLDES), + Memi[im+n]) + n = n + 1 + } + } + + # Initialize i/o. + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[mvout], IM_MAXDIM) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + call amovkl (long(1), Meml[ve], IM_MAXDIM) + Meml[ve] = npix + + # For each input line compute an output line. + while (impnlr (im_out, buf_out, Meml[vout]) != EOF && + impnli (msk_out, buf_msk, Meml[mvout]) != EOF) { + + # Clear the output buffer. + call aclrr (Memr[buf_out], npix) + call aclri (Memi[buf_msk], npix) + + # Accumulate lines from each input image. + do i = 1, n { + call mio_setrange (Memi[mpim+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[im+i-1])) + call amovl (Meml[vs], Meml[vin], IM_MAXDIM) + while (mio_glsegr (Memi[mpim+i-1], buf_in, mval, + Meml[vin], npts) != EOF) { + call awsur (Memr[buf_in], Memr[buf_out+Meml[vin]-1], + Memr[buf_out+Meml[vin]-1], npts, Memr[norm+i-1], + 1.0) + call aaddki (Memi[buf_msk+Meml[vin]-1], 1, + Memi[buf_msk+Meml[vin]-1], npts) + } + } + + # Compute the average. + do i = 1, npix { + if (Memi[buf_msk+i-1] > 1) + Memr[buf_out+i-1] = Memr[buf_out+i-1] / + Memi[buf_msk+i-1] + } + + # Set the i/o parameters. + call amovl (Meml[vout], Meml[vs], IM_MAXDIM) + call amovl (Meml[vout], Meml[ve], IM_MAXDIM) + Meml[vs] = 1 + Meml[ve] = npix + } + + # Unmap the images. + do i = 1, n { + call mio_close (Memi[mpim+i-1]) + call imunmap (Memi[mkim+i-1]) + call imunmap (Memi[im+i-1]) + } + + # Finish up. + call sfree (sp) + return + } + + # Pixel rejection is turned on. + + # Collect the images to be combined and open them for masked i/o. + n = 0 + do i = start, finish { + if (i == current) + next + if (imtrgetim (list, i, Memc[input], SZ_FNAME) != EOF) { + Memi[im+n] = immap (Memc[input], READ_ONLY, 0) + iferr (Memr[norm+n] = imgetr (Memi[im+n], skyscale)) + Memr[norm+n] = 1.0 + if (imtrgetim (msklist, i, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + Memi[mkim+n] = mp_open (Memc[str], Memi[im+n], + Memc[input], SZ_FNAME) + } else + Memi[mkim+n] = mp_open (Memc[str+1], Memi[im+n], + Memc[input], SZ_FNAME) + } else if (imtrgetim (msklist, 1, Memc[str], SZ_FNAME) != EOF) { + Memi[mkim+n] = mp_open (Memc[str], Memi[im+n], + Memc[input], SZ_FNAME) + } else { + Memi[mkim+n] = mp_open ("", Memi[im+n], Memc[input], + SZ_FNAME) + } + Memi[mpim+n] = mio_openo (imstati(Memi[mkim+n], IM_PLDES), + Memi[im+n]) + n = n + 1 + } + } + + # Allocate additional buffer space. + call salloc (pbuf, nimages * npix, TY_REAL) + + # Initialize the i/o. + call amovkl (long(1), Meml[vout], IM_MAXDIM) + call amovkl (long(1), Meml[mvout], IM_MAXDIM) + call amovkl (long(1), Meml[vs], IM_MAXDIM) + call amovkl (long(1), Meml[ve], IM_MAXDIM) + Meml[ve] = npix + + # Compute output lines for each input line. + while (impnlr (im_out, buf_out, Meml[vout]) != EOF && + impnli (msk_out, buf_msk, Meml[mvout]) != EOF) { + + # Initialize the output image. + call aclri (Memi[buf_msk], npix) + + # Read lines from the input images. + for (i = 1; i <= n; i = i + 1) { + call mio_setrange (Memi[mpim+i-1], Meml[vs], Meml[ve], + IM_NDIM(Memi[im+i-1])) + call amovl (Meml[vs], Meml[vin], IM_MAXDIM) + while (mio_glsegr (Memi[mpim+i-1], buf_in, mval, Meml[vin], + npts) != EOF) { + call rs_accumr (Memr[buf_in], npts, Meml[vin] - 1, + Memr[norm+i-1], Memr[pbuf], Memi[buf_msk], npix) + } + } + + # Reject pixels. + call rs_mmrejr (Memr[pbuf], Memi[buf_msk], Memr[buf_out], npix, + flow, fhigh) + + # If averaging divide the sum by the number of images averaged. + do i = 1, npix { + if (Memi[buf_msk+i-1] > 1) + Memr[buf_out+i-1] = Memr[buf_out+i-1] / Memi[buf_msk+i-1] + } + + # Set the i/o parameters. + call amovl (Meml[vout], Meml[vs], IM_MAXDIM) + call amovl (Meml[vout], Meml[ve], IM_MAXDIM) + Meml[vs] = 1 + Meml[ve] = npix + } + + # Finish up. + do i = 1, n { + call mio_close (Memi[mpim+i-1]) + call imunmap (Memi[mkim+i-1]) + call imunmap (Memi[im+i-1]) + } + call sfree (sp) +end + + +# RS_ASUMR -- Sum or average images with optional high and low pixel rejection. +# This version of the routine takes a list of image pointers as input. Median +# combining is enabled if either of the incoming nlow or nhigh parameters is +# INDEF. +# +# This procedure is a simplified version of code used by the imsum task which +# was easy to modify for the present purposes. + +procedure rs_asumr (imptrs, imids, im_out, start, finish, current, nlow, nhigh, + skyscale) + +pointer imptrs[ARB] #I the image pointers +int imids[ARB] #I the image ids +pointer im_out #I Output image descriptor +int start #I The starting image for the sum +int finish #I The ending image for the sum +int current #I The current image to be skipped +int nlow #I Number of low pixels to reject +int nhigh #I Number of high pixels to reject +char skyscale[ARB] #I Keyword containing scaling factor + +real const +pointer sp, v1, v2, im, norm, buf_out, buf_in, pbuf, rbuf +int i, n, nl, nh, nimages, naccept, npix +real imgetr() +int impnlr(), imgnlr() +errchk imgetr() + +begin + # Initialize. + nimages = finish - start + if (IS_INDEFI(nlow) || IS_INDEFI(nhigh)) { + if (mod (nimages,2) == 0) { + nl = nimages / 2 - 1 + nh = nimages / 2 - 1 + } else { + nl = nimages / 2 + nh = nimages / 2 + } + } else { + nl = nlow + nh = nhigh + } + naccept = nimages - nl - nh + const = naccept + npix = IM_LEN(im_out, 1) + + # Allocate memory. + call smark (sp) + call salloc (v1, IM_MAXDIM, TY_LONG) + call salloc (v2, IM_MAXDIM, TY_LONG) + call salloc (im, nimages, TY_INT) + call salloc (norm, nimages, TY_REAL) + + # If there are no pixels to be rejected avoid calls to reject pixels. + # This case will not actually be used in the rskysub task because it + # is handled more efficiently in a different module but is included + # for completeness. + + if ((nl == 0) && (nh == 0)) { + + # Open the images. + n = 0 + do i = 1, finish - start + 1 { + if (imids[i] == current) + next + Memi[im+n] = imptrs[i] + iferr (Memr[norm+n] = imgetr (Memi[im+n], skyscale)) + Memr[norm+n] = 1.0 + n = n + 1 + } + + # Initialize i/o. + call amovkl (long(1), Meml[v1], IM_MAXDIM) + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + + # For each input line compute an output line. + while (impnlr (im_out, buf_out, Meml[v2]) != EOF) { + + # Clear the output buffer. + call aclrr (Memr[buf_out], npix) + + # Accumulate lines from each input image. + do i = 1, n { + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + if (imgnlr (Memi[im+i-1], buf_in, Meml[v2]) == EOF) + call error (0, "Error reading input image") + call awsur (Memr[buf_in], Memr[buf_out], Memr[buf_out], + npix, Memr[norm+i-1], 1.0) + #call amulkr (Memr[buf_in], Memr[norm+i-1], Memr[buf_in], + #npix) + #call aaddr (Memr[buf_in], Memr[buf_out], Memr[buf_out], + #npix) + } + + # Compute the average. + call adivkr (Memr[buf_out], const, Memr[buf_out], npix) + + # Set the i/o parameters. + call amovl (Meml[v2], Meml[v1], IM_MAXDIM) + } + + # Finish up. + call sfree (sp) + return + } + + # Pixel rejection is turned on. + + n = 0 + do i = 1, finish - start + 1 { + if (imids[i] == current) + next + Memi[im+n] = imptrs[i] + iferr (Memr[norm+n] = imgetr (Memi[im+n], skyscale)) + Memr[norm+n] = 1.0 + n = n + 1 + } + + # Allocate additional buffer space. + call salloc (pbuf, nimages, TY_INT) + call salloc (rbuf, nimages * npix, TY_REAL) + + # Initialize the i/o. + call amovkl (long(1), Meml[v1], IM_MAXDIM) + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + + # Compute output lines for each input line. + while (impnlr (im_out, buf_out, Meml[v2]) != EOF) { + + # Read lines from the input images. + for (i = 1; i <= n; i = i + 1) { + Memi[pbuf+i-1] = rbuf + (i - 1) * npix + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + if (imgnlr (Memi[im+i-1], buf_in, Meml[v2]) == EOF) + call error (0, "Error reading input image") + call amulkr (Memr[buf_in], Memr[norm+i-1], Memr[Memi[pbuf+i-1]], + npix) + } + + # Reject pixels. Sum the remaining pixels. + call rs_rejr (Memi[pbuf], nimages, Memr[buf_out], npix, nl, nh) + + # If averaging divide the sum by the number of images averaged. + if (naccept > 1) { + const = naccept + call adivkr (Memr[buf_out], const, Memr[buf_out], npix) + } + + call amovl (Meml[v2], Meml[v1], IM_MAXDIM) + } + + # Finish up. + call sfree (sp) +end + + +# RS_SUMR -- Sum or average images with optional high and low pixel rejection. +# This version of the routines takes a list of images as input. Medianing +# combining is enabled if either of the incoming nlow or nhigh values is +# INDEF +# +# This procedure is a simplified version of code used by the imsum task which +# was easy to modify for the present purposes. + +procedure rs_sumr (list, im_out, start, finish, current, nlow, nhigh, skyscale) + +int list #I List of input images +pointer im_out #I Output image descriptor +int start #I The starting image for the sum +int finish #I The ending image for the sum +int current #I The current image to be skipped +int nlow #I Number of low pixels to reject +int nhigh #I Number of high pixels to reject +char skyscale[ARB] #I Keyword containing scaling factor + +real const +pointer sp, input, v1, v2, im, norm, buf_out, buf_in, buf +int i, n, nimages, naccept, npix, nl, nh +real imgetr() +pointer immap() +int imtrgetim(), impnlr(), imgnlr() +errchk imgetr() + +begin + # Initialize. + nimages = finish - start + if (IS_INDEFI(nlow) || IS_INDEFI(nhigh)) { + if (mod (nimages,2) == 0) { + nl = nimages / 2 - 1 + nh = nimages / 2 - 1 + } else { + nl = nimages / 2 + nh = nimages / 2 + } + } else { + nl = nlow + nh = nhigh + } + naccept = nimages - nl - nh + const = naccept + npix = IM_LEN(im_out, 1) + + # Allocate memory. + call smark (sp) + call salloc (input, SZ_FNAME, TY_CHAR) + call salloc (v1, IM_MAXDIM, TY_LONG) + call salloc (v2, IM_MAXDIM, TY_LONG) + call salloc (im, nimages, TY_INT) + call salloc (norm, nimages, TY_REAL) + + # If there are no pixels to be rejected avoid calls to reject pixels. + # This case will not actually be used in the rskysub task because it + # is handled more efficiently in a different module but is included + # for completeness. + + if ((nl == 0) && (nh == 0)) { + + # Open the images. + n = 0 + do i = start, finish { + if (i == current) + next + if (imtrgetim (list, i, Memc[input], SZ_FNAME) != EOF) { + Memi[im+n] = immap (Memc[input], READ_ONLY, 0) + iferr (Memr[norm+n] = imgetr (Memi[im+n], skyscale)) + Memr[norm+n] = 1.0 + n = n + 1 + } + } + + # Initialize i/o. + call amovkl (long(1), Meml[v1], IM_MAXDIM) + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + + # For each input line compute an output line. + while (impnlr (im_out, buf_out, Meml[v2]) != EOF) { + + # Clear the output buffer. + call aclrr (Memr[buf_out], npix) + + # Accumulate lines from each input image. + do i = 1, n { + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + if (imgnlr (Memi[im+i-1], buf_in, Meml[v2]) == EOF) + call error (0, "Error reading input image") + call amulkr (Memr[buf_in], Memr[norm+i-1], Memr[buf_in], + npix) + call aaddr (Memr[buf_in], Memr[buf_out], Memr[buf_out], + npix) + } + + # Compute the average. + call adivkr (Memr[buf_out], const, Memr[buf_out], npix) + + # Set the i/o parameters. + call amovl (Meml[v2], Meml[v1], IM_MAXDIM) + } + + # Unmap the images. + do i = 1, n + call imunmap (Memi[im+i-1]) + + # Finish up. + call sfree (sp) + return + } + + # Pixel rejection is turned on. + + n = 0 + do i = start, finish { + if (i == current) + next + if (imtrgetim (list, i, Memc[input], SZ_FNAME) != EOF) { + Memi[im+n] = immap (Memc[input], READ_ONLY, 0) + iferr (Memr[norm+n] = imgetr (Memi[im+n], skyscale)) + Memr[norm+n] = 1.0 + n = n + 1 + } + } + + # Allocate additional buffer space. + call salloc (buf, nimages, TY_INT) + + # Initialize the i/o. + call amovkl (long(1), Meml[v1], IM_MAXDIM) + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + + # Compute output lines for each input line. + while (impnlr (im_out, buf_out, Meml[v2]) != EOF) { + + # Read lines from the input images. + for (i = 1; i <= n; i = i + 1) { + call amovl (Meml[v1], Meml[v2], IM_MAXDIM) + if (imgnlr (Memi[im+i-1], Memi[buf+i-1], Meml[v2]) == EOF) + call error (0, "Error reading input image") + call amulkr (Memr[Memi[buf+i-1]], Memr[norm+i-1], + Memr[Memi[buf+i-1]], npix) + } + + # Reject pixels. Sum the remaining pixels. + call rs_rejr (Memi[buf], nimages, Memr[buf_out], npix, nl, nh) + + # If averaging divide the sum by the number of images averaged. + if (naccept > 1) { + const = naccept + call adivkr (Memr[buf_out], const, Memr[buf_out], npix) + } + + call amovl (Meml[v2], Meml[v1], IM_MAXDIM) + } + + # Finish up. + do i = 1, n + call imunmap (Memi[im+i-1]) + call sfree (sp) +end + + +# RS_ACCUMR -- Acumulate the masked data into the input buffer. + +procedure rs_accumr (indata, npts, offset, norm, outdata, ndata, npix) + +real indata[npts] #I the input data +int npts #I the number of input data points +int offset #I the offset of the first data point +real norm #I the normalization factor +real outdata[npix,ARB] #U the output array +int ndata[npix] #U the number of good data points +int npix #I number of points in a line + +int i + +begin + do i = 1, npts { + ndata[i+offset] = ndata[i+offset] + 1 + outdata[i+offset,ndata[i+offset]] = norm * indata[i] + } +end + + +# RS_MMREJR -- Reject a specified number of high and low pixels. This routine +# is a modified version of one in imcombine. It works off a real data +# buffer rather than a set of image i/o buffers. It also sums the points at +# the end + +procedure rs_mmrejr (indata, n, out, npts, flo, fhi) + +real indata[npts,ARB] #U the data buffer of good pixels +int n[npts] #U The number of good pixels +real out[npts] #O the output sum +int npts #I The number of output points per line +real flo #I Fraction of low points to reject +real fhi #I Fraction of high points to reject + + +real d1, d2, dmin, dmax, sum +int n1, npairs, nlow, nhigh, naccept, np, nlo, nhi, medflag +int i, j, jmax, jmin + + +begin + if (IS_INDEFR(flo) || IS_INDEFR(fhi)) + medflag = YES + else + medflag = NO + + do i = 1, npts { + + n1 = n[i] + if (medflag == YES) { + if (mod (n1, 2) == 0) { + nlo = n1 / 2 - 1 + nhi = n1 / 2 - 1 + } else { + nlo = n1 / 2 + nhi = n1 / 2 + } + } else { + nlo = flo * n1 + 0.001 + nhi = fhi * n1 + 0.001 + } + naccept = n1 - nlo - nhi + + # No points are rejected. + if (naccept == n1) + next + + # All points are rejected. + if (naccept <= 0) { + n[i] = 0 + next + } + + npairs = min (nlo, nhi) + nlow = nlo - npairs + nhigh = nhi - npairs + + # Reject the npairs low and high points. + do np = 1, npairs { + d1 = indata[i,1] + dmax = d1; dmin = d1; jmax = 1; jmin = 1 + do j = 2, n1 { + d2 = d1 + d1 = indata[i,j] + if (d1 > dmax) { + dmax = d1; jmax = j + } else if (d1 < dmin) { + dmin = d1; jmin = j + } + } + j = n1 - 1 + if (jmax < j) { + if (jmin != j) + indata[i,jmax] = d2 + else + indata[i,jmax] = d1 + } + if (jmin < j) { + if (jmax != n1) + indata[i,jmin] = d1 + else + indata[i,jmin] = d2 + } + n1 = n1 - 2 + } + + # Reject the excess low points. + do np = 1, nlow { + d1 = indata[i,1] + dmin = d1; jmin = 1 + do j = 2, n1 { + d1 = indata[i,j] + if (d1 < dmin) { + dmin = d1; jmin = j + } + } + if (jmin < n1) + indata[i,jmin] = d1 + n1 = n1 - 1 + } + + # Reject the excess high points. + do np = 1, nhigh { + d1 = indata[i,1] + dmax = d1; jmax = 1 + do j = 2, n1 { + d1 = indata[i,j] + if (d1 > dmax) { + dmax = d1; jmax = j + } + } + if (jmax < n1) + indata[i,jmax] = d1 + n1 = n1 - 1 + } + + n[i] = n1 + } + + # Compute the sum. + do i = 1, npts { + if (n[i] == 0) { + out[i] = 0.0 + } else if (n[i] == 1) { + out[i] = indata[i,1] + } else { + sum = indata[i,1] + do j = 2, n[i] + sum = sum + indata[i,j] + out[i] = sum + } + } +end + + +## RS_MMREJR -- Reject a specified number of high and low pixels from a +## buffer by doing min / max comparison, reordering the data buffer, and +## editing the number of good pixels array. This routine is a modified +## version of the one in the imcombine task. +# +#procedure rs_mmrejr (d, n, npts, nlo, nhi) +# +#pointer d[ARB] #I The input data pointers +#int n[npts] #U The number of good pixels +#int npts #I The number of output points per line +#int nlo #I Number of low points to reject +#int nhi #I Number of high points to reject +# +#real d1, d2, dmin, dmax +#pointer k, kmax, kmin +#int n1, npairs, nlow, nhigh, np +#int i, i1, j, jmax, jmin +# +#begin +# npairs = min (nlo, nhi) +# nlow = nlo - npairs +# nhigh = nhi - npairs +# do i = 1, npts { +# +# i1 = i - 1 +# n1 = n[i] +# naccept = n1 - nlo - nhi +# if (naccept == n1) +# next +# if (naccept <= 0) { +# n[i] = 0 +# next +# } +# +# +# +# # 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 (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 (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 (jmax < n1) +# Memr[kmax] = d1 +# n1 = n1 - 1 +# } +# +# n[i] = n1 +# } +#end + + +# RS_REJR -- Reject the number of high and low points and sum the rest. + +procedure rs_rejr (a, nvecs, b, npts, nlow, nhigh) + +pointer a[nvecs] # Pointers to set of vectors +int nvecs # Number of vectors +real b[npts] # Output vector +int npts # Number of points in the vectors +int nlow # Number of low points to be rejected +int nhigh # Number of high points to be rejected + +int i, j +int naccept, minrej, npairs, nlow1, nhigh1 +real tmedian, time1, time2 + +begin + naccept = nvecs - nlow - nhigh + + # If no points are rejected return the sum. + + if (naccept == nvecs) { + call amovr (Memr[a[1]], b, npts) + for (j = 2; j <= naccept; j = j + 1) + call aaddr (Memr[a[j]], b, b, npts) + return + } + + minrej = min (nlow, nhigh) + npairs = minrej + nlow1 = nlow - npairs + nhigh1 = nhigh - npairs + + if ((naccept == 1) && (npairs > 0)) { + if (npairs == 1) { + tmedian = TMED3 + npairs = npairs - 1 + } else { + tmedian = TMED5 + npairs = npairs - 2 + } + } else + tmedian = 0 + + # Compare the time required to reject the minimum number + # of low or high points and extract the number of points to accept + # with the time to reject pairs and the excess number of low or + # high points to either reach a median of 3 or 5 points or isolate + # the acceptable points. + + time1 = TMINSW * (minrej + naccept) + time2 = tmedian + TMXMNSW * npairs + TMINSW * (nlow1 + nhigh1) + + i = nvecs + if (time1 < time2) { + + # Sort the nlow and naccept points + if (nlow < nhigh) { + for (j = 1; j <= nlow + naccept; j = j + 1) { + call rs_minswr (a, i, npts) + i = i - 1 + } + call amovr (Memr[a[nhigh+1]], b, npts) + for (j = nhigh+2; j <= nhigh+naccept; j = j + 1) + call aaddr (Memr[a[j]], b, b, npts) + + # Sort the nhigh and naccept points + } else { + for (j = 1; j <= nhigh + naccept; j = j + 1) { + call rs_maxswr (a, i, npts) + i = i - 1 + } + call amovr (Memr[a[nlow+1]], b, npts) + for (j = nlow+2; j <= nlow+naccept; j = j + 1) + call aaddr (Memr[a[j]], b, b, npts) + } + + } else { + # Reject the npairs low and high points. + for (j = 1; j <= npairs; j = j + 1) { + call rs_mxmnswr (a, i, npts) + i = i - 2 + } + # Reject the excess low points. + for (j = 1; j <= nlow1; j = j + 1) { + call rs_minswr (a, i, npts) + i = i - 1 + } + # Reject the excess high points. + for (j = 1; j <= nhigh1; j = j + 1) { + call rs_maxswr (a, i, npts) + i = i - 1 + } + + # Check if the remaining points constitute a 3 or 5 point median + # or the set of desired points. + if (tmedian == 0.) { + call amovr (Memr[a[1]], b, npts) + for (j = 2; j <= naccept; j = j + 1) + call aaddr (Memr[a[j]], b, b, npts) + } else if (tmedian == TMED3) { + call amed3r (Memr[a[1]], Memr[a[2]], Memr[a[3]], b, npts) + } else { + call amed5r (Memr[a[1]], Memr[a[2]], Memr[a[3]], + Memr[a[4]], Memr[a[5]], b, npts) + } + } +end + + +# RS_MINSWR -- Given an array of vector pointers for each element in the vectors +# swap the minimum element with that of the last vector. + +procedure rs_minswr (a, nvecs, npts) + +pointer a[nvecs] # Array of vector pointers +int nvecs # Number of vectors +int npts # Number of points in the vectors + +int i, j, k, kmin +real temp + +begin + do i = 0, npts - 1 { + kmin = a[1] + i + do j = 2, nvecs { + k = a[j] + i + if (Memr[k] < Memr[kmin]) + kmin = k + } + if (k != kmin) { + temp = Memr[k] + Memr[k] = Memr[kmin] + Memr[kmin] = temp + } + } +end + + +# RS_MAXSW -- Given an array of vector pointers for each element in the vectors +# swap the maximum element with that of the last vector. + +procedure rs_maxswr (a, nvecs, npts) + +pointer a[nvecs] # Array of vector pointers +int nvecs # Number of vectors +int npts # Number of points in the vectors + +int i, j, k, kmax +real temp + +begin + do i = 0, npts - 1 { + kmax = a[1] + i + do j = 2, nvecs { + k = a[j] + i + if (Memr[k] > Memr[kmax]) + kmax = k + } + if (k != kmax) { + temp = Memr[k] + Memr[k] = Memr[kmax] + Memr[kmax] = temp + } + } +end + + +# RS_MXMNSW -- Given an array of vector pointers for each element in the vectors +# swap the maximum element with that of the last vector and the minimum element +# with that of the next to last vector. The number of vectors must be greater +# than 1. + +procedure rs_mxmnswr (a, nvecs, npts) + +pointer a[nvecs] # Array of vector pointers +int nvecs # Number of vectors +int npts # Number of points in the vectors + +int i, j, k, kmax, kmin +real temp + +begin + do i = 0, npts - 1 { + kmax = a[1] + i + kmin = kmax + do j = 2, nvecs { + k = a[j] + i + if (Memr[k] > Memr[kmax]) + kmax = k + else if (Memr[k] < Memr[kmin]) + kmin = k + } + temp = Memr[k] + Memr[k] = Memr[kmax] + Memr[kmax] = temp + if (kmin == k) { + j = a[nvecs - 1] + i + temp = Memr[j] + Memr[j] = Memr[kmax] + Memr[kmax] = temp + } else { + j = a[nvecs - 1] + i + temp = Memr[j] + Memr[j] = Memr[kmin] + Memr[kmin] = temp + } + } +end + diff --git a/pkg/proto/masks/rsscache.x b/pkg/proto/masks/rsscache.x new file mode 100644 index 00000000..efce9e7c --- /dev/null +++ b/pkg/proto/masks/rsscache.x @@ -0,0 +1,123 @@ +include <imhdr.h> +include <imset.h> + +define MEMFUDGE 1.05 + +# RS_CACHEN -- Cache N same sized images in memory using the image i/o +# buffer sizes. + +procedure rs_cachen (cache, nimages, im, old_size) + +int cache #I cache the image pixels in the imio buffer +int nimages #I the number of images +pointer im #I the current image descriptor +int old_size #O the old working set size + +int i, req_size, buf_size +int sizeof(), rs_memstat() + +begin + req_size = MEMFUDGE * IM_LEN(im,1) * sizeof (IM_PIXTYPE(im)) + do i = 2, IM_NDIM(im) + req_size = req_size * IM_LEN(im,i) + req_size = nimages * req_size + if (rs_memstat (cache, req_size, old_size) == YES) + call rs_pcache (im, INDEFI, buf_size) +end + + +# RS_CACHE1 -- Cache 1 image in memory using the image i/o buffer sizes. + +procedure rs_cache1 (cache, im, old_size) + +int cache #I cache the image pixels in the imio buffer +pointer im #I the image descriptor +int old_size #O the old working set size + +int i, req_size, buf_size +int sizeof(), rs_memstat() + +begin + req_size = MEMFUDGE * IM_LEN(im,1) * sizeof (IM_PIXTYPE(im)) + do i = 2, IM_NDIM(im) + req_size = req_size * IM_LEN(im,i) + if (rs_memstat (cache, req_size, old_size) == YES) + call rs_pcache (im, INDEFI, buf_size) +end + + +# RS_MEMSTAT -- Figure out if there is enough memory to cache the image +# pixels. If it is necessary to request more memory and the memory is +# avalilable return YES otherwise return NO. + +int procedure rs_memstat (cache, req_size, old_size) + +int cache #I cache memory ? +int req_size #I the requested working set size in chars +int old_size #O the original working set size in chars + +int cur_size, max_size +int begmem() + +begin + # Find the default working set size. + cur_size = begmem (0, old_size, max_size) + + # If cacheing is disabled return NO regardless of the working set size. + if (cache == NO) + return (NO) + + # If the requested working set size is less than the current working + # set size return YES. + if (req_size <= cur_size) + return (YES) + + # Reset the current working set size. + cur_size = begmem (req_size, old_size, max_size) + if (req_size <= cur_size) { + return (YES) + } else { + return (NO) + } +end + + +# RS_PCACHE -- Cache the image pixels im memory by resetting the default image +# buffer size. If req_size is INDEF the size of the image is used to determine +# the size of the image i/o buffers. + +procedure rs_pcache (im, req_size, buf_size) + +pointer im #I the input image point +int req_size #I the requested working set size in chars +int buf_size #O the new image buffer size + +int i, def_size, new_imbufsize +int sizeof(), imstati() + +begin + # Find the default buffer size. + def_size = imstati (im, IM_BUFSIZE) + + # Compute the new required image i/o buffer size in chars. + if (IS_INDEFI(req_size)) { + new_imbufsize = IM_LEN(im,1) * sizeof (IM_PIXTYPE(im)) + do i = 2, IM_NDIM(im) + new_imbufsize = new_imbufsize * IM_LEN(im,i) + } else { + new_imbufsize = req_size + } + + # If the default image i/o buffer size is already bigger than + # the requested size do nothing. + if (def_size >= new_imbufsize) { + buf_size = def_size + return + } + + # Reset the image i/o buffer. + call imseti (im, IM_BUFSIZE, new_imbufsize) + call imseti (im, IM_BUFFRAC, 0) + buf_size = new_imbufsize +end + diff --git a/pkg/proto/masks/rsstats.x b/pkg/proto/masks/rsstats.x new file mode 100644 index 00000000..9c7a1b32 --- /dev/null +++ b/pkg/proto/masks/rsstats.x @@ -0,0 +1,492 @@ +include <mach.h> +include <imhdr.h> +include <imset.h> +include <pmset.h> +include "mimstat.h" +include "rskysub.h" + + +# RS_STATS -- Compute the input image scaling factors. + +procedure rs_stats (inlist, imsklist, omsklist, sclist, rs, msk_invert, + cache, verbose) + +int inlist #I the input image list +int imsklist #I the input mask list +int omsklist #I the output mask list +int sclist #I the input scale factors list +pointer rs #I the sky subtraction descriptor +bool msk_invert #I invert the pixel masks ? +bool cache #I cache the image i/o buffers ? +bool verbose #I print image statistics ? + +real fscale +pointer sp, image, imaskname, omaskname, masktemp, str +pointer im, ims, pmim, pmout +int ip, old_size +real imgetr() +pointer immap(), im_pmmap(), mp_open() +int imtgetim(), imtlen(), imtrgetim(), ctor(), ctowrd(), btoi() +int fntgfnb(), imstati(), imaccess() +bool strne(), streq() +errchk immap() + +begin + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imaskname, SZ_FNAME, TY_CHAR) + call salloc (omaskname, SZ_FNAME, TY_CHAR) + call salloc (masktemp, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Loop over the input images and compute the scale factors. + # At some point we might combine this with the later running + # mean / median loop for more efficient operation especially in an + # observing environment but that can easily be rearranged later. + + while (imtgetim (inlist, Memc[image], SZ_FNAME) != EOF) { + + # Open the input image. This image is opened READ_WRITE + # so some header information can be added ... + iferr (im = immap (Memc[image], READ_WRITE, 0)) { + call printf ("Error opening image %s ...\n") + call pargstr (Memc[image]) + next + } + + # Check for a statistics section. If the image image already + # includes a section strip it off, append the statistics + # section to the input image name, and open the statistics + # section image. + + if (streq (RS_ISCALES(rs), "median") && RS_STATSEC(rs) != EOS) { + call imgimage (Memc[image], Memc[str], SZ_FNAME) + call strcat (RS_STATSEC(rs), Memc[str], SZ_FNAME) + iferr (ims = immap (Memc[str], READ_ONLY, 0)) { + call imunmap (im) + call printf ("Error opening image %s ...\n") + call pargstr (Memc[image]) + next + } + } else + ims = NULL + + # Open input the mask if any. The input and output mask + # lists are ignored if the scaling factor is not median + # or if the list lengths are both zero. + if (strne (RS_ISCALES(rs), "median")) { + pmim = NULL + pmout = NULL + } else if (imtlen (omsklist) == 0 && imtlen (imsklist) == 0) { + pmim = NULL + pmout = NULL + } else { + + # Get the input mask which defaults to the empty mask if + # there is none. + if (imtgetim (imsklist, Memc[str+1], SZ_FNAME) != EOF) { + if (msk_invert) { + Memc[str] = '^' + pmim = mp_open (Memc[str], im, Memc[imaskname], + SZ_FNAME) + } else + pmim = mp_open (Memc[str+1], im, Memc[imaskname], + SZ_FNAME) + } else if (imtrgetim (imsklist, 1, Memc[str], + SZ_FNAME) != EOF) { + pmim = mp_open (Memc[str], im, Memc[imaskname], SZ_FNAME) + } else { + pmim = mp_open ("", im, Memc[imaskname], SZ_FNAME) + } + if (pmim == NULL) { + call printf ("Error reading mask for image %s ...\n") + call pargstr (Memc[image]) + call imunmap (im) + next + } + + # Get the output mask name if any. + if (imtlen (omsklist) > 0) { + if (imtgetim (omsklist, Memc[omaskname], SZ_FNAME) == EOF) { + call imunmap (pmim) + call imunmap (im) + next + } else { + if (Memc[imaskname] == '^') + call xt_mkimtemp (Memc[imaskname+1], + Memc[omaskname], Memc[masktemp], SZ_FNAME) + else + call xt_mkimtemp (Memc[imaskname], Memc[omaskname], + Memc[masktemp], SZ_FNAME) + pmout = im_pmmap (Memc[omaskname], NEW_IMAGE, 0) + call mp_mpcopy (im, pmim, pmout) + } + } else { + pmout = NULL + } + } + + + # Print title. + if (verbose) { + if (pmim == NULL) { + call printf ("Computing scale factor for image %s\n") + call pargstr (Memc[image]) + } else { + call printf ( + "Computing scale factor for image %s using mask %s\n") + call pargstr (Memc[image]) + call pargstr (Memc[imaskname]) + } + call flush (STDOUT) + } + + # Check for existence of scaling keyword. If the keyword is + # present and the rescaling flag is turned off then proceed + # to the next image, otherwise compute the new scale factor. + + if (RS_RESCALE(rs) == NO) { + ifnoerr (fscale = imgetr (im, RS_KYFSCALE(rs))) { + if (verbose) { + call printf (" Using precomputed value %g\n") + call pargr (fscale) + } + call imunmap (pmim) + if (ims != NULL) + call imunmap (ims) + call imunmap (im) + next + } + } + + # Compute the scaling factor. The scaling factor defaults + # to, 1 if the scaling method is "none", the value of the image + # header keyowrd if the scaling factor is !KEYWORD, 1 / median + # if the the scaling methid is "median", or the value in the + # scaling factors file if the scaling factor is "@file". If an + # error occurs the scaling factor is set to 1.0. + + if (streq (RS_ISCALES(rs), "none")) { + fscale = 1.0 + } else if (RS_ISCALES(rs) == '!') { + ip = 2 + if (ctowrd (RS_ISCALES(rs), ip, Memc[str], SZ_FNAME) <= 0) + Memc[str] = EOS + iferr (fscale = imgetr (im, Memc[str])) + fscale = 1.0 + } else if (streq (RS_ISCALES(rs), "median")) { + if (ims != NULL) + call rs_cache1 (btoi(cache), ims, old_size) + else + call rs_cache1 (btoi(cache), im, old_size) + if (pmim == NULL) { + if (ims != NULL) + call rs_med (ims, rs, fscale) + else + call rs_med (im, rs, fscale) + } else { + if (ims != NULL) + call rs_mmed (im, ims, pmim, pmout, rs, fscale) + else + call rs_mmed (im, im, pmim, pmout, rs, fscale) + } + if (IS_INDEFR(fscale)) + fscale = 1.0 + else + fscale = 1.0 / fscale + call fixmem (old_size) + } else if (fntgfnb (sclist, Memc[str], SZ_FNAME) != EOF) { + ip = 1 + if (ctor (Memc[str], ip, fscale) <= 0) + fscale = 1.0 + } else { + fscale = 1.0 + } + + # Print the computed scaling factor. + if (verbose) { + call printf (" New scale factor is 1 / %g\n") + call pargr (1.0 / fscale) + if (pmout != NULL) { + call printf (" Writing new image mask %s\n") + call pargstr (Memc[masktemp]) + } + call flush (STDOUT) + } + + # Store the new scaling factor in the input image header. + call imaddr (im, RS_KYFSCALE(rs), fscale) + + # Close the input image and mask. + if (pmout != NULL) { + if (imaccess (Memc[omaskname], YES) == YES) + call imdelete (Memc[omaskname]) + call pm_savef (imstati (pmout, IM_PMDES), Memc[omaskname], + "", 0) + call imunmap (pmout) + if (pmim != NULL) + call imunmap (pmim) + call xt_delimtemp (Memc[omaskname], Memc[masktemp]) + } else { + if (pmim != NULL) + call imunmap (pmim) + } + if (ims != NULL) + call imunmap (ims) + call imunmap (im) + } + + call sfree (sp) +end + + +# RS_MMED -- Estimate the image median using iterative rejection and +# a pixel mask. The input image and input statistics image descriptors may +# be the same. + +procedure rs_mmed (im, ims, pmim, pmout, rs, fscale) + +pointer im #I the input image descriptor +pointer ims #I the input image statistics descriptor +pointer pmim #I the input mask image descriptor +pointer pmout #I the output mask image descriptor +pointer rs #I the sky subtraction pointer +real fscale #O the scaling factor + +real low, up, hmin, hmax, hwidth +pointer sp, vs, ve, mst, pm, mp, buf, hgm, smsk +int i, mval, npts, npix, nbins, nbad + +pointer mp_miopen() +int imstati(), mio_glsegr(), mst_ihist(), rs_umask() + +begin + call smark (sp) + call salloc (vs, IM_MAXDIM, TY_LONG) + call salloc (ve, IM_MAXDIM, TY_LONG) + + # Allocate space for statistics structure. + call mst_allocate (mst) + + # Get the selected fields. + #nfields = mst_fields ("midpt,stddev" Memi[fields], MIS_NFIELDS) + + # Set the processing switches + #call mst_switches (mst, Memi[fields], nfields, RS_MAXITER(rs)) + + # Set up the region masking parameters. + mp = mp_miopen (ims, pmim) + + # Compute the image statistics. + low = RS_LOWER(rs) + up = RS_UPPER(rs) + do i = 0 , RS_MAXITER(rs) { + + # Set up the mask i/o boundaries. + call amovkl (long(1), Meml[vs], IM_NDIM(ims)) + call amovl (IM_LEN(ims,1), Meml[ve], IM_NDIM(ims)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(ims)) + + # Initialize the statistics computation. + call mst_initialize (mst, low, up) + + # Accumulate the statistics. + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate2 (mst, Memr[buf], npts, low, up, YES) + + # Compute the 2nd order central moment statistics. + call mst_stats (mst) + + # Compute new limits and iterate. + if (i < RS_MAXITER(rs)) { + if (IS_INDEFR(RS_LNSIGREJ(rs))) + low = -MAX_REAL + else if (RS_LNSIGREJ(rs) > 0.0 || IS_INDEFR(MIS_MEAN(mst)) || + IS_INDEFR(MIS_STDDEV(mst))) + low = MIS_MEAN(mst) - RS_LNSIGREJ(rs) * MIS_STDDEV(mst) + else + low = -MAX_REAL + if (IS_INDEFR(RS_UNSIGREJ(rs))) + up = MAX_REAL + else if (RS_UNSIGREJ(rs) > 0.0 || IS_INDEFR(MIS_MEAN(mst)) || + IS_INDEFR(MIS_STDDEV(mst))) + up = MIS_MEAN(mst) + RS_UNSIGREJ(rs) * MIS_STDDEV(mst) + else + up = MAX_REAL + if (i > 0) { + if (MIS_NPIX(mst) == npix) + break + } + npix = MIS_NPIX(mst) + } + + } + + # Estimate the median and the mode by accumulating the histogram. + hgm = NULL + if (mst_ihist (mst, RS_BINWIDTH(rs), hgm, nbins, hwidth, hmin, + hmax) == YES) { + call aclri (Memi[hgm], nbins) + call amovkl (long(1), Meml[vs], IM_NDIM(ims)) + call amovl (IM_LEN(ims,1), Meml[ve], IM_NDIM(ims)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(ims)) + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call ahgmr (Memr[buf], npts, Memi[hgm], nbins, hmin, hmax) + call mst_hmedian (mst, Memi[hgm], nbins, hwidth, hmin, hmax) + } + if (hgm != NULL) + call mfree (hgm, TY_INT) + + # Set the statistic + fscale = MIS_MEDIAN(mst) + + if (pmout != NULL) { + call malloc (smsk, IM_LEN(im,1), TY_SHORT) + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + call amovl (IM_LEN(im,1), Meml[ve], IM_NDIM(im)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(im)) + pm = imstati (pmout, IM_PMDES) + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) { + nbad = rs_umask (Memr[buf], Mems[smsk], npts, low, up) + if (nbad > 0) + call pm_plps (pm, Meml[vs], Mems[smsk], 1, npts, PIX_SRC) + } + call mp_invert (pm) + call imseti (pmout, IM_PMDES, pm) + call mfree (smsk, TY_SHORT) + } + + # Close the maskio descriptor. + call mio_close (mp) + + call mst_free (mst) + call sfree (sp) +end + + +# RS_MED -- Estimate the image median using iterative rejection and +# no pixel mask. + +procedure rs_med (im, rs, fscale) + +pointer im #I the input image descriptor +pointer rs #I the sky subtraction descriptor +real fscale #I the computed scaling factor + + +real low, up, hmin, hmax, hwidth +pointer sp, v, mst, buf, hgm +int i, npts, npix, nbins +int imgnlr(), mst_ihist() + +begin + call smark (sp) + call salloc (v, IM_MAXDIM, TY_LONG) + + # Allocate space for statistics structure. + call mst_allocate (mst) + + # Get the selected fields. + #nfields = mst_fields ("midpt,stddev" Memi[fields], MIS_NFIELDS) + + # Set the processing switches + #call mst_switches (mst, Memi[fields], nfields, RS_MAXITER(rs)) + + # Compute the image statistics. + low = RS_LOWER(rs) + up = RS_UPPER(rs) + do i = 0 , RS_MAXITER(rs) { + + # Initialize the statistics computation. + call mst_initialize (mst, low, up) + + # Accumulate the statistics. + npts = IM_LEN(im,1) + call amovkl (long(1), Meml[v], IM_NDIM(im)) + while (imgnlr (im, buf, Meml[v]) != EOF) + call mst_accumulate2 (mst, Memr[buf], npts, low, up, YES) + + # Compute the 2nd order central moment statistics. + call mst_stats (mst) + + # Compute new limits and iterate. + if (i < RS_MAXITER(rs)) { + if (IS_INDEFR(RS_LNSIGREJ(rs))) + low = -MAX_REAL + else if (RS_LNSIGREJ(rs) > 0.0) + low = MIS_MEAN(mst) - RS_LNSIGREJ(rs) * MIS_STDDEV(mst) + else + low = -MAX_REAL + if (IS_INDEFR(RS_UNSIGREJ(rs))) + up = MAX_REAL + else if (RS_UNSIGREJ(rs) > 0.0) + up = MIS_MEAN(mst) + RS_UNSIGREJ(rs) * MIS_STDDEV(mst) + else + up = MAX_REAL + if (i > 0) { + if (MIS_NPIX(mst) == npix) + break + } + npix = MIS_NPIX(mst) + } + + } + + # Estimate the median and the mode by accumulating the histogram. + hgm = NULL + if (mst_ihist (mst, RS_BINWIDTH(rs), hgm, nbins, hwidth, hmin, + hmax) == YES) { + call aclri (Memi[hgm], nbins) + call amovkl (long(1), Meml[v], IM_NDIM(im)) + while (imgnlr (im, buf, Meml[v]) != EOF) + call ahgmr (Memr[buf], npts, Memi[hgm], nbins, hmin, hmax) + call mst_hmedian (mst, Memi[hgm], nbins, hwidth, hmin, hmax) + } + if (hgm != NULL) + call mfree (hgm, TY_INT) + + # Set the statistic + fscale = MIS_MEDIAN(mst) + + call mst_free (mst) + call sfree (sp) +end + + +# RS_UMASK -- Update the mask. + +int procedure rs_umask (pix, msk, npts, lower, upper) + +real pix[ARB] #I array of image pixels +short msk[ARB] #O array of mask pixels, set to 1 and 0 +int npts #I the number of pixels +real lower #I the lower good data limit +real upper #I the upper good data limit + +real lo, up +int i, nbad + +begin + if (IS_INDEFR(lower) && IS_INDEFR(upper)) + return (0) + + if (IS_INDEFR(lower)) + lo = -MAX_REAL + else + lo = lower + if (IS_INDEFR(upper)) + up = MAX_REAL + else + up = upper + + nbad = 0 + do i = 1, npts { + if (pix[i] < lo || pix[i] > up) { + msk[i] = 0 + nbad = nbad + 1 + } else + msk[i] = 1 + } + + return (nbad) +end diff --git a/pkg/proto/masks/t_mimstat.x b/pkg/proto/masks/t_mimstat.x new file mode 100644 index 00000000..99d5ab09 --- /dev/null +++ b/pkg/proto/masks/t_mimstat.x @@ -0,0 +1,363 @@ +include <mach.h> +include <imhdr.h> +include <imset.h> +include <pmset.h> +include "mimstat.h" + +# T_MIMSTATISTICS -- Compute image statistics through masks. + +procedure t_mimstatistics() + +real lower, upper, lsigma, usigma, binwidth, low, up, hwidth, hmin, hmax +pointer sp, inmasks, fieldstr, fields, image, imask, omask, masktemp, str, str2 +pointer mst, vs, ve, im, pmim, pmout, opm, mp, buf, hgm, smsk +int i, imlist, inlist, outlist, nclip, nfields, format, mval, npts, npix +int nbins, in_invert, nbad, cache, old_size + +real clgetr() +pointer yt_mappm(), mp_miopen() +int imtopenp(), imtopen(), imtlen(), imtgetim(), immap(), clgeti() +int mst_fields(), btoi(), mio_glsegr(), mst_ihist(), imstati() +int mst_umask(), strmatch() +bool clgetb() +errchk immap(), yt_mappm(), yt_pminvert() + +begin + # Allocate working space. + call smark (sp) + call salloc (inmasks, SZ_FNAME, TY_CHAR) + call salloc (fieldstr, SZ_LINE, TY_CHAR) + call salloc (fields, MIS_NFIELDS, TY_INT) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imask, SZ_FNAME, TY_CHAR) + call salloc (omask, SZ_FNAME, TY_CHAR) + call salloc (masktemp, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + call salloc (str2, SZ_FNAME, TY_CHAR) + + call salloc (vs, IM_MAXDIM, TY_LONG) + call salloc (ve, IM_MAXDIM, TY_LONG) + + # Open the input image list. + imlist = imtopenp ("images") + if (imtlen (imlist) <= 0) { + call eprintf ("The input image list is empty\n") + call imtclose (imlist) + call sfree (sp) + return + } + + # Get the input mask specification + call clgstr ("imasks", Memc[inmasks+1], SZ_FNAME) + if (Memc[inmasks+1] == '^') { + in_invert = YES + inlist = imtopen (Memc[inmasks+2]) + } else { + in_invert = NO + inlist = imtopen (Memc[inmasks+1]) + } + if (imtlen (inlist) > 1 && imtlen (inlist) != imtlen (imlist)) { + call eprintf ("The input mask and image lists don't match\n") + call imtclose (inlist) + call imtclose (imlist) + call sfree (sp) + return + } + + # Open the output mask list. The number of output masks must be + # zero equal to the number of input images. + outlist = imtopenp ("omasks") + if (imtlen (outlist) > 0 && imtlen(outlist) != imtlen(imlist)) { + call eprintf ("The output mask and image lists don't match\n") + call imtclose (outlist) + call imtclose (inlist) + call imtclose (imlist) + call sfree (sp) + return + } + + # Get algorithm parameters. + call clgstr ("fields", Memc[fieldstr], SZ_LINE) + lower = clgetr ("lower") + upper = clgetr ("upper") + nclip = clgeti ("nclip") + lsigma = clgetr ("lsigma") + usigma = clgetr ("usigma") + binwidth = clgetr ("binwidth") + if (nclip > 0 && IS_INDEFR(lsigma) && IS_INDEFR(usigma)) + nclip = 0 + + # Get the other parameters. + format = btoi(clgetb ("format")) + cache = btoi(clgetb ("cache")) + + # Allocate space for statistics structure. + call mst_allocate (mst) + + # Get the selected fields. + nfields = mst_fields (Memc[fieldstr], Memi[fields], MIS_NFIELDS) + if (nfields <= 0) { + call imtclose (outlist) + call imtclose (inlist) + call imtclose (imlist) + call sfree (sp) + return + } + + # Set the processing switches + call mst_switches (mst, Memi[fields], nfields, nclip) + + if (format == YES) + call mst_pheader (Memi[fields], nfields) + + # Loop over the input images. + while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) { + + # Open the input image. + iferr (im = immap (Memc[image], READ_ONLY, 0)) { + call printf ("Error reading image %s ...\n") + call pargstr (Memc[image]) + next + } + + # Open the input mask. + if (imtgetim (inlist, Memc[str+1], SZ_FNAME) != EOF) { + Memc[str] = '^' + if (in_invert == YES) + pmim = yt_mappm (Memc[str+1], im, "logical", + Memc[imask], SZ_FNAME) + else + pmim = yt_mappm (Memc[str], im, "logical", + Memc[imask], SZ_FNAME) + } else if (imtlen (inlist) == 1) { + Memc[inmasks] = '^' + if (in_invert == YES) + pmim = yt_mappm (Memc[inmasks+1], im, "logical", + Memc[imask], SZ_FNAME) + else + pmim = yt_mappm (Memc[inmasks], im, "logical", + Memc[imask], SZ_FNAME) + } else + pmim = yt_mappm ("^EMPTY", im, "logical", Memc[imask], SZ_FNAME) + + # Check the mask status and open an empty mask if there + # was an error. + if (pmim == NULL) { + call printf ("Error reading mask for image %s ...\n") + call pargstr (Memc[image]) + call imunmap (im) + next + } + + # Get the output mask name if any and open a VIRTUAL output + # mask. + if (imtlen (outlist) > 0) { + if (imtgetim (outlist, Memc[omask], SZ_FNAME) == EOF) { + call imunmap (pmim) + call imunmap (im) + next + } else { + if (strmatch (Memc[omask], ".pl$") == 0) + call strcat (".pl", Memc[omask], SZ_FNAME) + if (Memc[imask] == '^') + call xt_mkimtemp (Memc[imask+1], Memc[omask], + Memc[masktemp], SZ_FNAME) + else + call xt_mkimtemp (Memc[imask], Memc[omask], + Memc[masktemp], SZ_FNAME) + pmout = immap (Memc[omask], NEW_COPY, im) + call mp_mpcopy (im, pmim, pmout) + } + } else { + pmout = NULL + } + + if (cache == YES) + call mst_cache1 (cache, im, old_size) + + # Set up the input masking parameters. + mp = mp_miopen (im, pmim) + + # Compute the image statistics. + low = lower + up = upper + do i = 0 , nclip { + + # Set up the mask i/o boundaries. + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + call amovl (IM_LEN(im,1), Meml[ve], IM_NDIM(im)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(im)) + + # Initialize the statistics computation. + call mst_initialize (mst, low, up) + + # Accumulate the sums. + if (MIS_SKURTOSIS(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate4 (mst, Memr[buf], npts, low, up, + MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SSKEW(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate3 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SSTDDEV(MIS_SW(mst)) == YES || + MIS_SMEDIAN(MIS_SW(mst)) == YES || + MIS_SMODE(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate2 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SMEAN(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate1 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SNPIX(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate0 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SMINMAX(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate0 (mst, Memr[buf], npts, + low, up, YES) + } + + # Compute the central moment statistics. + call mst_stats (mst) + + # Compute new limits and iterate. + if (i < nclip) { + if (IS_INDEFR(lsigma) || IS_INDEFR(MIS_MEAN(mst)) || + IS_INDEFR(MIS_STDDEV(mst))) + low = -MAX_REAL + else if (lsigma > 0.0) + low = MIS_MEAN(mst) - lsigma * MIS_STDDEV(mst) + else + low = -MAX_REAL + if (IS_INDEFR(usigma) || IS_INDEFR(MIS_MEAN(mst)) || + IS_INDEFR(MIS_STDDEV(mst))) + up = MAX_REAL + else if (usigma > 0.0) + up = MIS_MEAN(mst) + usigma * MIS_STDDEV(mst) + else + up = MAX_REAL + if (!IS_INDEFR(lower)) + low = max (low, lower) + if (!IS_INDEFR(upper)) + up = min (up, upper) + if (i > 0) { + if (MIS_NPIX(mst) == npix) + break + } + npix = MIS_NPIX(mst) + } + + } + + # Estimate the median and the mode by accumulating the histogram. + hgm = NULL + if ((MIS_SMEDIAN(MIS_SW(mst)) == YES || + MIS_SMODE(MIS_SW(mst)) == YES) && mst_ihist (mst, binwidth, + hgm, nbins, hwidth, hmin, hmax) == YES) { + call aclri (Memi[hgm], nbins) + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + call amovl (IM_LEN(im,1), Meml[ve], IM_NDIM(im)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(im)) + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call ahgmr (Memr[buf], npts, Memi[hgm], nbins, hmin, hmax) + if (MIS_SMEDIAN(MIS_SW(mst)) == YES) + call mst_hmedian (mst, Memi[hgm], nbins, hwidth, hmin, + hmax) + if (MIS_SMODE(MIS_SW(mst)) == YES) + call mst_hmode (mst, Memi[hgm], nbins, hwidth, hmin, hmax) + } + if (hgm != NULL) + call mfree (hgm, TY_INT) + + # Print the statistics. + if (format == YES) + call mst_print (Memc[image], Memc[imask], mst, Memi[fields], + nfields) + else + call mst_fprint (Memc[image], Memc[imask], mst, Memi[fields], + nfields) + + # Save the new mask to an output image. + if (pmout != NULL) { + call malloc (smsk, IM_LEN(im,1), TY_SHORT) + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + call amovl (IM_LEN(im,1), Meml[ve], IM_NDIM(im)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(im)) + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + opm = imstati (pmout, IM_PMDES) + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) { + nbad = mst_umask (Memr[buf], Mems[smsk], npts, low, up) + if (nbad > 0) + call pm_plps (opm, Meml[vs], Mems[smsk], 1, npts, + PIX_SRC) + } + call yt_pminvert (opm) + call imseti (pmout, IM_PMDES, opm) + call mfree (smsk, TY_SHORT) + } + + # Close the images and descriptors. + call mio_close (mp) + if (pmout != NULL) { + #call pm_savef (opm, Memc[omask], "", 0) + call imunmap (pmout) + call imunmap (pmim) + call xt_delimtemp (Memc[omask], Memc[masktemp]) + } else + call imunmap (pmim) + call imunmap (im) + if (cache == YES) + call fixmem (old_size) + } + + call mst_free (mst) + call imtclose (outlist) + call imtclose (inlist) + call imtclose (imlist) + + call sfree (sp) +end + + +# MST_UMASK -- Update the mask. + +int procedure mst_umask (pix, msk, npts, lower, upper) + +real pix[ARB] #I array of image pixels +short msk[ARB] #O array of mask pixels, set to 1 and 0 +int npts #I the number of pixels +real lower #I the lower good data limit +real upper #I the upper good data limit + +real lo, up +int i, nbad + +begin + if (IS_INDEFR(lower) && IS_INDEFR(upper)) + return (0) + + if (IS_INDEFR(lower)) + lo = -MAX_REAL + else + lo = lower + if (IS_INDEFR(upper)) + up = MAX_REAL + else + up = upper + + nbad = 0 + do i = 1, npts { + if (pix[i] < lo || pix[i] > up) { + msk[i] = 0 + nbad = nbad + 1 + } else + msk[i] = 1 + } + + return (nbad) +end + + diff --git a/pkg/proto/masks/t_mimstat.xBAK b/pkg/proto/masks/t_mimstat.xBAK new file mode 100644 index 00000000..e986b5c5 --- /dev/null +++ b/pkg/proto/masks/t_mimstat.xBAK @@ -0,0 +1,366 @@ +include <mach.h> +include <imhdr.h> +include <imset.h> +include <pmset.h> +include "mimstat.h" + +# T_MIMSTATISTICS -- Compute image statistics through masks. + +procedure t_mimstatistics() + +real lower, upper, lsigma, usigma, binwidth, low, up, hwidth, hmin, hmax +pointer sp, inmasks, fieldstr, fields, image, imask, omask, masktemp, str, str2 +pointer mst, vs, ve, im, pmim, pmout, opm, mp, buf, hgm, smsk +int i, imlist, inlist, outlist, nclip, nfields, format, mval, npts, npix +int nbins, in_invert, nbad, cache, old_size + +real clgetr() +pointer yt_mappm(), mp_miopen() +int imtopenp(), imtopen(), imtlen(), imtgetim(), immap(), clgeti() +int mst_fields(), btoi(), mio_glsegr(), mst_ihist(), imstati() +int mst_umask(), strmatch() +bool clgetb() +errchk immap(), yt_mappm(), yt_pminvert() + +begin + # Allocate working space. + call smark (sp) + call salloc (inmasks, SZ_FNAME, TY_CHAR) + call salloc (fieldstr, SZ_LINE, TY_CHAR) + call salloc (fields, MIS_NFIELDS, TY_INT) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (imask, SZ_FNAME, TY_CHAR) + call salloc (omask, SZ_FNAME, TY_CHAR) + call salloc (masktemp, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + call salloc (str2, SZ_FNAME, TY_CHAR) + + call salloc (vs, IM_MAXDIM, TY_LONG) + call salloc (ve, IM_MAXDIM, TY_LONG) + + # Open the input image list. + imlist = imtopenp ("images") + if (imtlen (imlist) <= 0) { + call eprintf ("The input image list is empty\n") + call imtclose (imlist) + call sfree (sp) + return + } + + # Get the input mask specification + call clgstr ("imasks", Memc[inmasks], SZ_FNAME) + if (Memc[inmasks] == '^') { + in_invert = YES + inlist = imtopen (Memc[inmasks+1]) + } else { + in_invert = NO + inlist = imtopen (Memc[inmasks]) + } + if (imtlen (inlist) > 1 && imtlen (inlist) != imtlen (imlist)) { + call eprintf ("The input mask and image lists don't match\n") + call imtclose (inlist) + call imtclose (imlist) + call sfree (sp) + return + } + + # Open the output mask list. The number of output masks must be + # zero equal to the number of input images. + outlist = imtopenp ("omasks") + if (imtlen (outlist) > 0 && imtlen(outlist) != imtlen(imlist)) { + call eprintf ("The output mask and image lists don't match\n") + call imtclose (outlist) + call imtclose (inlist) + call imtclose (imlist) + call sfree (sp) + return + } + + # Get algorithm parameters. + call clgstr ("fields", Memc[fieldstr], SZ_LINE) + lower = clgetr ("lower") + upper = clgetr ("upper") + nclip = clgeti ("nclip") + lsigma = clgetr ("lsigma") + usigma = clgetr ("usigma") + binwidth = clgetr ("binwidth") + if (nclip > 0 && IS_INDEFR(lsigma) && IS_INDEFR(usigma)) + nclip = 0 + + # Get the other parameters. + format = btoi(clgetb ("format")) + cache = btoi(clgetb ("cache")) + + # Allocate space for statistics structure. + call mst_allocate (mst) + + # Get the selected fields. + nfields = mst_fields (Memc[fieldstr], Memi[fields], MIS_NFIELDS) + if (nfields <= 0) { + call imtclose (outlist) + call imtclose (inlist) + call imtclose (imlist) + call sfree (sp) + return + } + + # Set the processing switches + call mst_switches (mst, Memi[fields], nfields, nclip) + + if (format == YES) + call mst_pheader (Memi[fields], nfields) + + # Loop over the input images. + while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) { + + # Open the input image. + iferr (im = immap (Memc[image], READ_ONLY, 0)) { + call printf ("Error reading image %s ...\n") + call pargstr (Memc[image]) + next + } + + # Open the input mask. + if (imtgetim (inlist, Memc[str+1], SZ_FNAME) != EOF) { + if (in_invert == YES) { + Memc[str] = '^' + #pmim = mp_open (Memc[str], im, Memc[imask], SZ_FNAME) + pmim = yt_mappm (Memc[str], im, "logical", + Memc[imask], SZ_FNAME) + } else + #pmim = mp_open (Memc[str+1], im, Memc[imask], SZ_FNAME) + pmim = yt_mappm (Memc[str+1], im, "logical", + Memc[imask], SZ_FNAME) + } else if (imtlen (inlist) == 1) { + #pmim = mp_open (Memc[inmasks], im, Memc[imask], SZ_FNAME) + pmim = yt_mappm (Memc[inmasks], im, "logical", + Memc[imask], SZ_FNAME) + } else { + #pmim = mp_open ("", im, Memc[imask], SZ_FNAME) + pmim = yt_mappm ("EMPTY", im, "logical", Memc[imask], SZ_FNAME) + } + + # Check the mask status and open an empty mask if there + # was an error. + if (pmim == NULL) { + call printf ("Error reading mask for image %s ...\n") + call pargstr (Memc[image]) + call imunmap (im) + next + } + + # Invert the mask. + if (pmim != NULL) { + opm = imstati (pmim, IM_PMDES) + call yt_pminvert (opm) + call imseti (pmim, IM_PMDES, opm) + } + + # Get the output mask name if any and open a VIRTUAL output + # mask. + if (imtlen (outlist) > 0) { + if (imtgetim (outlist, Memc[omask], SZ_FNAME) == EOF) { + call imunmap (pmim) + call imunmap (im) + next + } else { + if (strmatch (Memc[omask], ".pl$") == 0) + call strcat (".pl", Memc[omask], SZ_FNAME) + if (Memc[imask] == '^') + call xt_mkimtemp (Memc[imask+1], Memc[omask], + Memc[masktemp], SZ_FNAME) + else + call xt_mkimtemp (Memc[imask], Memc[omask], + Memc[masktemp], SZ_FNAME) + pmout = immap (Memc[omask], NEW_COPY, im) + call mp_mpcopy (im, pmim, pmout) + } + } else { + pmout = NULL + } + + if (cache == YES) + call mst_cache1 (cache, im, old_size) + + # Set up the input masking parameters. + mp = mp_miopen (im, pmim) + + # Compute the image statistics. + low = lower + up = upper + do i = 0 , nclip { + + # Set up the mask i/o boundaries. + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + call amovl (IM_LEN(im,1), Meml[ve], IM_NDIM(im)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(im)) + + # Initialize the statistics computation. + call mst_initialize (mst, low, up) + + # Accumulate the sums. + if (MIS_SKURTOSIS(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate4 (mst, Memr[buf], npts, low, up, + MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SSKEW(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate3 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SSTDDEV(MIS_SW(mst)) == YES || + MIS_SMEDIAN(MIS_SW(mst)) == YES || + MIS_SMODE(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate2 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SMEAN(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate1 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SNPIX(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate0 (mst, Memr[buf], npts, + low, up, MIS_SMINMAX(MIS_SW(mst))) + } else if (MIS_SMINMAX(MIS_SW(mst)) == YES) { + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call mst_accumulate0 (mst, Memr[buf], npts, + low, up, YES) + } + + # Compute the central moment statistics. + call mst_stats (mst) + + # Compute new limits and iterate. + if (i < nclip) { + if (IS_INDEFR(lsigma) || IS_INDEFR(MIS_MEAN(mst)) || + IS_INDEFR(MIS_STDDEV(mst))) + low = -MAX_REAL + else if (lsigma > 0.0) + low = MIS_MEAN(mst) - lsigma * MIS_STDDEV(mst) + else + low = -MAX_REAL + if (IS_INDEFR(usigma) || IS_INDEFR(MIS_MEAN(mst)) || + IS_INDEFR(MIS_STDDEV(mst))) + up = MAX_REAL + else if (usigma > 0.0) + up = MIS_MEAN(mst) + usigma * MIS_STDDEV(mst) + else + up = MAX_REAL + if (i > 0) { + if (MIS_NPIX(mst) == npix) + break + } + npix = MIS_NPIX(mst) + } + + } + + # Estimate the median and the mode by accumulating the histogram. + hgm = NULL + if ((MIS_SMEDIAN(MIS_SW(mst)) == YES || + MIS_SMODE(MIS_SW(mst)) == YES) && mst_ihist (mst, binwidth, + hgm, nbins, hwidth, hmin, hmax) == YES) { + call aclri (Memi[hgm], nbins) + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + call amovl (IM_LEN(im,1), Meml[ve], IM_NDIM(im)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(im)) + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) + call ahgmr (Memr[buf], npts, Memi[hgm], nbins, hmin, hmax) + if (MIS_SMEDIAN(MIS_SW(mst)) == YES) + call mst_hmedian (mst, Memi[hgm], nbins, hwidth, hmin, + hmax) + if (MIS_SMODE(MIS_SW(mst)) == YES) + call mst_hmode (mst, Memi[hgm], nbins, hwidth, hmin, hmax) + } + if (hgm != NULL) + call mfree (hgm, TY_INT) + + # Print the statistics. + if (format == YES) + call mst_print (Memc[image], Memc[imask], mst, Memi[fields], + nfields) + else + call mst_fprint (Memc[image], Memc[imask], mst, Memi[fields], + nfields) + + # Save the new mask to an output image. + if (pmout != NULL) { + call malloc (smsk, IM_LEN(im,1), TY_SHORT) + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + call amovl (IM_LEN(im,1), Meml[ve], IM_NDIM(im)) + call mio_setrange (mp, Meml[vs], Meml[ve], IM_NDIM(im)) + call amovkl (long(1), Meml[vs], IM_NDIM(im)) + opm = imstati (pmout, IM_PMDES) + while (mio_glsegr (mp, buf, mval, Meml[vs], npts) != EOF) { + nbad = mst_umask (Memr[buf], Mems[smsk], npts, low, up) + if (nbad > 0) + call pm_plps (opm, Meml[vs], Mems[smsk], 1, npts, + PIX_SRC) + } + call mp_invert (opm) + call imseti (pmout, IM_PMDES, opm) + call mfree (smsk, TY_SHORT) + } + + # Close the images and descriptors. + call mio_close (mp) + if (pmout != NULL) { + #call pm_savef (opm, Memc[omask], "", 0) + call imunmap (pmout) + call imunmap (pmim) + call xt_delimtemp (Memc[omask], Memc[masktemp]) + } else + call imunmap (pmim) + call imunmap (im) + if (cache == YES) + call fixmem (old_size) + } + + call mst_free (mst) + call imtclose (outlist) + call imtclose (inlist) + call imtclose (imlist) + + call sfree (sp) +end + + +# MST_UMASK -- Update the mask. + +int procedure mst_umask (pix, msk, npts, lower, upper) + +real pix[ARB] #I array of image pixels +short msk[ARB] #O array of mask pixels, set to 1 and 0 +int npts #I the number of pixels +real lower #I the lower good data limit +real upper #I the upper good data limit + +real lo, up +int i, nbad + +begin + if (IS_INDEFR(lower) && IS_INDEFR(upper)) + return (0) + + if (IS_INDEFR(lower)) + lo = -MAX_REAL + else + lo = lower + if (IS_INDEFR(upper)) + up = MAX_REAL + else + up = upper + + nbad = 0 + do i = 1, npts { + if (pix[i] < lo || pix[i] > up) { + msk[i] = 0 + nbad = nbad + 1 + } else + msk[i] = 1 + } + + return (nbad) +end + + diff --git a/pkg/proto/masks/t_rskysub.x b/pkg/proto/masks/t_rskysub.x new file mode 100644 index 00000000..85f0b991 --- /dev/null +++ b/pkg/proto/masks/t_rskysub.x @@ -0,0 +1,248 @@ +include <imhdr.h> +include "rskysub.h" + +# T_RSKYSUB -- Sky subtract a set of input images using image scaling and +# a running statistics compution + +procedure t_rskysub() + +pointer sp, imasks, str +pointer rs +int inlist, imsklist, outlist, omsklist, hmsklist, sclist, tmplist +bool msk_invert, useimasks, cache, verbose + +real clgetr() +int imtopenp(), imtopen(), imtlen(), fntopnb(), fntlenb() +int clgeti(), btoi(), clgwrd(), rs_imlist(), rs_olist(), rs_omlist() +bool clgetb(), strne() + +begin + # Allocate working space. + call smark (sp) + call salloc (imasks, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_FNAME, TY_CHAR) + + # Open the input image list. Make this a test versus nmin ? + inlist = imtopenp ("input") + if (imtlen (inlist) <= 0) { + call eprintf ("The input image list is empty\n") + call imtclose (inlist) + call sfree (sp) + return + } + + # Open the output image list. The number of output images must be + # zero equal to the number of input images. + call clgstr ("output", Memc[str], SZ_FNAME) + outlist = rs_olist (inlist, Memc[str], "default", "sub") + if (imtlen (outlist) > 0 && imtlen(outlist) != imtlen(inlist)) { + call eprintf ("The output mask and image lists don't match\n") + call imtclose (outlist) + call imtclose (inlist) + call sfree (sp) + return + } + + # Open the input mask list. + call clgstr ("imasks", Memc[imasks], SZ_FNAME) + if (Memc[imasks] == '^') { + #imsklist = imtopen (Memc[imasks+1]) + imsklist = rs_imlist (inlist, Memc[imasks+1], "default", "obm") + msk_invert = true + } else { + #imsklist = imtopen (Memc[imasks]) + imsklist = rs_imlist (inlist, Memc[imasks], "default", "obm") + msk_invert = false + } + if (imtlen (imsklist) > 1 && imtlen (imsklist) != imtlen (inlist)) { + call eprintf ("The input mask and image lists don't match\n") + call imtclose (imsklist) + call imtclose (outlist) + call imtclose (inlist) + call sfree (sp) + return + } + + # Open the output mask list. The number of output masks must be + # zero equal to the number of input images. + call clgstr ("omasks", Memc[str], SZ_FNAME) + omsklist = rs_omlist (inlist, Memc[str], "default", "skm") + if (imtlen (omsklist) > 0 && imtlen(omsklist) != imtlen(inlist)) { + call eprintf ("The output mask and image lists don't match\n") + call imtclose (omsklist) + call imtclose (imsklist) + call imtclose (outlist) + call imtclose (inlist) + call sfree (sp) + return + } + + # Open the output holes mask list. The number of output holes masks + # must be zero equal to the number of input images. + call clgstr ("hmasks", Memc[str], SZ_FNAME) + hmsklist = rs_omlist (inlist, Memc[str], "default", "hom") + if (imtlen (hmsklist) > 0 && imtlen(hmsklist) != imtlen(inlist)) { + call eprintf ("The holes mask and image lists don't match\n") + call imtclose (hmsklist) + call imtclose (omsklist) + call imtclose (imsklist) + call imtclose (outlist) + call imtclose (inlist) + call sfree (sp) + return + } + + # Allocate the sky subtraction structure + call malloc (rs, LEN_RSKYSUB, TY_STRUCT) + + # Get the scaling factor computation method. + RS_RESCALE(rs) = btoi(clgetb ("rescale")) + call clgstr ("scale", RS_ISCALES(rs), SZ_FNAME) + sclist = fntopnb (RS_ISCALES(rs), NO) + if (fntlenb (sclist) > 1 && fntlenb (sclist) != imtlen (inlist)) { + call eprintf ("The scaling factor and image lists don't match\n") + call fntclsb (sclist) + call imtclose (hmsklist) + call imtclose (omsklist) + call imtclose (imsklist) + call imtclose (outlist) + call imtclose (inlist) + call sfree (sp) + return + } + + # If the scaling algorith is not "median" then new output masks + # cannot be created. + if (strne (RS_ISCALES(rs), "median")) { + call imtclose (omsklist) + omsklist = imtopen ("") + } + call clgstr ("skyscale", RS_KYFSCALE(rs), SZ_FNAME) + + # Get statisitics computation parameters. + useimasks = clgetb ("useimasks") + call clgstr ("statsec", RS_STATSEC(rs), SZ_FNAME) + RS_LOWER(rs) = clgetr ("lower") + RS_UPPER(rs) = clgetr ("upper") + RS_MAXITER(rs) = clgeti ("maxiter") + RS_LNSIGREJ(rs) = clgetr ("lnsigrej") + RS_UNSIGREJ(rs) = clgetr ("unsigrej") + RS_BINWIDTH(rs) = clgetr ("binwidth") + if (RS_MAXITER(rs) > 0 && IS_INDEFR(RS_LNSIGREJ(rs)) && + IS_INDEFR(RS_UNSIGREJ(rs))) + RS_MAXITER(rs) = 0 + + # Get the sky subtraction parameters + RS_RESUBTRACT(rs) = btoi(clgetb ("resubtract")) + RS_COMBINE(rs) = clgwrd ("combine", Memc[str], SZ_FNAME, RS_COMBINESTR) + RS_NCOMBINE(rs) = clgeti ("ncombine") + RS_NMIN(rs) = clgeti ("nmin") + if (RS_NMIN(rs) <= 0 || RS_NMIN(rs) > RS_NCOMBINE(rs)) { + RS_NMIN(rs) = RS_NCOMBINE(rs) + call eprintf ("Warning: resetting nmin to %d\n") + call pargi (RS_NMIN(rs)) + } + + # Get starting values for the rejection parameters. These may have + # to be adjusted if image masking is enabled and for cases where + # the number of combined images is greater then equal to nmin but + # less than ncombine. + RS_NLOREJ(rs) = clgeti ("nlorej") + RS_NHIREJ(rs) = clgeti ("nhirej") + switch (RS_COMBINE(rs)) { + case RS_MEAN: + if ((RS_NMIN(rs) - RS_NLOREJ(rs) - RS_NHIREJ(rs)) < 1) { + call eprintf ("Too many rejected pixels\n") + call fntclsb (sclist) + call imtclose (hmsklist) + call imtclose (omsklist) + call imtclose (imsklist) + call imtclose (outlist) + call imtclose (inlist) + call sfree (sp) + return + } + case RS_MEDIAN: + if (mod (RS_NCOMBINE(rs), 2) == 0) { + RS_NLOREJ(rs) = RS_NCOMBINE(rs) / 2 - 1 + RS_NHIREJ(rs) = RS_NCOMBINE(rs) / 2 - 1 + } else { + RS_NLOREJ(rs) = RS_NCOMBINE(rs) / 2 + RS_NHIREJ(rs) = RS_NCOMBINE(rs) / 2 + } + default: + } + RS_BLANK(rs) = clgetr ("blank") + call clgstr ("skysub", RS_KYSKYSUB(rs), SZ_FNAME) + call clgstr ("holes", RS_KYHMASK(rs), SZ_FNAME) + + cache = clgetb ("cache") + verbose = clgetb ("verbose") + + # Compute the sky statistics and optionally the output sky masks. + + if (useimasks) { + call rs_stats (inlist, imsklist, omsklist, sclist, rs, msk_invert, + cache, verbose) + } else { + tmplist = imtopen ("") + call rs_stats (inlist, tmplist, omsklist, sclist, rs, msk_invert, + cache, verbose) + call imtclose (tmplist) + } + + # Do the sky subtraction with or without image masking and with or + # without bad pixel rejection. Unmasked image medians can be handled + # by setting the high and low pixel rejection parameters appropriately. + # Masked image means and medians may require dynaimc altering of the + # high and low rejection parameters. + + switch (RS_COMBINE(rs)) { + case RS_MEAN, RS_MEDIAN: + if (imtlen (omsklist) > 0) { + if (RS_NLOREJ(rs) > 0 || RS_NHIREJ(rs) > 0) + # Choose which of the two routines to use later based + # on timing tests. + #call rs_prmsub (inlist, omsklist, outlist, hmsklist, rs, + #msk_invert, cache, verbose) + call rs_prrmsub (inlist, omsklist, outlist, hmsklist, rs, + msk_invert, cache, verbose) + else + call rs_pmsub (inlist, omsklist, outlist, hmsklist, rs, + msk_invert, cache, verbose) + } else if (imtlen (imsklist) > 0) { + if (RS_NLOREJ(rs) > 0 || RS_NHIREJ(rs) > 0) + # Choose which of the two routines to use later based on + # timing tests. + #call rs_prmsub (inlist, imsklist, outlist, hmsklist, rs, + #msk_invert, cache, verbose) + call rs_prrmsub (inlist, imsklist, outlist, hmsklist, rs, + msk_invert, cache, verbose) + else + call rs_pmsub (inlist, imsklist, outlist, hmsklist, rs, + msk_invert, cache, verbose) + } else { + if (RS_NLOREJ(rs) > 0 || RS_NHIREJ(rs) > 0) + # Choose which of the two routines to use later based on + # timing tests. + #call rs_rmsub (inlist, outlist, rs, cache, verbose) + call rs_rrmsub (inlist, outlist, rs, cache, verbose) + else + call rs_msub (inlist, outlist, rs, cache, verbose) + } + default: + ; + } + + # Close image and file lists. + call fntclsb (sclist) + call imtclose (hmsklist) + call imtclose (imsklist) + call imtclose (omsklist) + call imtclose (outlist) + call imtclose (inlist) + + call mfree (rs, TY_STRUCT) + call sfree (sp) +end + |