diff options
Diffstat (limited to 'noao/onedspec/splot/gfit.x')
-rw-r--r-- | noao/onedspec/splot/gfit.x | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/noao/onedspec/splot/gfit.x b/noao/onedspec/splot/gfit.x new file mode 100644 index 00000000..2e60d8c4 --- /dev/null +++ b/noao/onedspec/splot/gfit.x @@ -0,0 +1,391 @@ +include <error.h> +include <mach.h> +include <gset.h> + +define NSUB 3 # Number of pixel subsamples +define MC_N 50 # Monte-Carlo samples +define MC_P 10 # Percent done interval (percent) +define MC_SIG 68 # Sigma sample point (percent) + +# GFIT -- Fit Gaussian + +procedure gfit (sh, gfd, wx1, wy1, wcs, pix, n, fd1, fd2, xg, yg, sg, lg, pg,ng) + +pointer sh # SHDR pointer +pointer gfd # GIO file descriptor +real wx1, wy1 # Cursor position +real wcs[n] # Spectrum data +real pix[n] # Spectrum data +int n # Number of points +int fd1, fd2 # Output file descriptors +pointer xg, yg, sg, lg, pg # Pointers to fit parameters +int ng # Number of components + +int fit[5], nsub, mc_p, mc_sig, mc_n +int i, j, i1, npts, nlines, wc, key +long seed +real w, dw, wyc, wx, wy, wx2, wy2, v, u +real slope, peak, flux, cont, gfwhm, lfwhm, eqw, scale, sscale, chisq +real sigma0, invgain, wyc1, slope1, flux1, cont1, eqw1 +bool fitit +pointer xg1, yg1, sg1, lg1 +pointer sp, cmd, x, y, s, z, ym, conte, xge, yge, sge, lge, fluxe, eqwe + +int clgeti(), clgcur() +real clgetr(), model(), gasdev(), asumr() +errchk dofit, dorefit + +define done_ 99 + +begin + call smark (sp) + call salloc (cmd, SZ_FNAME, TY_CHAR) + + # Input cursor is first continuum point now get second continuum point. + call printf ("k again:") + if (clgcur ("cursor", wx2, wy2, wc, key, Memc[cmd], SZ_FNAME) == EOF) { + call sfree (sp) + return + } + + # Set pixel indices and determine number of points to fit. + call fixx (sh, wx1, wx2, wy1, wy2, i1, j) + npts = j - i1 + 1 + if (npts < 3) { + call eprintf ("At least 3 points are required\n") + call sfree (sp) + return + } + + # Allocate space for the points to be fit. + call salloc (x, npts, TY_REAL) + call salloc (y, npts, TY_REAL) + call salloc (s, npts, TY_REAL) + call salloc (z, npts, TY_REAL) + + # Scale the data. + mc_n = clgeti ("nerrsample") + sigma0 = clgetr ("sigma0") + invgain = clgetr ("invgain") + if (IS_INDEF(sigma0) || IS_INDEF(invgain) || sigma0<0. || + invgain<0. || (sigma0 == 0. && invgain == 0.)) { + sigma0 = INDEF + invgain = INDEF + } + scale = 0. + do i = 1, npts { + Memr[x+i-1] = wcs[i1+i-1] + Memr[y+i-1] = pix[i1+i-1] + if (Memr[y+i-1] <= 0.) + if (!IS_INDEF(invgain) && invgain != 0.) { + sigma0 = INDEF + invgain = INDEF + call eprintf ( + "WARNING: Cannot compute errors with non-zero gain") + call eprintf ( + " and negative pixel values.\n") + } + scale = max (scale, abs (Memr[y+i-1])) + } + if (IS_INDEF(sigma0)) { + call amovkr (1., Memr[s], npts) + sscale = 1. + } else { + do i = 1, npts + Memr[s+i-1] = sqrt (sigma0 ** 2 + invgain * Memr[y+i-1]) + sscale = asumr (Memr[s], npts) / npts + } + call adivkr (Memr[y], scale, Memr[y], npts) + call adivkr (Memr[s], sscale, Memr[s], npts) + + # Allocate memory. + nlines = 1 + if (ng == 0) { + call malloc (xg, nlines, TY_REAL) + call malloc (yg, nlines, TY_REAL) + call malloc (sg, nlines, TY_REAL) + call malloc (lg, nlines, TY_REAL) + call malloc (pg, nlines, TY_INT) + } else if (ng != nlines) { + call realloc (xg, nlines, TY_REAL) + call realloc (yg, nlines, TY_REAL) + call realloc (sg, nlines, TY_REAL) + call realloc (lg, nlines, TY_REAL) + call realloc (pg, nlines, TY_INT) + } + ng = nlines + + # Do fit. + fit[1] = 1 + fit[2] = 2 + fit[3] = 2 + fit[4] = 2 + fit[5] = 2 + + # Setup initial estimates. + slope = (wy2-wy1) / (wx2-wx1) / scale + wyc = wy1 / scale - slope * wx1 + wx = 0 + do i = 0, npts-1 { + w = Memr[x+i] + wy = Memr[y+i] - wyc - slope * w + if (abs (wy) > wx) { + wx = abs (wy) + j = i + Memr[xg] = w + Memr[yg] = wy + } + } + + if (j > 0 && j < npts-1) { + w = Memr[x+j-1] + wy = min (0.99, max (0.01, abs (Memr[y+j-1] - wyc - slope*w) / wx)) + gfwhm = 2.355 * sqrt (-0.5 * (w-Memr[xg])**2 / log (wy)) + w = Memr[x+j+1] + wy = min (0.99, max (0.01, abs (Memr[y+j+1] - wyc - slope*w) / wx)) + gfwhm = (gfwhm + 2.355 * sqrt (-0.5*(w-Memr[xg])**2/log (wy))) / 2 + } else + gfwhm = 0.3 * abs (Memr[x+npts-1] - Memr[x]) + + switch (key) { + case 'l': + Memr[sg] = 0. + Memr[lg] = gfwhm + Memi[pg] = 2 + case 'v': + Memr[sg] = 0.5 * gfwhm + Memr[lg] = 0.5 * gfwhm + Memi[pg] = 3 + default: + Memr[sg] = gfwhm + Memr[lg] = 0. + Memi[pg] = 1 + } + + nsub = NSUB + dw = (wcs[n] - wcs[1]) / (n - 1) + iferr (call dofit (fit, Memr[x], Memr[y], Memr[s], npts, dw, nsub, + wyc, slope, Memr[xg], Memr[yg], Memr[sg], Memr[lg], Memi[pg], + ng, chisq)) { + fitit = false + goto done_ + } + + # Compute Monte-Carlo errors. + if (mc_n > 9 && !IS_INDEF(sigma0)) { + mc_p = nint (mc_n * MC_P / 100.) + mc_sig = nint (mc_n * MC_SIG / 100.) + + call salloc (ym, npts, TY_REAL) + call salloc (xg1, ng, TY_REAL) + call salloc (yg1, ng, TY_REAL) + call salloc (sg1, ng, TY_REAL) + call salloc (lg1, ng, TY_REAL) + call salloc (conte, mc_n*ng, TY_REAL) + call salloc (xge, mc_n*ng, TY_REAL) + call salloc (yge, mc_n*ng, TY_REAL) + call salloc (sge, mc_n*ng, TY_REAL) + call salloc (lge, mc_n*ng, TY_REAL) + call salloc (fluxe, mc_n*ng, TY_REAL) + call salloc (eqwe, mc_n*ng, TY_REAL) + do i = 1, npts { + w = Memr[x+i-1] + Memr[ym+i-1] = model (w, dw, nsub, Memr[xg], Memr[yg], + Memr[sg], Memr[lg], Memi[pg], ng) + wyc + slope * w + } + seed = 1 + do i = 0, mc_n-1 { + if (i > 0 && mod (i, mc_p) == 0) { + call printf ("%2d ") + call pargi (100 * i / mc_n) + call flush (STDOUT) + } + do j = 1, npts + Memr[y+j-1] = Memr[ym+j-1] + + sscale / scale * Memr[s+j-1] * gasdev (seed) + wyc1 = wyc + slope1 = slope + call amovr (Memr[xg], Memr[xg1], ng) + call amovr (Memr[yg], Memr[yg1], ng) + call amovr (Memr[sg], Memr[sg1], ng) + call amovr (Memr[lg], Memr[lg1], ng) + call dorefit (fit, Memr[x], Memr[y], Memr[s], npts, + dw, nsub, wyc1, slope1, + Memr[xg1], Memr[yg1], Memr[sg1], Memr[lg1], Memi[pg], ng, + chisq) + + do j = 0, ng-1 { + cont = wyc + slope * Memr[xg+j] + cont1 = wyc1 + slope1 * Memr[xg+j] + switch (Memi[pg+j]) { + case 1: + flux = 1.064467 * Memr[yg+j] * Memr[sg+j] + flux1 = 1.064467 * Memr[yg1+j] * Memr[sg1+j] + case 2: + flux = 1.570795 * Memr[yg+j] * Memr[lg+j] + flux1 = 1.570795 * Memr[yg1+j] * Memr[lg1+j] + case 3: + call voigt (0., 0.832555*Memr[lg+j]/Memr[sg+j], v, u) + flux = 1.064467 * Memr[yg+j] * Memr[sg+j] / v + call voigt (0., 0.832555*Memr[lg1+j]/Memr[sg1+j], v, u) + flux1 = 1.064467 * Memr[yg1+j] * Memr[sg1+j] / v + } + if (cont > 0. && cont1 > 0.) { + eqw = -flux / cont + eqw1 = -flux1 / cont1 + } else { + eqw = 0. + eqw1 = 0. + } + Memr[conte+j*mc_n+i] = abs (cont1 - cont) + Memr[xge+j*mc_n+i] = abs (Memr[xg1+j] - Memr[xg+j]) + Memr[yge+j*mc_n+i] = abs (Memr[yg1+j] - Memr[yg+j]) + Memr[sge+j*mc_n+i] = abs (Memr[sg1+j] - Memr[sg+j]) + Memr[lge+j*mc_n+i] = abs (Memr[lg1+j] - Memr[lg+j]) + Memr[fluxe+j*mc_n+i] = abs (flux1 - flux) + Memr[eqwe+j*mc_n+i] = abs (eqw1 - eqw) + } + } + do j = 0, ng-1 { + call asrtr (Memr[conte+j*mc_n], Memr[conte+j*mc_n], mc_n) + call asrtr (Memr[xge+j*mc_n], Memr[xge+j*mc_n], mc_n) + call asrtr (Memr[yge+j*mc_n], Memr[yge+j*mc_n], mc_n) + call asrtr (Memr[sge+j*mc_n], Memr[sge+j*mc_n], mc_n) + call asrtr (Memr[lge+j*mc_n], Memr[lge+j*mc_n], mc_n) + call asrtr (Memr[fluxe+j*mc_n], Memr[fluxe+j*mc_n], mc_n) + call asrtr (Memr[eqwe+j*mc_n], Memr[eqwe+j*mc_n], mc_n) + } + call amulkr (Memr[conte], scale, Memr[conte], mc_n*ng) + call amulkr (Memr[yge], scale, Memr[yge], mc_n*ng) + call amulkr (Memr[fluxe], scale, Memr[fluxe], mc_n*ng) + } + + call amulkr (Memr[yg], scale, Memr[yg], ng) + wyc = (wyc + slope * wx1) * scale + slope = slope * scale + + # Compute model spectrum with continuum and plot. + fitit = true + do i = 1, npts { + w = wcs[i1+i-1] + Memr[z+i-1] = model (w, dw, nsub, Memr[xg], Memr[yg], + Memr[sg], Memr[lg], Memi[pg], ng) + wyc + slope * (w - wx1) + } + + call gseti (gfd, G_PLTYPE, 2) + call gseti (gfd, G_PLCOLOR, 2) + call gpline (gfd, wcs[i1], Memr[z], npts) + call gseti (gfd, G_PLTYPE, 3) + call gseti (gfd, G_PLCOLOR, 3) + call gline (gfd, wx1, wyc, wx2, wyc + slope * (wx2 - wx1)) + call gseti (gfd, G_PLTYPE, 1) + call gseti (gfd, G_PLCOLOR, 1) + call gflush (gfd) + +done_ + # Log computed values + if (fitit) { + do i = 1, nlines { + w = Memr[xg+i-1] + cont = wyc + slope * (w - wx1) + peak = Memr[yg+i-1] + gfwhm = Memr[sg+i-1] + lfwhm = Memr[lg+i-1] + switch (Memi[pg+i-1]) { + case 1: + flux = 1.064467 * peak * gfwhm + if (cont > 0.) + eqw = -flux / cont + else + eqw = INDEF + call printf ( + "\n%d: center = %8.6g, flux = %8.4g, eqw = %6.4g, gfwhm = %6.4g") + call pargi (i) + call pargr (w) + call pargr (flux) + call pargr (eqw) + call pargr (gfwhm) + case 2: + flux = 1.570795 * peak * lfwhm + if (cont > 0.) + eqw = -flux / cont + else + eqw = INDEF + call printf ( + "\n%d: center = %8.6g, flux = %8.4g, eqw = %6.4g, lfwhm = %6.4g") + call pargi (i) + call pargr (w) + call pargr (flux) + call pargr (eqw) + call pargr (lfwhm) + case 3: + call voigt (0., 0.832555*lfwhm/gfwhm, v, u) + flux = 1.064467 * peak * gfwhm / v + if (cont > 0.) + eqw = -flux / cont + else + eqw = INDEF + call printf ( + "\n%d: center = %8.6g, eqw = %6.4g, gfwhm = %6.4g, lfwhm = %6.4g") + call pargi (i) + call pargr (w) + call pargr (eqw) + call pargr (gfwhm) + call pargr (lfwhm) + } + if (fd1 != NULL) { + call fprintf (fd1, + " %9.7g %9.7g %9.6g %9.4g %9.6g %9.4g %9.4g\n") + call pargr (w) + call pargr (cont) + call pargr (flux) + call pargr (eqw) + call pargr (peak) + call pargr (gfwhm) + call pargr (lfwhm) + } + if (fd2 != NULL) { + call fprintf (fd2, + " %9.7g %9.7g %9.6g %9.4g %9.6g %9.4g %9.4g\n") + call pargr (w) + call pargr (cont) + call pargr (flux) + call pargr (eqw) + call pargr (peak) + call pargr (gfwhm) + call pargr (lfwhm) + } + if (mc_n > 9 && !IS_INDEF(sigma0)) { + if (fd1 != NULL) { + call fprintf (fd1, + " (%7.5g) (%7w) (%7.4g) (%7.4g) (%7.4g) (%7.4g) (%7.4g)\n") + call pargr (Memr[xge+(i-1)*mc_n+mc_sig]) + call pargr (Memr[fluxe+(i-1)*mc_n+mc_sig]) + call pargr (Memr[eqwe+(i-1)*mc_n+mc_sig]) + call pargr (Memr[yge+(i-1)*mc_n+mc_sig]) + call pargr (Memr[sge+(i-1)*mc_n+mc_sig]) + call pargr (Memr[lge+(i-1)*mc_n+mc_sig]) + } + if (fd2 != NULL) { + call fprintf (fd2, + " (%7.5g) (%7w) (%7.4g) (%7.4g) (%7.4g) (%7.4g) (%7.4g)\n") + call pargr (Memr[xge+(i-1)*mc_n+mc_sig]) + call pargr (Memr[fluxe+(i-1)*mc_n+mc_sig]) + call pargr (Memr[eqwe+(i-1)*mc_n+mc_sig]) + call pargr (Memr[yge+(i-1)*mc_n+mc_sig]) + call pargr (Memr[sge+(i-1)*mc_n+mc_sig]) + call pargr (Memr[lge+(i-1)*mc_n+mc_sig]) + } + } + } + } else { + call mfree (xg, TY_REAL) + call mfree (yg, TY_REAL) + call mfree (sg, TY_REAL) + call mfree (lg, TY_REAL) + call mfree (pg, TY_INT) + ng = 0 + } + + call sfree (sp) +end |