diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /pkg/images/imfit/src/imsurfit.x | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/images/imfit/src/imsurfit.x')
-rw-r--r-- | pkg/images/imfit/src/imsurfit.x | 1172 |
1 files changed, 1172 insertions, 0 deletions
diff --git a/pkg/images/imfit/src/imsurfit.x b/pkg/images/imfit/src/imsurfit.x new file mode 100644 index 00000000..9f655f52 --- /dev/null +++ b/pkg/images/imfit/src/imsurfit.x @@ -0,0 +1,1172 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <imhdr.h> +include <math/surfit.h> +include "imsurfit.h" + +# IMSURFIT -- Procedure to fit a surface to a single image including +# optional pixel rejection. + +procedure imsurfit (imin, imout, imfit, gl) + +pointer imin # pointer to the input image +pointer imout # pointer to the output image +pointer imfit # pointer to the imsurfit parameters +pointer gl # pointer to the good regions list + +pointer sf, rl +errchk isfree, prl_free +errchk all_pixels, good_pixels, good_median, all_medians, do_reject +errchk set_outimage + +begin + sf = NULL + rl = NULL + + # Accumulate and solve the surface. + if (gl == NULL) { + if (MEDIAN(imfit) == NO) + call all_pixels (imin, imfit, sf) + else + call all_medians (imin, imfit, sf) + } else { + if (MEDIAN(imfit) == NO) + call good_pixels (imin, imfit, gl, sf) + else + call good_medians (imin, imfit, gl, sf) + } + + # Perform the reject cycle. + if (REJECT(imfit) == YES || TYPE_OUTPUT(imfit) == CLEAN) + call do_reject (imin, imfit, gl, sf, rl) + + # Evaluate surface for appropriate output type. + call set_outimage (imin, imout, imfit, sf, rl) + + # Cleanup. + call prl_free (rl) + call isfree (sf) + + rl = NULL + sf = NULL +end + + +# ALL_PIXELS -- Accumulate surface when there are no bad regions +# and no median processing. + +procedure all_pixels (im, imfit, sf) + +pointer im # pointer to the input image +pointer imfit # pointer to the imsurfit structure +pointer sf # pointer to the surface descriptor + +int i, lp, ncols, nlines, ier +long v[IM_MAXDIM] +pointer sp, cols, lines, wgt, lbuf +int imgnlr() +errchk smark, salloc, sfree, imgnlr +errchk isinit, islfit, islrefit, issolve + +begin + ncols = IM_LEN(im, 1) + nlines = IM_LEN(im,2) + + # Initialize the surface fit. + call isinit (sf, SURFACE_TYPE(imfit), XORDER(imfit), YORDER(imfit), + CROSS_TERMS(imfit), ncols, nlines) + + # Allocate working space for fitting. + call smark (sp) + call salloc (cols, ncols, TY_INT) + call salloc (lines, nlines, TY_INT) + call salloc (wgt, ncols, TY_REAL) + + # Initialize the x and weight buffers. + do i = 1, ncols + Memi[cols - 1 + i] = i + call amovkr (1.0, Memr[wgt], ncols) + + # Loop over image lines. + lp = 0 + call amovkl (long (1), v, IM_MAXDIM) + do i = 1, nlines { + + # Read in the image line. + if (imgnlr (im, lbuf, v) == EOF) + call error (0, "Error reading image") + + # Fit each image line. + if (i == 1) + call islfit (sf, Memi[cols], i, Memr[lbuf], Memr[wgt], + ncols, SF_USER, ier) + else + call islrefit (sf, Memi[cols], i, Memr[lbuf], Memr[wgt]) + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call eprintf ("Warning: Too few columns to fit line: %d\n") + call pargi (i) + case SINGULAR: + call eprintf ("Warning: Solution singular for line: %d\n") + call pargi (i) + Memi[lines + lp] = i + lp = lp + 1 + default: + Memi[lines + lp] = i + lp = lp + 1 + } + + } + + # Solve the surface. + call issolve (sf, Memi[lines], lp, ier) + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call error (0, "ALL_PIXELS: Cannot fit surface.") + case SINGULAR: + call eprintf ("Warning: Solution singular for surface.\n") + default: + # everything OK + } + + # Free space. + call sfree (sp) +end + + +# GOOD_PIXELS -- Get surface when good regions are defined and median +# processing is off. + +procedure good_pixels (im, imfit, gl, sf) + +pointer im # input image +pointer imfit # pointer to imsurfit header structure +pointer gl # pointer to good region list +pointer sf # pointer to the surface descriptor + +int lp, lineno, prevlineno, ncols, nlines, npts, nranges, ier, ijunk +int max_nranges +pointer sp, colsfit, lines, buf, fbuf, wgt, ranges +int prl_nextlineno(), prl_eqlines(), prl_get_ranges(), is_expand_ranges() +int is_choose_rangesr() +pointer imgl2r() + +errchk smark, salloc, sfree, imgl2r +errchk isinit, islfit, islrefit, issolve +errchk prl_nextlineno, prl_eqlines, prl_get_ranges +errchk is_choose_rangesr + +begin + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + max_nranges = ncols + + # Initialize the surface fit. + call isinit (sf, SURFACE_TYPE(imfit), XORDER(imfit), YORDER(imfit), + CROSS_TERMS(imfit), ncols, nlines) + + # Allocate temporary space for fitting. + call smark (sp) + call salloc (colsfit, ncols, TY_INT) + call salloc (lines, nlines, TY_INT) + call salloc (fbuf, ncols, TY_REAL) + call salloc (wgt, ncols, TY_REAL) + call salloc (ranges, 3 * max_nranges + 1, TY_INT) + call amovkr (1., Memr[wgt], ncols) + + # Intialize counters and pointers. + lp = 0 + lineno = 0 + prevlineno = 0 + + # Loop over those lines to be fit. + while (prl_nextlineno (gl, lineno) != EOF) { + + # Read in the image line. + buf = imgl2r (im, lineno) + if (buf == EOF) + call error (0, "GOOD_PIXELS: Error reading image.") + + # Get the ranges for that image line. + nranges = prl_get_ranges (gl, lineno, Memi[ranges], max_nranges) + if (nranges == 0) + next + + # If ranges are not equal to previous line fit else refit. + if (lp == 0 || prl_eqlines (gl, lineno, prevlineno) == NO) { + npts = is_expand_ranges (Memi[ranges], Memi[colsfit], ncols) + ijunk = is_choose_rangesr (Memi[colsfit], Memr[buf], Memr[fbuf], + npts, 1, ncols) + call islfit (sf, Memi[colsfit], lineno, Memr[fbuf], Memr[wgt], + npts, SF_USER, ier) + } else { + ijunk = is_choose_rangesr (Memi[colsfit], Memr[buf], Memr[fbuf], + npts, 1, ncols) + call islrefit (sf, Memi[colsfit], lineno, Memr[fbuf], Memr[wgt]) + } + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call eprintf ("Warning: Too few columns to fit line: %d\n") + call pargi (lineno) + case SINGULAR: + call eprintf ("Warning: Solution singular for line: %d\n") + call pargi (lineno) + Memi[lines+lp] = lineno + lp = lp + 1 + default: + Memi[lines+lp] = lineno + lp = lp + 1 + } + + prevlineno = lineno + } + + # Solve the surface. + call issolve (sf, Memi[lines], lp, ier) + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call error (0, "GOOD_PIXELS: Cannot fit surface.") + case SINGULAR: + call eprintf ("Warning: Solution singular for surface.\n") + default: + # everything OK + } + + # Free space. + call sfree (sp) +end + + +# ALL_MEDIANS -- Get surface when median processor on and all +# pixels good. + +procedure all_medians (im, imfit, sf) + +pointer im # input image +pointer imfit # pointer to the imsurfit header structure +pointer sf # pointer to the surface descriptor + +int i, lp, cp, op, lineno, x1, x2, y1, y2, ier +int nimcols, nimlines, ncols, nlines, npts +pointer sp, cols, lines, wgt, z, med, sbuf, lbuf, buf + +pointer imgs2r() +real asokr() +errchk salloc, sfree, smark +errchk isinit, islfit, islrefit, issolve + +begin + # Determine the number of lines and columns for a median processed + # image. + nimcols = IM_LEN(im,1) + if (mod (int (IM_LEN(im,1)), XMEDIAN(imfit)) != 0) + ncols = IM_LEN(im,1) / XMEDIAN(imfit) + 1 + else + ncols = IM_LEN(im,1) / XMEDIAN(imfit) + nimlines = IM_LEN(im,2) + if (mod (int (IM_LEN(im,2)), YMEDIAN(imfit)) != 0) + nlines = IM_LEN(im,2) / YMEDIAN(imfit) + 1 + else + nlines = IM_LEN(im,2) / YMEDIAN(imfit) + + # Initialize the surface fitting. + call isinit (sf, SURFACE_TYPE(imfit), XORDER(imfit), YORDER(imfit), + CROSS_TERMS(imfit), ncols, nlines) + + # Allocate workin memory. + call smark (sp) + call salloc (cols, ncols, TY_INT) + call salloc (wgt, ncols, TY_REAL) + call salloc (lines, nlines, TY_INT) + call salloc (z, ncols, TY_REAL) + call salloc (med, XMEDIAN(imfit) * YMEDIAN(imfit), TY_REAL) + + # Intialize the x and weight arrays. + do i = 1, ncols + Memi[cols - 1 + i] = i + call amovkr (1.0, Memr[wgt], ncols) + + # Loop over image sections. + lp = 0 + lineno = 1 + for (y1 = 1; y1 <= nimlines; y1 = y1 + YMEDIAN(imfit)) { + + # Get image section. + y2 = min (y1 + YMEDIAN(imfit) - 1, nimlines) + sbuf = imgs2r (im, 1, nimcols, y1, y2) + if (sbuf == EOF) + call error (0, "Error reading image section.") + + # Loop over median boxes. + cp = 0 + for (x1 = 1; x1 <= nimcols; x1 = x1 + XMEDIAN(imfit)) { + + x2 = min (x1 + XMEDIAN(imfit) - 1, nimcols) + npts = x2 - x1 + 1 + lbuf = sbuf - 1 + x1 + + # Loop over lines in the median box. + op = 0 + buf = lbuf + for (i = 1; i <= y2 - y1 + 1; i = i + 1) { + call amovr (Memr[buf], Memr[med+op], npts) + op = op + npts + buf = buf + nimcols + } + + # Calculate the median. + Memr[z+cp] = asokr (Memr[med], op, (op + 1) / 2) + cp = cp + 1 + + } + + # Fit each image "line". + if (y1 == 1) + call islfit (sf, Memi[cols], lineno, Memr[z], Memr[wgt], + ncols, SF_USER, ier) + else + call islrefit (sf, Memi[cols], lineno, Memr[z], Memr[wgt]) + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call eprintf ("Warning: Too few columns to fit line: %d\n") + call pargi (lineno) + case SINGULAR: + call eprintf ("Warning: Solution singular for line: %d\n") + call pargi (lineno) + Memi[lines + lp] = lineno + lp = lp + 1 + default: + Memi[lines + lp] = lineno + lp = lp + 1 + } + + lineno = lineno + 1 + } + + # Solve th surface. + call issolve (sf, Memi[lines], lp, ier) + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call error (0, "ALL_MEDIANS: Cannot fit surface.") + case SINGULAR: + call eprintf ("Warning: Solution singular for surface.\n") + default: + # everything OK + } + + # Free space + call sfree (sp) +end + + +# GOOD_MEDIANS -- Procedure to fetch medians when the good regions +# list is defined. + +procedure good_medians (im, imfit, gl, sf) + +pointer im # input image +pointer imfit # pointer to surface descriptor structure +pointer gl # pointer to good regions list +pointer sf # pointer the surface descriptor + +int i, cp, lp, x1, x2, y1, y2, ier, ntemp +int nimcols, nimlines, ncols, nlines, nranges, nbox, nxpts +int lineno, current_line, lines_per_box, max_nranges +pointer sp, colsfit, cols, lines, wgt, npts, lbuf, med, mbuf, z, ranges + +int prl_get_ranges(), prl_nextlineno(), is_expand_ranges() +int is_choose_rangesr() +pointer imgl2r() +real asokr() +errchk smark, salloc, sfree, imgl2r +errchk isinit, islfit, issolve +errchk prl_get_ranges, prl_nextlineno, is_choose_rangesr() + +begin + # Determine the number of lines and columns for a median processed + # image. + nimcols = IM_LEN(im,1) + if (mod (int (IM_LEN(im,1)), XMEDIAN(imfit)) != 0) + ncols = IM_LEN(im,1) / XMEDIAN(imfit) + 1 + else + ncols = IM_LEN(im,1) / XMEDIAN(imfit) + nimlines = IM_LEN(im,2) + if (mod (int (IM_LEN(im,2)), YMEDIAN(imfit)) != 0) + nlines = IM_LEN(im,2) / YMEDIAN(imfit) + 1 + else + nlines = IM_LEN(im,2) / YMEDIAN(imfit) + nbox = XMEDIAN(imfit) * YMEDIAN(imfit) + max_nranges = nimcols + + # Initialize the surface fitting. + call isinit (sf, SURFACE_TYPE(imfit), XORDER(imfit), YORDER(imfit), + CROSS_TERMS(imfit), ncols, nlines) + + # Allocate working memory. + call smark (sp) + call salloc (colsfit, nimcols, TY_INT) + call salloc (cols, ncols, TY_INT) + call salloc (npts, ncols, TY_INT) + call salloc (lines, nlines, TY_INT) + call salloc (wgt, ncols, TY_REAL) + call salloc (med, nbox * ncols, TY_REAL) + call salloc (z, ncols, TY_REAL) + call salloc (ranges, 3 * max_nranges + 1, TY_INT) + call amovkr (1., Memr[wgt], ncols) + + # Loop over median boxes in y. + lp = 0 + lineno = 0 + for (y1 = 1; y1 <= nimlines; y1 = y1 + YMEDIAN(imfit)) { + + lineno = lineno + 1 + current_line = y1 - 1 + y2 = min (y1 + YMEDIAN(imfit) - 1, nimlines) + + # If lines not in range, next image section. + lines_per_box = 0 + while (prl_nextlineno (gl, current_line) != EOF) { + if (current_line > y2) + break + lines_per_box = lines_per_box + 1 + } + if (lines_per_box < (YMEDIAN(imfit) * (MEDIAN_PERCENT(imfit)/100.))) + next + + # Loop over the image lines. + call aclri (Memi[npts], ncols) + do i = y1, y2 { + + # Get image line, and check the good regions list. + lbuf = imgl2r (im, i) + nranges = prl_get_ranges (gl, i, Memi[ranges], max_nranges) + if (nranges == 0) + next + nxpts = is_expand_ranges (Memi[ranges], Memi[colsfit], nimcols) + + # Loop over the median boxes in x. + cp= 0 + mbuf = med + for (x1 = 1; x1 <= nimcols; x1 = x1 + XMEDIAN(imfit)) { + x2 = min (x1 + XMEDIAN(imfit) - 1, nimcols) + ntemp = is_choose_rangesr (Memi[colsfit], Memr[lbuf], + Memr[mbuf+Memi[npts+cp]], nxpts, x1, x2) + Memi[npts+cp] = Memi[npts+cp] + ntemp + mbuf = mbuf + nbox + cp = cp + 1 + } + } + + # Calculate the medians. + nxpts = 0 + mbuf = med + do i = 1, ncols { + if (Memi[npts+i-1] > ((MEDIAN_PERCENT(imfit) / 100.) * nbox)) { + Memr[z+nxpts] = asokr (Memr[mbuf], Memi[npts+i-1], + (Memi[npts+i-1] + 1) / 2) + Memi[cols+nxpts] = i + nxpts = nxpts + 1 + } + mbuf = mbuf + nbox + } + + # Fit the line. + call islfit (sf, Memi[cols], lineno, Memr[z], Memr[wgt], nxpts, + SF_USER, ier) + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call eprintf ("Warning: Too few columns to fit line: %d\n") + call pargi (lineno) + case SINGULAR: + call eprintf ("Warning: Solution singular for line: %d\n") + call pargi (lineno) + Memi[lines+lp] = lineno + lp = lp + 1 + default: + Memi[lines+lp] = lineno + lp = lp + 1 + } + } + + # Solve the surface. + call issolve (sf, Memi[lines], lp, ier) + + # Handle fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call error (0, "GOOD_MEDIANS: Cannot fit surface.") + case SINGULAR: + call eprintf ("Warning: Solution singular for surface.") + default: + # everyting OK + } + + # Free space. + call sfree (sp) +end + + +# SET_OUTIMAGE -- Procedure to write an output image of the desired type. + +procedure set_outimage (imin, imout, imfit, sf, rl) + +pointer imin # input image +pointer imout # output image +pointer imfit # pointer to the imsurfut header structure +pointer sf # pointer to the surface descriptor +pointer rl # pointer to the rejected pixel list regions list + +int i, k, ncols, nlines, max_nranges +long u[IM_MAXDIM], v[IM_MAXDIM] +real b1x, b2x, b1y, b2y +pointer sp, x, y, inbuf, outbuf, ranges + +int impnlr(), imgnlr() +real ims_divzero() +extern ims_divzero +errchk malloc, mfree, imgnlr, impnlr + +begin + ncols = IM_LEN(imin,1) + nlines = IM_LEN(imin,2) + max_nranges = ncols + + # Calculate transformation constants from real coordinates to + # median coordinates if median processing specified. + if (MEDIAN(imfit) == YES) { + b1x = (1. + XMEDIAN(imfit)) / (2. * XMEDIAN(imfit)) + b2x = (2. * ncols + XMEDIAN(imfit) - 1.) / (2. * XMEDIAN(imfit)) + b1y = (1. + YMEDIAN(imfit)) / (2. * YMEDIAN(imfit)) + b2y = (2. * nlines + YMEDIAN(imfit) - 1.) / (2. * YMEDIAN(imfit)) + } + + # Allocate space for x coordinates, initialize to image coordinates + # and transform to median coordinates. + call smark (sp) + call salloc (x, ncols, TY_REAL) + call salloc (y, ncols, TY_REAL) + call salloc (ranges, 3 * max_nranges + 1, TY_INT) + + # Intialize the x array. + do i = 1, ncols + Memr[x - 1 + i] = i + if (MEDIAN(imfit) == YES) + call amapr (Memr[x], Memr[x], ncols, 1., real (ncols), b1x, b2x) + + # loop over the images lines + call amovkl (long (1), v, IM_MAXDIM) + call amovkl (long (1), u, IM_MAXDIM) + do i = 1, nlines { + + # Get input and output image buffers. + if (TYPE_OUTPUT(imfit) != FIT) { + if (imgnlr (imin, inbuf, v) == EOF) + call error (0, "Error reading input image.") + } + if (impnlr (imout, outbuf, u) == EOF) + call error (0, "Error writing output image.") + + # Intialize y coordinates to image coordinates, and + # transform to median coordinates. + if (MEDIAN(imfit) == YES) { + Memr[y] = real (i) + call amapr (Memr[y], Memr[y], 1, 1., real (nlines), + b1y, b2y) + call amovkr (Memr[y], Memr[y+1], (ncols-1)) + } else + call amovkr (real (i), Memr[y], ncols) + + # Write output image. + switch (TYPE_OUTPUT(imfit)) { + case FIT: + call isvector (sf, Memr[x], Memr[y], Memr[outbuf], ncols) + case CLEAN: + call clean_line (Memr[x], Memr[y], Memr[inbuf], ncols, nlines, + rl, sf, i, NGROW(imfit)) + call amovr (Memr[inbuf], Memr[outbuf], ncols) + case RESID: + call isvector (sf, Memr[x], Memr[y], Memr[outbuf], ncols) + call asubr (Memr[inbuf], Memr[outbuf], Memr[outbuf], ncols) + case RESP: + call isvector (sf, Memr[x], Memr[y], Memr[outbuf], ncols) + if (IS_INDEF(DIV_MIN(imfit))) { + iferr (call adivr (Memr[inbuf], Memr[outbuf], Memr[outbuf], + ncols)) + call advzr (Memr[inbuf], Memr[outbuf], Memr[outbuf], + ncols, ims_divzero) + } else { + do k = 1, ncols { + if (Memr[outbuf-1+k] < DIV_MIN(imfit)) + Memr[outbuf-1+k] = 1. + else + Memr[outbuf-1+k] = Memr[inbuf-1+k] / + Memr[outbuf-1+k] + } + } + default: + call error (0, "SET_OUTIMAGE: Unknown output type.") + } + } + + # Free space + call sfree (sp) +end + + +# CLEAN_LINE -- Procedure to set weights of rejected points to zero + +procedure clean_line (x, y, z, ncols, nlines, rl, sf, line, ngrow) + +real x[ARB] # array of weights set to 1 +real y # y value of line +real z[ARB] # line of data +int ncols # number of image columns +int nlines # number of image lines +pointer rl # pointer to reject pixel list +pointer sf # surface fitting +int line # line number +int ngrow # radius for region growing + +int cp, j, k, nranges, dist, yreg_min, yreg_max, xreg_min, xreg_max +pointer sp, branges +real r2 +int prl_get_ranges(), is_next_number() +real iseval() + +begin + call smark (sp) + call salloc (branges, 3 * ncols + 1, TY_INT) + + r2 = ngrow ** 2 + yreg_min = max (1, line - ngrow) + yreg_max = min (nlines, line + ngrow) + + do j = yreg_min, yreg_max { + nranges = prl_get_ranges (rl, j, Memi[branges], ncols) + if (nranges == 0) + next + dist = int (sqrt (r2 - (j - line) ** 2)) + cp = 0 + while (is_next_number (Memi[branges], cp) != EOF) { + xreg_min = max (1, cp - dist) + xreg_max = min (ncols, cp + dist) + do k = xreg_min, xreg_max + z[k] = iseval (sf, x[k], y) + cp = xreg_max + } + } + + call sfree (sp) +end + + +# DO_REJECT -- Procedure to detect rejected pixels in an image. + +procedure do_reject (im, imfit, gl, sf, rl) + +pointer im # pointer to in put image +pointer imfit # pointer to image fitting structure +pointer gl # pointer to good regions list +pointer sf # pointer to surface descriptor +pointer rl # pointer to rejected pixel list + +int niter, nrejects +real sigma +int detect_rejects() +real get_sigma() +errchk prl_init, detect_rejects, get_sigma, refit_surface + +begin + # Initialize rejected pixel list. + call prl_init (rl, int(IM_LEN(im,1)), int(IM_LEN(im,2))) + + # Do an iterative rejection cycle on the image. + niter = 0 + repeat { + + # Get the sigma of the fit. + sigma = get_sigma (im, gl, sf, rl) + + # Detect rejected pixels. + nrejects = detect_rejects (im, imfit, gl, sf, rl, sigma) + + # If no rejected pixels quit, else refit surface. + if (nrejects == 0 || NITER(imfit) == 0) + break + call refit_surface (im, imfit, gl, sf, rl) + + niter = niter + 1 + + } until (niter == NITER(imfit)) +end + + +# REFIT_SURFACE -- Procedure tp refit the surface. + +procedure refit_surface (im, imfit, gl, sf, rl) + +pointer im # pointer to image +pointer imfit # pointer to surface fitting structure +pointer gl # pointer to good regions list +pointer sf # pointer to surface descriptor +pointer rl # pointer to rejected pixels list + +int i, ijunk, lp, ier, max_nranges +int ncols, nlines, npts, nfree, nrejects, nranges, ncoeff +pointer sp, cols, colsfit, lines, buf, fbuf, wgt, granges + +int prl_get_ranges(), grow_regions(), is_expand_ranges() +int is_choose_rangesr() +pointer imgl2r() +errchk smark, salloc, sfree, imgl2r +errchk iscoeff, islfit, issolve +errchk prl_get_ranges, grow_regions +errchk is_choose_rangesr + +begin + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + max_nranges = ncols + + # Allocate up temporary storage. + call smark (sp) + call salloc (cols, ncols, TY_INT) + call salloc (colsfit, ncols, TY_INT) + call salloc (lines, nlines, TY_INT) + call salloc (fbuf, ncols, TY_REAL) + call salloc (wgt, ncols, TY_REAL) + call salloc (granges, 3 * max_nranges + 1, TY_INT) + + # Initialize columns. + do i = 1, ncols + Memi[cols+i-1] = i + call amovi (Memi[cols], Memi[colsfit], ncols) + + # Get number of coefficients. + switch (SURFACE_TYPE(imfit)) { + case SF_LEGENDRE, SF_CHEBYSHEV: + ncoeff = XORDER(imfit) + case SF_SPLINE3: + ncoeff = XORDER(imfit) + 3 + case SF_SPLINE1: + ncoeff = XORDER(imfit) + 1 + } + + # Refit affected lines and solve for surface. + lp = 0 + do i = 1, nlines { + + # Determine whether image line is good. + if (gl != NULL) { + nranges = prl_get_ranges (gl, i, Memi[granges], max_nranges) + if (nranges == 0) + next + } + + # Define rejected points with region growing. + call amovkr (1., Memr[wgt], ncols) + nrejects = grow_regions (Memr[wgt], ncols, nlines, rl, i, + NGROW(imfit)) + + # Get number of data points. + if (gl == NULL) + npts = ncols + else + npts = is_expand_ranges (Memi[granges], Memi[colsfit], ncols) + nfree = npts - nrejects + + # If no rejected pixels skip to next line. + if (nrejects == 0) { + if (nfree >= ncoeff ) { + Memi[lines+lp] = i + lp = lp + 1 + } + next + } + + # Read in image line. + buf = imgl2r (im, i) + if (buf == EOF) + call error (0, "REFIT_SURFACE: Error reading image.") + + # Select the data. + if (gl == NULL) { + npts = ncols + if (nfree >= ncoeff) + call islfit (sf, Memi[colsfit], i, Memr[buf], Memr[wgt], + npts, SF_USER, ier) + else + ier = NO_DEG_FREEDOM + } else { + ijunk = is_choose_rangesr (Memi[colsfit], Memr[buf], + Memr[fbuf], npts, 1, ncols) + ijunk = is_choose_rangesr (Memi[colsfit], Memr[wgt], Memr[wgt], + npts, 1, ncols) + if (nfree >= ncoeff) + call islfit (sf, Memi[colsfit], i, Memr[fbuf], Memr[wgt], + npts, SF_USER, ier) + else + ier = NO_DEG_FREEDOM + } + + # Evaluate fitting errors. + switch (ier) { + case NO_DEG_FREEDOM: + call eprintf ("REFIT_SURFACE: Too few points to fit line: %d\n") + call pargi (i) + case SINGULAR: + call eprintf ("REFIT_SURFACE: Solution singular for line: %d\n") + call pargi (i) + Memi[lines+lp] = i + lp = lp + 1 + default: + Memi[lines+lp] = i + lp = lp + 1 + } + } + + # Resolve surface. + call issolve (sf, Memi[lines], lp, ier) + + # Evaluate fitting errors for surface. + switch (ier) { + case NO_DEG_FREEDOM: + call error (0, "REFIT_SURFACE: Too few points to fit surface\n") + case SINGULAR: + call eprintf ("REFIT_SURFACE: Solution singular for surface\n") + default: + # everything OK + } + + call sfree (sp) + +end + + +# GROW_REGIONS -- Procedure to set weights of rejected points to zero. + +int procedure grow_regions (wgt, ncols, nlines, rl, line, ngrow) + +real wgt[ARB] # array of weights set to 1 +int ncols # number of image columnspoints +int nlines # number of images lines +pointer rl # pointer to reject pixel list +int line # line number +int ngrow # radius for region growing + +int cp, j, k, nrejects, nranges, max_nranges +int dist, yreg_min, yreg_max, xreg_min, xreg_max +pointer sp, branges +real r2 +int prl_get_ranges(), is_next_number() +errchk smark, salloc, sfree +errchk prl_get_ranges, is_next_number + +begin + max_nranges = ncols + + call smark (sp) + call salloc (branges, 3 * max_nranges + 1, TY_INT) + + r2 = ngrow ** 2 + nrejects = 0 + yreg_min = max (1, line - ngrow) + yreg_max = min (nlines, line + ngrow) + + do j = yreg_min, yreg_max { + nranges = prl_get_ranges (rl, j, Memi[branges], max_nranges) + if (nranges == 0) + next + dist = int (sqrt (r2 - (j - line) ** 2)) + cp = 0 + while (is_next_number (Memi[branges], cp) != EOF) { + xreg_min = max (1, cp - dist) + xreg_max = min (ncols, cp + dist) + do k = xreg_min, xreg_max { + if (wgt[k] > 0.) { + wgt[k] = 0. + nrejects = nrejects + 1 + } + } + cp = xreg_max + } + } + + call sfree (sp) + return (nrejects) +end + + +# GET_SIGMA -- Procedure to calculate the sigma of the surface fit + +real procedure get_sigma (im, gl, sf, rl) + +pointer im # pointer to image +pointer gl # pointer to good pixel list +pointer sf # pointer to surface deascriptor +pointer rl # pointer to rejected pixel list + +int i, ijunk, cp, nranges, npts, ntpts, ncols, nlines, max_nranges +pointer sp, colsfit, x, xfit, y, zfit, buf, fbuf, wgt, granges, branges +real sum, sigma +int prl_get_ranges(), is_next_number(), is_expand_ranges() +int is_choose_rangesr() +pointer imgl2r() +real asumr(), awssqr() +errchk smark, salloc, sfree, imgl2r + +begin + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + max_nranges = ncols + + # Allocate working space. + call smark (sp) + call salloc (colsfit, ncols, TY_INT) + call salloc (x, ncols, TY_REAL) + call salloc (xfit, ncols, TY_REAL) + call salloc (y, ncols, TY_REAL) + call salloc (fbuf, ncols, TY_REAL) + call salloc (zfit, ncols, TY_REAL) + call salloc (wgt, ncols, TY_REAL) + call salloc (granges, 3 * max_nranges + 1, TY_INT) + call salloc (branges, 3 * max_nranges + 1, TY_INT) + + # Intialize the x array. + do i = 1, ncols + Memr[x+i-1] = i + call amovr (Memr[x], Memr[xfit], ncols) + + sum = 0. + sigma = 0. + ntpts = 0 + + # Loop over the image. + do i = 1, nlines { + + # Check that line is in range. + if (gl != NULL) { + nranges = prl_get_ranges (gl, i, Memi[granges], max_nranges) + if (nranges == 0) + next + npts = is_expand_ranges (Memi[granges], Memi[colsfit], ncols) + } + + # Read in image. + buf = imgl2r (im, i) + if (buf == EOF) + call error (0, "GET_SIGMA: Error reading image.") + + # Select appropriate data and fit. + call amovkr (real (i), Memr[y], ncols) + if (gl == NULL) { + npts = ncols + call isvector (sf, Memr[xfit], Memr[y], Memr[zfit], npts) + call asubr (Memr[buf], Memr[zfit], Memr[zfit], npts) + } else { + ijunk = is_choose_rangesr (Memi[colsfit], Memr[x], Memr[xfit], + npts, 1, ncols) + ijunk = is_choose_rangesr (Memi[colsfit], Memr[buf], Memr[fbuf], + npts, 1, ncols) + call isvector (sf, Memr[xfit], Memr[y], Memr[zfit], npts) + call asubr (Memr[fbuf], Memr[zfit], Memr[zfit], npts) + } + + # Get ranges of rejected pixels for the line and set weights. + call amovkr (1., Memr[wgt], ncols) + nranges = prl_get_ranges (rl, i, Memi[branges], max_nranges) + if (nranges > 0) { + cp = 0 + while (is_next_number (Memi[branges], cp) != EOF) + Memr[wgt+cp-1] = 0. + if (gl != NULL) + ijunk = is_choose_rangesr (Memi[colsfit], Memr[wgt], + Memr[wgt], npts, 1, ncols) + } + + # Calculate sigma. + sigma = sigma + awssqr (Memr[zfit], Memr[wgt], npts) + ntpts = ntpts + asumr (Memr[wgt], npts) + } + + call sfree (sp) + + return (sqrt (sigma / (ntpts - 1))) +end + + +# DETECT_REJECTS - Procedure to detect rejected pixels. + +int procedure detect_rejects (im, imfit, gl, sf, rl, sigma) + +pointer im # pointer to image +pointer imfit # pointer to surface fitting structure +pointer gl # pointer to good pixel list +pointer sf # pointer to surface descriptor +pointer rl # pointer to rejected pixel list +real sigma # standard deviation of fit + +int i, j, ijunk, cp, ncols, nlines, npts, nranges, nlrejects, ntrejects +int norejects, max_nranges +pointer sp, granges, branges, x, xfit, cols, colsfit, y, zfit, buf, fbuf +pointer wgt, list +real upper, lower + +int prl_get_ranges(), is_next_number(), is_make_ranges(), is_expand_ranges() +int is_choose_rangesr() +pointer imgl2r() + +begin + ncols = IM_LEN(im,1) + nlines = IM_LEN(im,2) + max_nranges = ncols + + # Allocate temporary space. + call smark (sp) + call salloc (x, ncols, TY_REAL) + call salloc (xfit, ncols, TY_REAL) + call salloc (cols, ncols, TY_INT) + call salloc (colsfit, ncols, TY_INT) + call salloc (y, ncols, TY_REAL) + call salloc (fbuf, ncols, TY_REAL) + call salloc (zfit, ncols, TY_REAL) + call salloc (wgt, ncols, TY_REAL) + call salloc (granges, 3 * max_nranges + 1, TY_INT) + call salloc (branges, 3 * max_nranges + 1, TY_INT) + call salloc (list, ncols, TY_INT) + + # Intialize x and column values. + do i = 1, ncols { + Memi[cols+i-1] = i + Memr[x+i-1] = i + } + call amovr (Memr[x], Memr[xfit], ncols) + call amovi (Memi[cols], Memi[colsfit], ncols) + + ntrejects = 0 + if (LOWER(imfit) <= 0.0) + lower = -MAX_REAL + else + lower = -sigma * LOWER(imfit) + if (UPPER(imfit) <= 0.0) + upper = MAX_REAL + else + upper = sigma * UPPER(imfit) + + # Loop over the image. + do i = 1, nlines { + + # Get ranges if appropriate. + if (gl != NULL) { + nranges = prl_get_ranges (gl, i, Memi[granges], max_nranges) + if (nranges == 0) + next + npts = is_expand_ranges (Memi[granges], Memi[colsfit], ncols) + } + + # Read in image. + buf = imgl2r (im, i) + if (buf == EOF) + call error (0, "GET_SIGMA: Error reading image.") + + # Select appropriate data and fit. + call amovkr (real (i), Memr[y], ncols) + if (gl == NULL) { + npts = ncols + call isvector (sf, Memr[xfit], Memr[y], Memr[zfit], npts) + call asubr (Memr[buf], Memr[zfit], Memr[zfit], npts) + } else { + ijunk = is_choose_rangesr (Memi[colsfit], Memr[x], Memr[xfit], + npts, 1, ncols) + ijunk = is_choose_rangesr (Memi[colsfit], Memr[buf], Memr[fbuf], + npts, 1, ncols) + call isvector (sf, Memr[xfit], Memr[y], Memr[zfit], npts) + call asubr (Memr[fbuf], Memr[zfit], Memr[zfit], npts) + } + + # Get ranges of rejected pixels for the line and set weights. + call amovkr (1., Memr[wgt], ncols) + nranges = prl_get_ranges (rl, i, Memi[branges], max_nranges) + norejects = 0 + if (nranges > 0) { + cp = 0 + while (is_next_number (Memi[branges], cp) != EOF) { + Memi[list+norejects] = cp + norejects = norejects + 1 + Memr[wgt+cp-1] = 0. + } + if (gl != NULL) + ijunk = is_choose_rangesr (Memi[colsfit], Memr[wgt], + Memr[wgt], npts, 1, ncols) + } + + # Detect deviant pixels. + nlrejects = 0 + do j = 1, npts { + if ((Memr[zfit+j-1] < lower || Memr[zfit+j-1] > upper) && + Memr[wgt+j-1] != 0.) { + Memi[list+norejects+nlrejects] = Memi[colsfit+j-1] + nlrejects = nlrejects + 1 + } + } + + # Add to rejected pixel list. + if (nlrejects > 0) { + call asrti (Memi[list], Memi[list], norejects + nlrejects) + nranges = is_make_ranges (Memi[list], norejects + nlrejects, + Memi[granges], max_nranges) + call prl_put_ranges (rl, i, i, Memi[granges]) + } + + ntrejects = ntrejects + nlrejects + } + + call sfree (sp) + return (ntrejects) +end + + +# AWSSQR -- Procedure to calculate the weighted sum of the squares + +real procedure awssqr (a, w, npts) + +real a[npts] # array of data +real w[npts] # array of points +int npts # number of data points + +int i +real sum + +begin + sum = 0. + do i = 1, npts + sum = sum + w[i] * a[i] ** 2 + + return (sum) +end + + +# IMS_DIVZER0 -- Return 1. on a divide by zero + +real procedure ims_divzero (x) + +real x + +begin + return (1.) +end |