diff options
Diffstat (limited to 'noao/onedspec/sensfunc/sfextinct.x')
-rw-r--r-- | noao/onedspec/sensfunc/sfextinct.x | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/noao/onedspec/sensfunc/sfextinct.x b/noao/onedspec/sensfunc/sfextinct.x new file mode 100644 index 00000000..f7b95326 --- /dev/null +++ b/noao/onedspec/sensfunc/sfextinct.x @@ -0,0 +1,226 @@ +include <pkg/gtools.h> +include "sensfunc.h" + +define RANGE_AIRMASS 0.1 # Minimum airmass range +define SIGMA_AIRMASS 0.05 # Minimum sigma in airmass + +# SF_EXINCT -- Determine a residual extinction curve. At each wavelength +# for which there are multiple observations or neighboring wavelengths +# such that there is a sufficient airmass range determine the slope +# of the sensitivity vs airmass. Residual sensitivity is used to minimize +# wavelength scatter when multiple wavelengths are needed because of +# nonoverlapping standard star data. Each such slope is a measure of the +# residual extinction at that wavelength. To make the residual extinction +# curve fit the extinction vs. wavelength using ICFIT. + +procedure sf_extinct (gp, stds, nstds, cv, ecv, function, order) + +pointer gp # Graphics structure +pointer stds[nstds] # Standard star data +int nstds # Number of standard stars +pointer cv # Sensitivity function curve +pointer ecv # Residual extinction curve +char function[ARB] # Fitting function +int order # Function order + +bool ans +int i, j, n, nwaves, sum, npts, scan() +real a, amin, amax, rms, rms1, r2, sig, cveval() +double x, y, z, sumx, sumy, sumz, sumx2, sumxy +pointer sp, waves, sens, airm, xp, yp, fp, wp, ic +pointer gt, gt_init() +errchk salloc, xt_sort3, icg_fit, ic_open + +define cancel_ 99 + +begin + # Cancel previous extinction if defined. + if (ecv != NULL) + goto cancel_ + + # Check for minimum airmass range and determine number of points. + # Ignore added objects and composite data. + amin = 100. + amax = 0. + nwaves = 0 + do i = 1, nstds - 2 { + if (STD_FLAG(stds[i]) != SF_INCLUDE) + next + nwaves = nwaves + STD_NWAVES(stds[i]) + a = STD_AIRMASS(stds[i]) + amin = min (amin, a) + amax = max (amax, a) + } + if (amax - amin < RANGE_AIRMASS) { + call printf ( + "Insufficient airmass coverage for extinction determination") + return + } + + # Extract data to be used and sort by wavelength. + # The data is wavelength, airmass, and residual sensitivity. + call smark (sp) + call salloc (waves, nwaves, TY_REAL) + call salloc (sens, nwaves, TY_REAL) + call salloc (airm, nwaves, TY_REAL) + + nwaves = 0 + do i = 1, nstds-2 { + if (STD_FLAG(stds[i]) != SF_INCLUDE) + next + n = STD_NWAVES(stds[i]) + a = STD_AIRMASS(stds[i]) + xp = STD_WAVES(stds[i]) + yp = STD_SENS(stds[i]) + fp = STD_FIT(stds[i]) + wp = STD_WTS(stds[i]) + do j = 1, n { + if (Memr[wp] != 0.) { + Memr[airm+nwaves] = a + Memr[waves+nwaves] = Memr[xp] + Memr[sens+nwaves] = Memr[yp] - Memr[fp] + nwaves = nwaves + 1 + } + xp = xp + 1 + yp = yp + 1 + fp = fp + 1 + wp = wp + 1 + } + } + + call xt_sort3 (Memr[waves], Memr[sens], Memr[airm], nwaves) + + # Bin points with common wavelengths or at least two points. + sum = 0 + sumx = 0. + sumy = 0. + sumz = 0. + sumx2 = 0. + sumxy = 0. + n = 0 + do i = 0, nwaves-2 { + x = Memr[airm+i] + y = Memr[sens+i] + z = Memr[waves+i] + sum = sum + 1 + sumx = sumx + x + sumy = sumy + y + sumx2 = sumx2 + x * x + sumxy = sumxy + x * y + sumz = sumz + z + + if ((z == Memr[waves+i+1]) || (sum < 2)) + next + + x = sumx2 - sumx * sumx / sum + if (x > SIGMA_AIRMASS) { + Memr[waves+n] = sumz / sum + Memr[sens+n] = (sumx * sumy / sum - sumxy) / x + Memr[airm+n] = 1. + n = n + 1 + sum = 0 + sumx = 0. + sumy = 0. + sumz = 0. + sumx2 = 0. + sumxy = 0. + } + } + if (sum > 1) { + x = sumx2 - sumx * sumx / sum + if (x > SIGMA_AIRMASS) { + Memr[waves+n] = sumz / sum + Memr[sens+n] = (sumx * sumy / sum - sumxy) / x + Memr[airm+n] = 1. + n = n + 1 + } + } + + if (n < 2) { + call printf ("Cannot determine residual extinction") + call sfree (sp) + return + } + + # Fit residual extinction curve using ICFIT. + gt = gt_init() + call gt_sets (gt, GTTYPE, "mark") + call gt_seti (gt, GTCOLOR, GP_PLCOLOR(gp)) + call ic_open (ic) + call ic_putr (ic, "xmin", min (STD_WSTART(stds[1]), STD_WEND(stds[1]))) + call ic_putr (ic, "xmax", max (STD_WSTART(stds[1]), STD_WEND(stds[1]))) + call ic_pstr (ic, "function", "chebyshev") + call ic_puti (ic, "order", 1) + call ic_pstr (ic, "xlabel", "wavelength") + call ic_pstr (ic, "ylabel", "residual extinction") + call ic_pstr (ic, "yunits", "mag") + call icg_fit (ic, GP_GIO(gp), "cursor", gt, ecv, Memr[waves], + Memr[sens], Memr[airm], n) + call ic_closer (ic) + call gt_free (gt) + + # Determine significance of the fit. + call sf_fit (stds, nstds, cv, function, order, + min (GP_WSTART(gp), GP_WEND(gp)), max (GP_WSTART(gp), GP_WEND(gp))) + call sf_rms (stds, nstds, rms1, npts) + do i = 1, nstds - 2 { + if (STD_FLAG(stds[i]) != SF_INCLUDE) + next + n = STD_NWAVES(stds[i]) + a = STD_AIRMASS(stds[i]) + xp = STD_WAVES(stds[i]) + yp = STD_SENS(stds[i]) + call cvvector (ecv, Memr[xp], Memr[sens], n) + call amulkr (Memr[sens], a, Memr[sens], n) + call aaddr (Memr[yp], Memr[sens], Memr[yp], n) + } + call sf_fit (stds, nstds, cv, function, order, + min (GP_WSTART(gp), GP_WEND(gp)), max (GP_WSTART(gp), GP_WEND(gp))) + call sf_rms (stds, nstds, rms, npts) + do i = 1, SF_NGRAPHS + if (GP_SHDR(gp,i) != NULL) + call shdr_close (GP_SHDR(gp,i)) + + r2 = 1 - rms ** 2 / rms1 ** 2 + sig = r2 * (nwaves - 2) / max (0.01, 1. - r2) + if (sig <= 0.0) + sig = 0. + else + sig = sqrt (sig) + + # Apply to data if desired. + call printf ( + "Significance = %4.1f sigma: Apply residual extinction correction? ") + call pargr (sig) + call flush (STDOUT) + + ans = false + if (scan() != EOF) + call gargb (ans) + + # Undo last fit if not applying correction. + if (!ans) + goto cancel_ + + call printf ("Residual extinction correction applied") + call sfree (sp) + return + +cancel_ + do i = 1, nstds - 2 { + if (STD_FLAG(stds[i]) == SF_EXCLUDE) + next + n = STD_NWAVES(stds[i]) + a = STD_AIRMASS(stds[i]) + xp = STD_WAVES(stds[i]) + yp = STD_SENS(stds[i]) + do j = 1, n { + Memr[yp] = Memr[yp] - a * cveval (ecv, Memr[xp]) + xp = xp + 1 + yp = yp + 1 + } + } + call cvfree (ecv) + call printf ("Residual extinction correction canceled") + call sfree (sp) +end |