aboutsummaryrefslogtreecommitdiff
path: root/noao/twodspec/apextract/apvariance.x
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /noao/twodspec/apextract/apvariance.x
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'noao/twodspec/apextract/apvariance.x')
-rw-r--r--noao/twodspec/apextract/apvariance.x420
1 files changed, 420 insertions, 0 deletions
diff --git a/noao/twodspec/apextract/apvariance.x b/noao/twodspec/apextract/apvariance.x
new file mode 100644
index 00000000..015eed74
--- /dev/null
+++ b/noao/twodspec/apextract/apvariance.x
@@ -0,0 +1,420 @@
+include <gset.h>
+include "apertures.h"
+
+
+# AP_VARIANCE -- Variance weighted extraction based on profile and CCD noise.
+# If desired reject deviant pixels. In addition to the variance weighted
+# spectrum, the unweighted and uncleaned "raw" spectrum is extracted and
+# a sigma spectrum is returned. Wavelengths with saturated pixels are
+# flagged with 0 value and negative sigma if cleaning.
+
+procedure ap_variance (im, ap, dbuf, nc, nl, c1, l1, sbuf, svar, profile,
+ nx, ny, xs, ys, spec, raw, specsig, nsubaps, asi)
+
+pointer im # IMIO pointer
+pointer ap # Aperture structure
+pointer dbuf # Data buffer
+int nc, nl # Size of data buffer
+int c1, l1 # Origin of data buffer
+pointer sbuf # Sky values (NULL if none)
+pointer svar # Sky variance
+real profile[ny,nx] # Profile (returned)
+int nx, ny # Size of profile array
+int xs[ny], ys # Origin of profile array
+real spec[ny,nsubaps] # Spectrum
+real raw[ny,nsubaps] # Raw spectrum
+real specsig[ny,nsubaps] # Sky variance in, spectrum sigma out
+int nsubaps # Number of subapertures
+pointer asi # Image interpolator for edge pixel weighting
+
+real rdnoise # Readout noise in RMS data numbers.
+real gain # Gain in photons per data number.
+real saturation # Maximum value for an unsaturated pixel.
+bool clean # Clean cosmic rays?
+real nclean # Number of pixels to clean
+real lsigma, usigma # Rejection sigmas.
+
+bool sat
+int fd, iterate, niterate, nrej, irej, nreject
+int i, ix, iy, ix1, ix2
+real low, high, step, shift, x1, x2, wt1, wt2, s, w, dat, sk, var, var0
+real sum, wsum, wvsum, sum1, sum2, total1, total2
+real vmin, resid, rrej
+pointer cv, gp
+pointer sp, str, work, wt, xplot, yplot, eplot, fplot, data, sky, data1
+
+real apgetr(), apgimr(), ap_cveval()
+bool apgetb()
+errchk apgimr, ap_asifit
+
+begin
+ # Get task parameters.
+ gain = apgimr ("gain", im)
+ rdnoise = apgimr ("readnoise", im) ** 2
+ saturation = apgetr ("saturation")
+ if (!IS_INDEF(saturation))
+ saturation = saturation * gain
+ clean = apgetb ("clean")
+ lsigma = apgetr ("lsigma")
+ usigma = apgetr ("usigma")
+ call ap_popen (gp, fd, "clean")
+
+ # Allocate memory and one index.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (work, 6*nx, TY_REAL)
+ wt = work - 1
+ xplot = wt + nx
+ yplot = xplot + nx
+ eplot = yplot + nx
+ fplot = eplot + nx
+ data1 = fplot + nx
+ if (sbuf == NULL) {
+ call salloc (sky, nx, TY_REAL)
+ call aclrr (Memr[sky], nx)
+ sky = sky - 1
+ var0 = rdnoise
+ }
+
+ # Initialize
+ if (rdnoise == 0.)
+ vmin = 1.
+ else
+ vmin = rdnoise
+ if (clean) {
+ nclean = apgetr ("nclean")
+ if (nclean < 1.)
+ niterate = max (1., nclean * nx)
+ else
+ niterate = max (1., min (real (nx), nclean))
+ } else
+ niterate = 0
+
+ call aclrr (spec, ny * nsubaps)
+ call aclrr (raw, ny * nsubaps)
+ call amovkr (-1., specsig, ny * nsubaps)
+
+ i = AP_AXIS(ap)
+ low = AP_CEN(ap,i) + AP_LOW(ap,i)
+ high = AP_CEN(ap,i) + AP_HIGH(ap,i)
+ step = (high - low) / nsubaps
+ cv = AP_CV(ap)
+
+ # For each line compute the weighted spectrum and then iterate
+ # to reject deviant pixels. Rejected pixels are flagged by negative
+ # variance.
+
+ nreject = 0
+ total1 = 0.
+ total2 = 0.
+ do iy = 1, ny {
+ shift = ap_cveval (cv, real (iy + ys - 1)) - c1 + 1
+ x1 = max (0.5, low + shift) + c1 - xs[iy]
+ x2 = min (nc + 0.49, high + shift) + c1 - xs[iy]
+ if (x1 >= x2)
+ next
+ ix1 = nint (x1)
+ ix2 = nint (x2)
+
+ call ap_asifit (dbuf+(iy+ys-1-l1)*nc, nc, xs[iy]-c1+1,
+ low+shift, high+shift, data, asi)
+# data = dbuf + (iy + ys - 1 - l1) * nc + xs[iy] - c1 - 1
+ if (sbuf != NULL) {
+ sky = sbuf + (iy - 1) * nx - 1
+ var0 = rdnoise + Memr[svar+iy-1]
+ }
+
+ # Set pixel weights for summing.
+# if (asi != NULL)
+# call asifit (asi, Memr[data], nc-xs[iy]+c1)
+ call ap_edge (asi, x1+1, x2+1, wt1, wt2)
+
+ # First estimate spectrum by summing across the aperture.
+ # Accumulate the raw spectrum and set up various arrays for
+ # plotting and later access.
+
+ sat = false
+ sum = 0.
+ wsum = 0.
+ wvsum = 0.
+ do ix = ix1, ix2 {
+ if (ix1 == ix2)
+ w = wt1
+ else if (ix == ix1)
+ w = wt1
+ else if (ix == ix2)
+ w = wt2
+ else
+ w = 1.
+ dat = Memr[data+ix]
+ if (!IS_INDEF(saturation))
+ if (dat > saturation)
+ sat = true
+ sk = Memr[sky+ix]
+ raw[iy,1] = raw[iy,1] + w * (dat - sk)
+
+ Memr[xplot+ix] = ix + xs[iy] - 1
+ Memr[yplot+ix] = dat - sk
+ Memr[data1+ix] = dat - sk
+ Memr[wt+ix] = w
+ var = max (vmin, var0 + max (0., dat))
+ w = profile[iy,ix] / var
+ var = sqrt (var)
+ Memr[eplot+ix] = var
+ sum = sum + w * (dat - sk)
+ wsum = wsum + w * profile[iy,ix]
+ wvsum = wvsum + (w * var) ** 2
+ }
+ if (wsum > 0.) {
+ spec[iy,1] = sum / wsum
+ specsig[iy,1] = sqrt (wvsum) / abs (wsum)
+ } else {
+ spec[iy,1] = 0.
+ specsig[iy,1] = -1.
+ }
+
+ sum = 0.
+ wsum = 0.
+ wvsum = 0.
+ sum1 = 0.
+ sum2 = 0.
+ do ix = ix1, ix2 {
+ sum1 = sum1 + Memr[wt+ix] * Memr[data1+ix]
+ if (Memr[eplot+ix] <= 0.)
+ next
+ sk = Memr[sky+ix]
+ s = max (0., spec[iy,1]) * profile[iy,ix]
+ var = max (vmin, var0 + (s + sk))
+ w = profile[iy,ix] / var
+ var = sqrt (var)
+ Memr[eplot+ix] = var
+ Memr[fplot+ix] = s
+ sum = sum + w * Memr[data1+ix]
+ wsum = wsum + w * profile[iy,ix]
+ wvsum = wvsum + (w * var) ** 2
+ }
+ if (wsum > 0.) {
+ spec[iy,1] = sum / wsum
+ specsig[iy,1] = sqrt (wvsum) / abs (wsum)
+ sum2 = sum2 + spec[iy,1]
+ } else {
+ spec[iy,1] = 0.
+ specsig[iy,1] = -1.
+ sum1 = 0.
+ sum2 = 0.
+ }
+
+ # Reject cosmic rays one at a time.
+ nrej = 0
+ do iterate = 1, niterate {
+ irej = 0
+ rrej = 0.
+
+ # Compute revised variance estimate using profile model
+ # skip rejected pixels, find worst pixel.
+
+ do ix = ix1, ix2 {
+ if (Memr[eplot+ix] <= 0.)
+ next
+ s = max (0., spec[iy,1]) * profile[iy,ix]
+ sk = Memr[sky+ix]
+ var = sqrt (max (vmin, var0 + max (0., s + sk)))
+ Memr[fplot+ix] = s
+ Memr[eplot+ix] = var
+
+ resid = (Memr[data1+ix] - Memr[fplot+ix]) / var
+ if (abs (resid) > abs (rrej)) {
+ rrej = resid
+ irej = ix
+ }
+ }
+
+ # Reject worst outlier.
+
+ if (rrej <= -lsigma || rrej >= usigma) {
+ Memr[eplot+irej] = -Memr[eplot+irej]
+ Memr[data1+irej] = Memr[fplot+irej]
+ nrej = nrej + 1
+ } else
+ break
+
+ # Update spectrum estimate excluding rejected pixels.
+ sum = 0.
+ wsum = 0.
+ wvsum = 0.
+ sum1 = 0.
+ sum2 = 0.
+ do ix = ix1, ix2 {
+ sum1 = sum1 + Memr[wt+ix] * Memr[data1+ix]
+ if (Memr[eplot+ix] <= 0.)
+ next
+ w = profile[iy,ix] / Memr[eplot+ix]**2
+ sum = sum + w * Memr[data1+ix]
+ wsum = wsum + w * profile[iy,ix]
+ wvsum = wvsum + (w * Memr[eplot+ix]) ** 2
+ }
+
+ if (wsum > 0.) {
+ spec[iy,1] = sum / wsum
+ specsig[iy,1] = sqrt (wvsum) / abs (wsum)
+ sum2 = sum2 + spec[iy,1]
+ } else {
+ spec[iy,1] = 0.
+ specsig[iy,1] = -1.
+ sum1 = 0.
+ sum2 = 0.
+ }
+ }
+
+ nreject = nreject + nrej
+ total1 = total1 + sum1
+ total2 = total2 + sum2
+
+ # Calculate subapertures if desired.
+ if (nsubaps > 1) {
+ do i = 1, nsubaps {
+ x1 = max (0.5, low + (i - 1) * step + shift) + c1 - xs[iy]
+ x2 = min (nc + 0.49, low + i * step + shift) + c1 - xs[iy]
+ if (x1 >= x2) {
+ spec[iy,i] = 0.
+ raw[iy,i] = 0.
+ specsig[iy,i] = -1.
+ next
+ }
+ ix1 = nint (x1)
+ ix2 = nint (x2)
+ call ap_edge (asi, x1+1, x2+1, wt1, wt2)
+
+ sum = 0.
+ wvsum = 0.
+ raw[iy,i] = 0.
+ do ix = ix1, ix2 {
+ if (ix1 == ix2)
+ w = wt1
+ else if (ix == ix1)
+ w = wt1
+ else if (ix == ix2)
+ w = wt2
+ else
+ w = 1.
+ raw[iy,i] = raw[iy,i] + w * Memr[yplot+ix]
+ if (Memr[eplot+ix] <= 0.)
+ next
+ w = profile[iy,ix] / Memr[eplot+ix]**2
+ sum = sum + w * Memr[data1+ix]
+ wvsum = wvsum + (w * Memr[eplot+ix]) ** 2
+ }
+
+ if (wsum > 0.) {
+ spec[iy,i] = sum / wsum
+ specsig[iy,i] = sqrt (wvsum) / abs (wsum)
+ } else {
+ spec[iy,i] = 0.
+ specsig[iy,i] = -1.
+ }
+ }
+ }
+
+ # Flag points with saturated pixels.
+ if (sat)
+ do i = 1, nsubaps
+ specsig[iy,i] = -specsig[iy,i]
+
+ # Plot profile with cosmic rays if desired.
+ if (gp != NULL && nrej > 0 && spec[iy,1] > 0.) {
+ call sprintf (Memc[str], SZ_LINE, "Profile %4d")
+ call pargi (iy)
+ s = Memr[yplot+ix1] - abs (Memr[eplot+ix1])
+ w = Memr[yplot+ix1] + abs (Memr[eplot+ix1])
+ do ix = ix1+1, ix2 {
+ s = min (s, Memr[yplot+ix] - abs (Memr[eplot+ix]))
+ w = max (w, Memr[yplot+ix] + abs (Memr[eplot+ix]))
+ }
+ sum = w - s
+ x1 = ix1 + xs[iy] - 2
+ x2 = ix2 + xs[iy]
+ s = s - 0.1 * sum
+ w = w + 0.1 * sum
+ call gclear (gp)
+ call gswind (gp, x1, x2, s, w)
+ call glabax (gp, Memc[str], "", "")
+
+ do ix = ix1, ix2 {
+ if (Memr[eplot+ix] > 0.) {
+ call gmark (gp, Memr[xplot+ix], Memr[yplot+ix],
+ GM_PLUS, 2., 2.)
+ call gmark (gp, Memr[xplot+ix], Memr[yplot+ix],
+ GM_VEBAR, 2., -6.*Memr[eplot+ix])
+ } else {
+ call gmark (gp, Memr[xplot+ix], Memr[yplot+ix],
+ GM_CROSS, 2., 2.)
+ call gmark (gp, Memr[xplot+ix], Memr[yplot+ix],
+ GM_VEBAR, 1., 6.*Memr[eplot+ix])
+ }
+ }
+ call gpline (gp, Memr[xplot+ix1], Memr[fplot+ix1], ix2-ix1+1)
+ }
+ }
+
+ # To avoid any bias, scale weighted extraction to same total flux
+ # as raw spectrum (with rejected pixels replaced by fit).
+
+ if (total1 * total2 <= 0.) {
+ call sprintf (Memc[str], SZ_LINE,
+ "EXTRACT: WARNING - Aperture %d:")
+ call pargi (AP_ID(ap))
+ call ap_log (Memc[str], YES, NO, YES)
+ call sprintf (Memc[str], SZ_LINE,
+ " Total variance weighted spectrum flux is %g")
+ call pargr (total2)
+ call ap_log (Memc[str], YES, NO, YES)
+ call sprintf (Memc[str], SZ_LINE,
+ " Total unweighted spectrum flux is %g")
+ call pargr (total1)
+ call ap_log (Memc[str], YES, NO, YES)
+ call sprintf (Memc[str], SZ_LINE,
+ " Variance spectrum bias factor ignored")
+ call ap_log (Memc[str], YES, NO, YES)
+ } else {
+ sum = total1 / total2
+ call amulkr (spec, sum, spec, ny * nsubaps)
+ call amulkr (specsig, sum, specsig, ny * nsubaps)
+ if (sum < .5 || sum > 2) {
+ call sprintf (Memc[str], SZ_LINE,
+ "EXTRACT: WARNING - Aperture %d:")
+ call pargi (AP_ID(ap))
+ call ap_log (Memc[str], YES, NO, YES)
+ call sprintf (Memc[str], SZ_LINE,
+ " Total variance weighted spectrum flux is %g")
+ call pargr (total2)
+ call ap_log (Memc[str], YES, NO, YES)
+ call sprintf (Memc[str], SZ_LINE,
+ " Total unweighted spectrum flux is %g")
+ call pargr (total1)
+ call ap_log (Memc[str], YES, NO, YES)
+ call sprintf (Memc[str], SZ_LINE,
+ "EXTRACT: Aperture %d variance spectrum bias factor is %g")
+ call pargi (AP_ID(ap))
+ call pargr (total1 / total2)
+ call ap_log (Memc[str], YES, NO, YES)
+ } else {
+ call sprintf (Memc[str], SZ_LINE,
+ "EXTRACT: Aperture %d variance spectrum bias factor is %g")
+ call pargi (AP_ID(ap))
+ call pargr (total1 / total2)
+ call ap_log (Memc[str], YES, NO, NO)
+ }
+ }
+
+ # Log the number of rejected pixels.
+ if (clean) {
+ call sprintf (Memc[str], SZ_LINE,
+ "EXTRACT: %d pixels rejected from aperture %d")
+ call pargi (nreject)
+ call pargi (AP_ID(ap))
+ call ap_log (Memc[str], YES, NO, NO)
+ }
+
+ call ap_pclose (gp, fd)
+ call sfree (sp)
+end