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/lib/geofiti.x | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/images/lib/geofiti.x')
-rw-r--r-- | pkg/images/lib/geofiti.x | 2521 |
1 files changed, 2521 insertions, 0 deletions
diff --git a/pkg/images/lib/geofiti.x b/pkg/images/lib/geofiti.x new file mode 100644 index 00000000..9f11da2b --- /dev/null +++ b/pkg/images/lib/geofiti.x @@ -0,0 +1,2521 @@ +# Copyright(c) 1986 Assocation of Universities for Research in Astronomy Inc. + +include <mach.h> +include <math.h> +include <math/gsurfit.h> +include "geomap.h" + + + +# GEO_MINIT -- Initialize the fitting routines. + +procedure geo_minit (fit, projection, geometry, function, xxorder, xyorder, + xxterms, yxorder, yyorder, yxterms, maxiter, reject) + +pointer fit #I pointer to the fit structure +int projection #I the coordinate projection type +int geometry #I the fitting geometry +int function #I fitting function +int xxorder #I order of x fit in x +int xyorder #I order of x fit in y +int xxterms #I include cross terms in x fit +int yxorder #I order of y fit in x +int yyorder #I order of y fit in y +int yxterms #I include cross-terms in y fit +int maxiter #I the maximum number of rejection interations +double reject #I rejection threshold in sigma + +begin + # Allocate the space. + call malloc (fit, LEN_GEOMAP, TY_STRUCT) + + # Set function and order. + GM_PROJECTION(fit) = projection + GM_PROJSTR(fit) = EOS + GM_FIT(fit) = geometry + GM_FUNCTION(fit) = function + GM_XXORDER(fit) = xxorder + GM_XYORDER(fit) = xyorder + GM_XXTERMS(fit) = xxterms + GM_YXORDER(fit) = yxorder + GM_YYORDER(fit) = yyorder + GM_YXTERMS(fit) = yxterms + + # Set rejection parameters. + GM_XRMS(fit) = 0.0d0 + GM_YRMS(fit) = 0.0d0 + GM_MAXITER(fit) = maxiter + GM_REJECT(fit) = reject + GM_NREJECT(fit) = 0 + GM_REJ(fit) = NULL + + # Set origin parameters. + GM_XO(fit) = INDEFD + GM_YO(fit) = INDEFD + GM_XOREF(fit) = INDEFD + GM_YOREF(fit) = INDEFD +end + + +# GEO_FREE -- Release the fitting space. + +procedure geo_free (fit) + +pointer fit #I pointer to the fitting structure + +begin + if (GM_REJ(fit) != NULL) + call mfree (GM_REJ(fit), TY_INT) + call mfree (fit, TY_STRUCT) +end + + + + + + +# GEO_FIT -- Fit the surface in batch. + +procedure geo_fitr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, npts, + xerrmsg, yerrmsg, maxch) + +pointer fit #I pointer to fitting structure +pointer sx1, sy1 #U pointer to linear surface +pointer sx2, sy2 #U pointer to higher order correction +real xref[ARB] #I x reference array +real yref[ARB] #I y reference array +real xin[ARB] #I x array +real yin[ARB] #I y array +real wts[ARB] #I weight array +int npts #I the number of data points +char xerrmsg[ARB] #O the x fit error message +char yerrmsg[ARB] #O the y fit error message +int maxch #I maximum size of the error message + +pointer sp, xresidual, yresidual +errchk geo_fxyr(), geo_mrejectr(), geo_fthetar(), geo_fmagnifyr() +errchk geo_flinearr() + +begin + call smark (sp) + call salloc (xresidual, npts, TY_REAL) + call salloc (yresidual, npts, TY_REAL) + + switch (GM_FIT(fit)) { + case GM_ROTATE: + call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts, + Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch, + yerrmsg, maxch) + sx2 = NULL + sy2 = NULL + case GM_RSCALE: + call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts, + Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch, + yerrmsg, maxch) + sx2 = NULL + sy2 = NULL + case GM_RXYSCALE: + call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts, + Memr[xresidual], Memr[yresidual], npts, xerrmsg, maxch, + yerrmsg, maxch) + sx2 = NULL + sy2 = NULL + default: + GM_ZO(fit) = GM_XOREF(fit) + call geo_fxyr (fit, sx1, sx2, xref, yref, xin, wts, + Memr[xresidual], npts, YES, xerrmsg, maxch) + GM_ZO(fit) = GM_YOREF(fit) + call geo_fxyr (fit, sy1, sy2, xref, yref, yin, wts, + Memr[yresidual], npts, NO, yerrmsg, maxch) + } + if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit))) + GM_NREJECT(fit) = 0 + else + call geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, + wts, Memr[xresidual], Memr[yresidual], npts, xerrmsg, + maxch, yerrmsg, maxch) + + call sfree (sp) +end + + +# GEO_FTHETA -- Compute the shift and rotation angle required to match one +# set of coordinates to another. + +procedure geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid, + yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit sturcture +pointer sx1 #U pointer to linear x fit surface +pointer sy1 #U pointer to linear y fit surface +real xref[npts] #I reference image x values +real yref[npts] #I reference image y values +real xin[npts] #I input image x values +real yin[npts] #I input image y values +real wts[npts] #I array of weights +real xresid[npts] #O x fit residuals +real yresid[npts] #O y fit residuals +int npts #I number of points +char xerrmsg[ARB] #O returned x fit error message +int xmaxch #I maximum number of characters in x fit error message +char yerrmsg[ARB] #O returned y fit error message +int ymaxch #I maximum number of characters in y fit error message + +int i +double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0 +double syrxi, sxryi, sxrxi, syryi, num, denom, theta, det +double ctheta, stheta, cthetax, sthetax, cthetay, sthetay +real xmin, xmax, ymin, ymax +pointer sp, savefit +bool fp_equald() + +begin + # Allocate some working space + call smark (sp) + call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL) + + # Initialize the fit. + if (sx1 != NULL) + call gsfree (sx1) + if (sy1 != NULL) + call gsfree (sy1) + + # Determine the minimum and maximum values + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Compute the sums required to determine the offsets. + sw = 0.0d0 + sxr = 0.0d0 + syr = 0.0d0 + sxi = 0.0d0 + syi = 0.0d0 + do i = 1, npts { + sw = sw + wts[i] + sxr = sxr + wts[i] * xref[i] + syr = syr + wts[i] * yref[i] + sxi = sxi + wts[i] * xin[i] + syi = syi + wts[i] * yin[i] + } + + # Do the fit. + if (sw < 2) { + call sfree (sp) + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, + "Too few data points for X and Y fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for X and Y fits.") + call error (1, "Too few data points for X and Y fits.") + } else { + call sprintf (xerrmsg, xmaxch, + "Too few data points for XI and ETA fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for XI and ETA fits.") + call error (1, "Too few data points for XI and ETA fits.") + } + + } else { + + # Compute the sums required to compute the rotation angle. + xr0 = sxr / sw + yr0 = syr / sw + xi0 = sxi / sw + yi0 = syi / sw + syrxi = 0.0d0 + sxryi = 0.0d0 + sxrxi = 0.0d0 + syryi = 0.0d0 + do i = 1, npts { + syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0) + sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0) + sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0) + syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0) + } + + # Compute the rotation angle. + num = sxrxi * syryi + denom = syrxi * sxryi + if (fp_equald (num, denom)) + det = 0.0d0 + else + det = num - denom + if (det < 0.0d0) { + num = syrxi + sxryi + denom = -sxrxi + syryi + } else { + num = syrxi - sxryi + denom = sxrxi + syryi + } + if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) { + theta = 0.0d0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + theta = atan2 (num, denom) + if (theta < 0.0d0) + theta = theta + TWOPI + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the polynomial coefficients. + ctheta = cos (theta) + stheta = sin (theta) + if (det < 0.0d0) { + cthetax = -ctheta + sthetay = -stheta + } else { + cthetax = ctheta + sthetay = stheta + } + sthetax = stheta + cthetay = ctheta + + # Compute the x fit coefficients. + call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sx1, Memr[savefit]) + call gsfree (sx1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + Memr[savefit+GS_SAVECOEFF+1] = cthetax + Memr[savefit+GS_SAVECOEFF+2] = sthetax + } else { + Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax * + (ymax + ymin) / 2 + Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0 + Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0 + } + call gsrestore (sx1, Memr[savefit]) + + # Compute the y fit coefficients. + call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sy1, Memr[savefit]) + call gsfree (sy1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) + Memr[savefit+GS_SAVECOEFF+1] = -sthetay + Memr[savefit+GS_SAVECOEFF+2] = cthetay + } else { + Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay * + (ymax + ymin) / 2.0 + Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0 + Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0 + } + call gsrestore (sy1, Memr[savefit]) + + # Compute the residuals + call gsvector (sx1, xref, yref, xresid, npts) + call gsvector (sy1, xref, yref, yresid, npts) + call asubr (xin, xresid, xresid, npts) + call asubr (yin, yresid, yresid, npts) + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= real(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Compute the rms of the x and y fits. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2 + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2 + + GM_NPTS(fit) = npts + + } + + call sfree (sp) +end + + +# GEO_FMAGNIFY -- Compute the shift, the rotation angle, and the magnification +# factor which is assumed to be the same in x and y, required to match one +# set of coordinates to another. + +procedure geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid, + yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit sturcture +pointer sx1 #U pointer to linear x fit surface +pointer sy1 #U pointer to linear y fit surface +real xref[npts] #I reference image x values +real yref[npts] #I reference image y values +real xin[npts] #I input image x values +real yin[npts] #I input image y values +real wts[npts] #I array of weights +real xresid[npts] #O x fit residuals +real yresid[npts] #O y fit residuals +int npts #I number of points +char xerrmsg[ARB] #O returned x fit error message +int xmaxch #I maximum number of characters in x fit error message +char yerrmsg[ARB] #O returned y fit error message +int ymaxch #I maximum number of characters in y fit error message + +int i +double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0 +double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, det, theta +double mag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay +real xmin, xmax, ymin, ymax +pointer sp, savefit +bool fp_equald() + +begin + # Allocate some working space + call smark (sp) + call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL) + + # Initialize the fit. + if (sx1 != NULL) + call gsfree (sx1) + if (sy1 != NULL) + call gsfree (sy1) + + # Determine the minimum and maximum values. + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Compute the sums required to determine the offsets. + sw = 0.0d0 + sxr = 0.0d0 + syr = 0.0d0 + sxi = 0.0d0 + syi = 0.0d0 + do i = 1, npts { + sw = sw + wts[i] + sxr = sxr + wts[i] * xref[i] + syr = syr + wts[i] * yref[i] + sxi = sxi + wts[i] * xin[i] + syi = syi + wts[i] * yin[i] + } + + # Do the fit. + if (sw < 2) { + call sfree (sp) + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, + "Too few data points for X and Y fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for X and Y fits.") + call error (1, "Too few data points for X and Y fits.") + } else { + call sprintf (xerrmsg, xmaxch, + "Too few data points for XI and ETA fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for XI and ETA fits.") + call error (1, "Too few data points for XI and ETA fits.") + } + } else { + + # Compute the sums. + xr0 = sxr / sw + yr0 = syr / sw + xi0 = sxi / sw + yi0 = syi / sw + sxrxr = 0.0d0 + syryr = 0.0d0 + syrxi = 0.0d0 + sxryi = 0.0d0 + sxrxi = 0.0d0 + syryi = 0.0d0 + do i = 1, npts { + sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0) + syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0) + syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0) + sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0) + sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0) + syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0) + } + + # Compute the rotation angle. + num = sxrxi * syryi + denom = syrxi * sxryi + if (fp_equald (num, denom)) + det = 0.0d0 + else + det = num - denom + if (det < 0.0d0) { + num = syrxi + sxryi + denom = -sxrxi + syryi + } else { + num = syrxi - sxryi + denom = sxrxi + syryi + } + if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) { + theta = 0.0d0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + theta = atan2 (num, denom) + if (theta < 0.0d0) + theta = theta + TWOPI + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the magnification factor. + ctheta = cos (theta) + stheta = sin (theta) + num = denom * ctheta + num * stheta + denom = sxrxr + syryr + if (denom <= 0.0d0) { + mag = 1.0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + mag = num / denom + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the polynomial coefficients. + if (det < 0.0d0) { + cthetax = -mag * ctheta + sthetay = -mag * stheta + } else { + cthetax = mag * ctheta + sthetay = mag * stheta + } + sthetax = mag * stheta + cthetay = mag * ctheta + + # Compute the x fit coefficients. + call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sx1, Memr[savefit]) + call gsfree (sx1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + Memr[savefit+GS_SAVECOEFF+1] = cthetax + Memr[savefit+GS_SAVECOEFF+2] = sthetax + } else { + Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax * + (ymax + ymin) / 2 + Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0 + Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0 + } + call gsrestore (sx1, Memr[savefit]) + + # Compute the y fit coefficients. + call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sy1, Memr[savefit]) + call gsfree (sy1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) + Memr[savefit+GS_SAVECOEFF+1] = -sthetay + Memr[savefit+GS_SAVECOEFF+2] = cthetay + } else { + Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay * + (ymax + ymin) / 2.0 + Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0 + Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0 + } + call gsrestore (sy1, Memr[savefit]) + + # Compute the residuals + call gsvector (sx1, xref, yref, xresid, npts) + call gsvector (sy1, xref, yref, yresid, npts) + call asubr (xin, xresid, xresid, npts) + call asubr (yin, yresid, yresid, npts) + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= real(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Compute the rms of the x and y fits. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2 + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2 + + GM_NPTS(fit) = npts + + } + + call sfree (sp) +end + + +# GEO_FLINEAR -- Compute the shift, the rotation angle, and the x and y scale +# factors required to match one set of coordinates to another. + +procedure geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid, + yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit sturcture +pointer sx1 #U pointer to linear x fit surface +pointer sy1 #U pointer to linear y fit surface +real xref[npts] #I reference image x values +real yref[npts] #I reference image y values +real xin[npts] #I input image x values +real yin[npts] #I input image y values +real wts[npts] #I array of weights +real xresid[npts] #O x fit residuals +real yresid[npts] #O y fit residuals +int npts #I number of points +char xerrmsg[ARB] #O returned x fit error message +int xmaxch #I maximum number of characters in x fit error message +char yerrmsg[ARB] #O returned y fit error message +int ymaxch #I maximum number of characters in y fit error message + +int i +double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0 +double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, theta +double xmag, ymag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay +real xmin, xmax, ymin, ymax +pointer sp, savefit +bool fp_equald() + +begin + # Allocate some working space + call smark (sp) + call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL) + + # Initialize the fit. + if (sx1 != NULL) + call gsfree (sx1) + if (sy1 != NULL) + call gsfree (sy1) + + # Determine the minimum and maximum values. + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Compute the sums required to determine the offsets. + sw = 0.0d0 + sxr = 0.0d0 + syr = 0.0d0 + sxi = 0.0d0 + syi = 0.0d0 + do i = 1, npts { + sw = sw + wts[i] + sxr = sxr + wts[i] * xref[i] + syr = syr + wts[i] * yref[i] + sxi = sxi + wts[i] * xin[i] + syi = syi + wts[i] * yin[i] + } + + # Do the fit. + if (sw < 3) { + call sfree (sp) + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, + "Too few data points for X and Y fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for X and Y fits.") + call error (1, "Too few data points for X and Y fits.") + } else { + call sprintf (xerrmsg, xmaxch, + "Too few data points for XI and ETA fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for XI and ETA fits.") + call error (1, "Too few data points for XI and ETA fits.") + } + } else { + xr0 = sxr / sw + yr0 = syr / sw + xi0 = sxi / sw + yi0 = syi / sw + sxrxr = 0.0d0 + syryr = 0.0d0 + syrxi = 0.0d0 + sxryi = 0.0d0 + sxrxi = 0.0d0 + syryi = 0.0d0 + do i = 1, npts { + sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0) + syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0) + syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0) + sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0) + sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0) + syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0) + } + + # Compute the rotation angle. + num = 2.0d0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi) + denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - sxrxr * + (syrxi + syryi) * (syrxi - syryi) + if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) { + theta = 0.0d0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + theta = atan2 (num, denom) / 2.0d0 + if (theta < 0.0d0) + theta = theta + TWOPI + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + ctheta = cos (theta) + stheta = sin (theta) + + # Compute the x magnification factor. + num = sxrxi * ctheta - sxryi * stheta + denom = sxrxr + if (denom <= 0.0d0) { + xmag = 1.0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + xmag = num / denom + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the y magnification factor. + num = syrxi * stheta + syryi * ctheta + denom = syryr + if (denom <= 0.0d0) { + ymag = 1.0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + ymag = num / denom + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the polynomial coefficients. + cthetax = xmag * ctheta + sthetax = ymag * stheta + sthetay = xmag * stheta + cthetay = ymag * ctheta + + # Compute the x fit coefficients. + call gsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sx1, Memr[savefit]) + call gsfree (sx1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + Memr[savefit+GS_SAVECOEFF+1] = cthetax + Memr[savefit+GS_SAVECOEFF+2] = sthetax + } else { + Memr[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax * + (ymax + ymin) / 2 + Memr[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0 + Memr[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0 + } + call gsrestore (sx1, Memr[savefit]) + + # Compute the y fit coefficients. + call gsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sy1, Memr[savefit]) + call gsfree (sy1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) + Memr[savefit+GS_SAVECOEFF+1] = -sthetay + Memr[savefit+GS_SAVECOEFF+2] = cthetay + } else { + Memr[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay * + (ymax + ymin) / 2.0 + Memr[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0 + Memr[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0 + } + call gsrestore (sy1, Memr[savefit]) + + # Compute the residuals + call gsvector (sx1, xref, yref, xresid, npts) + call gsvector (sy1, xref, yref, yresid, npts) + call asubr (xin, xresid, xresid, npts) + call asubr (yin, yresid, yresid, npts) + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= real(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Compute the rms of the x and y fits. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2 + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2 + + GM_NPTS(fit) = npts + + } + + call sfree (sp) +end + + +# GEO_FXY -- Fit the surface. + +procedure geo_fxyr (fit, sf1, sf2, x, y, z, wts, resid, npts, xfit, errmsg, + maxch) + +pointer fit #I pointer to the fit sturcture +pointer sf1 #U pointer to linear surface +pointer sf2 #U pointer to higher order surface +real x[npts] #I reference image x values +real y[npts] #I reference image y values +real z[npts] #I z values +real wts[npts] #I array of weights +real resid[npts] #O fitted residuals +int npts #I number of points +int xfit #I X fit ? +char errmsg[ARB] #O returned error message +int maxch #I maximum number of characters in error message + +int i, ier, ncoeff +pointer sp, zfit, savefit, coeff +real xmin, xmax, ymin, ymax +bool fp_equald() + +begin + # Allocate working space. + call smark (sp) + call salloc (zfit, npts, TY_REAL) + call salloc (savefit, GS_SAVECOEFF + 3, TY_REAL) + call salloc (coeff, 3, TY_REAL) + + # Determine the minimum and maximum values + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Initalize fit + if (sf1 != NULL) + call gsfree (sf1) + if (sf2 != NULL) + call gsfree (sf2) + + if (xfit == YES) { + + switch (GM_FIT(fit)) { + + case GM_SHIFT: + call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sf1, Memr[savefit]) + call gsfree (sf1) + call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax, + ymin, ymax) + call asubr (z, x, Memr[zfit], npts) + call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier) + call gscoeff (sf1, Memr[coeff], ncoeff) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + Memr[savefit+GS_SAVECOEFF+1] = 1.0 + Memr[savefit+GS_SAVECOEFF+2] = 0.0 + } else { + Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (xmax + xmin) / + 2.0 + Memr[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0 + Memr[savefit+GS_SAVECOEFF+2] = 0.0 + } + call gsfree (sf1) + call gsrestore (sf1, Memr[savefit]) + sf2 = NULL + + case GM_XYSCALE: + call gsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax, + ymin, ymax) + call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + sf2 = NULL + + default: + call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gsset (sf1, GSXREF, GM_XO(fit)) + call gsset (sf1, GSYREF, GM_YO(fit)) + call gsset (sf1, GSZREF, GM_ZO(fit)) + call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 || + GM_XXTERMS(fit) == GS_XFULL) + call gsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit), + GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin, + ymax) + else + sf2 = NULL + } + + } else { + + switch (GM_FIT(fit)) { + + case GM_SHIFT: + call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call gssave (sf1, Memr[savefit]) + call gsfree (sf1) + call gsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax, + ymin, ymax) + call asubr (z, y, Memr[zfit], npts) + call gsfit (sf1, x, y, Memr[zfit], wts, npts, WTS_USER, ier) + call gscoeff (sf1, Memr[coeff], ncoeff) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + Memr[savefit+GS_SAVECOEFF+1] = 0.0 + Memr[savefit+GS_SAVECOEFF+2] = 1.0 + } else { + Memr[savefit+GS_SAVECOEFF] = Memr[coeff] + (ymin + ymax) / + 2.0 + Memr[savefit+GS_SAVECOEFF+1] = 0.0 + Memr[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0 + } + call gsfree (sf1) + call gsrestore (sf1, Memr[savefit]) + sf2 = NULL + + case GM_XYSCALE: + call gsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin, + xmax, ymin, ymax) + call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + sf2 = NULL + + default: + call gsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, + xmax, ymin, ymax) + call gsset (sf1, GSXREF, GM_XO(fit)) + call gsset (sf1, GSYREF, GM_YO(fit)) + call gsset (sf1, GSZREF, GM_ZO(fit)) + call gsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 || + GM_YXTERMS(fit) == GS_XFULL) + call gsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit), + GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin, + ymax) + else + sf2 = NULL + + } + + } + + + if (ier == NO_DEG_FREEDOM) { + call sfree (sp) + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for X fit.") + call error (1, "Too few data points for X fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for XI fit.") + call error (1, "Too few data points for XI fit.") + } + } else { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for Y fit.") + call error (1, "Too few data points for Y fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for ETA fit.") + call error (1, "Too few data points for ETA fit.") + } + } + } else if (ier == SINGULAR) { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular X fit.") + else + call sprintf (errmsg, maxch, "Warning singular XI fit.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular Y fit.") + else + call sprintf (errmsg, maxch, "Warning singular ETA fit.") + } + } else { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "X fit ok.") + else + call sprintf (errmsg, maxch, "XI fit ok.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Y fit ok.") + else + call sprintf (errmsg, maxch, "ETA fit ok.") + } + } + + call gsvector (sf1, x, y, resid, npts) + call asubr (z, resid, resid, npts) + + # Calculate higher order fit. + if (sf2 != NULL) { + call gsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier) + if (ier == NO_DEG_FREEDOM) { + call sfree (sp) + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for X fit.") + call error (1, "Too few data points for X fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for XI fit.") + call error (1, "Too few data points for XI fit.") + } + } else { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for Y fit.") + call error (1, "Too few data points for Y fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for ETA fit.") + call error (1, "Too few data points for ETA fit.") + } + } + } else if (ier == SINGULAR) { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular X fit.") + else + call sprintf (errmsg, maxch, "Warning singular XI fit.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular Y fit.") + else + call sprintf (errmsg, maxch, + "Warning singular ETA fit.") + } + } else { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "X fit ok.") + else + call sprintf (errmsg, maxch, "XI fit ok.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Y fit ok.") + else + call sprintf (errmsg, maxch, "ETA fit ok.") + } + } + call gsvector (sf2, x, y, Memr[zfit], npts) + call asubr (resid, Memr[zfit], resid, npts) + } + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= real(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # calculate the rms of the fit + if (xfit == YES) { + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * resid[i] ** 2 + } else { + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * resid[i] ** 2 + } + + GM_NPTS(fit) = npts + + call sfree (sp) +end + + +# GEO_MREJECT -- Reject points from the fit. + +procedure geo_mrejectr (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, + xresid, yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit structure +pointer sx1, sy1 #I pointers to the linear surface +pointer sx2, sy2 #I pointers to the higher order surface +real xref[npts] #I reference image x values +real yref[npts] #I yreference values +real xin[npts] #I x values +real yin[npts] #I yvalues +real wts[npts] #I weights +real xresid[npts] #I residuals +real yresid[npts] #I yresiduals +int npts #I number of data points +char xerrmsg[ARB] #O the output x error message +int xmaxch #I maximum number of characters in the x error message +char yerrmsg[ARB] #O the output y error message +int ymaxch #I maximum number of characters in the y error message + +int i +int nreject, niter +pointer sp, twts +real cutx, cuty +errchk geo_fxyr(), geo_fthetar(), geo_fmagnifyr(), geo_flinearr() + +begin + # Allocate working space. + call smark (sp) + call salloc (twts, npts, TY_REAL) + + # Allocate space for the residuals. + if (GM_REJ(fit) != NULL) + call mfree (GM_REJ(fit), TY_INT) + call malloc (GM_REJ(fit), npts, TY_INT) + GM_NREJECT(fit) = 0 + + # Initialize the temporary weights array and the number of rejected + # points. + call amovr (wts, Memr[twts], npts) + nreject = 0 + + niter = 0 + repeat { + + # Compute the rejection limits. + if ((npts - GM_NWTS0(fit)) > 1) { + cutx = GM_REJECT(fit) * sqrt (GM_XRMS(fit) / (npts - + GM_NWTS0(fit) - 1)) + cuty = GM_REJECT(fit) * sqrt (GM_YRMS(fit) / (npts - + GM_NWTS0(fit) - 1)) + } else { + cutx = MAX_REAL + cuty = MAX_REAL + } + + # Reject points from the fit. + do i = 1, npts { + if (Memr[twts+i-1] > 0.0 && ((abs (xresid[i]) > cutx) || + (abs (yresid[i]) > cuty))) { + Memr[twts+i-1] = real(0.0) + nreject = nreject + 1 + Memi[GM_REJ(fit)+nreject-1] = i + } + } + if ((nreject - GM_NREJECT(fit)) <= 0) + break + GM_NREJECT(fit) = nreject + + # Compute number of deleted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= 0.0) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Recompute the X and Y fit. + switch (GM_FIT(fit)) { + case GM_ROTATE: + call geo_fthetar (fit, sx1, sy1, xref, yref, xin, yin, + Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch, + yerrmsg, ymaxch) + sx2 = NULL + sy2 = NULL + case GM_RSCALE: + call geo_fmagnifyr (fit, sx1, sy1, xref, yref, xin, yin, + Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch, + yerrmsg, ymaxch) + sx2 = NULL + sy2 = NULL + case GM_RXYSCALE: + call geo_flinearr (fit, sx1, sy1, xref, yref, xin, yin, + Memr[twts], xresid, yresid, npts, xerrmsg, xmaxch, + yerrmsg, ymaxch) + sx2 = NULL + sy2 = NULL + default: + GM_ZO(fit) = GM_XOREF(fit) + call geo_fxyr (fit, sx1, sx2, xref, yref, xin, Memr[twts], + xresid, npts, YES, xerrmsg, xmaxch) + GM_ZO(fit) = GM_YOREF(fit) + call geo_fxyr (fit, sy1, sy2, xref, yref, yin, Memr[twts], + yresid, npts, NO, yerrmsg, ymaxch) + } + + # Compute the x fit rms. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + Memr[twts+i-1] * xresid[i] ** 2 + + # Compute the y fit rms. + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + Memr[twts+i-1] * yresid[i] ** 2 + + niter = niter + 1 + + } until (niter >= GM_MAXITER(fit)) + + call sfree (sp) +end + + +# GEO_MMFREE - Free the space used to fit the surfaces. + +procedure geo_mmfreer (sx1, sy1, sx2, sy2) + +pointer sx1 #U pointer to the x fits +pointer sy1 #U pointer to the y fit +pointer sx2 #U pointer to the higher order x fit +pointer sy2 #U pointer to the higher order y fit + +begin + if (sx1 != NULL) + call gsfree (sx1) + if (sy1 != NULL) + call gsfree (sy1) + if (sx2 != NULL) + call gsfree (sx2) + if (sy2 != NULL) + call gsfree (sy2) +end + + + +# GEO_FIT -- Fit the surface in batch. + +procedure geo_fitd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, npts, + xerrmsg, yerrmsg, maxch) + +pointer fit #I pointer to fitting structure +pointer sx1, sy1 #U pointer to linear surface +pointer sx2, sy2 #U pointer to higher order correction +double xref[ARB] #I x reference array +double yref[ARB] #I y reference array +double xin[ARB] #I x array +double yin[ARB] #I y array +double wts[ARB] #I weight array +int npts #I the number of data points +char xerrmsg[ARB] #O the x fit error message +char yerrmsg[ARB] #O the y fit error message +int maxch #I maximum size of the error message + +pointer sp, xresidual, yresidual +errchk geo_fxyd(), geo_mrejectd(), geo_fthetad(), geo_fmagnifyd() +errchk geo_flineard() + +begin + call smark (sp) + call salloc (xresidual, npts, TY_DOUBLE) + call salloc (yresidual, npts, TY_DOUBLE) + + switch (GM_FIT(fit)) { + case GM_ROTATE: + call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts, + Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch, + yerrmsg, maxch) + sx2 = NULL + sy2 = NULL + case GM_RSCALE: + call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts, + Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch, + yerrmsg, maxch) + sx2 = NULL + sy2 = NULL + case GM_RXYSCALE: + call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts, + Memd[xresidual], Memd[yresidual], npts, xerrmsg, maxch, + yerrmsg, maxch) + sx2 = NULL + sy2 = NULL + default: + GM_ZO(fit) = GM_XOREF(fit) + call geo_fxyd (fit, sx1, sx2, xref, yref, xin, wts, + Memd[xresidual], npts, YES, xerrmsg, maxch) + GM_ZO(fit) = GM_YOREF(fit) + call geo_fxyd (fit, sy1, sy2, xref, yref, yin, wts, + Memd[yresidual], npts, NO, yerrmsg, maxch) + } + if (GM_MAXITER(fit) <= 0 || IS_INDEFD(GM_REJECT(fit))) + GM_NREJECT(fit) = 0 + else + call geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, + wts, Memd[xresidual], Memd[yresidual], npts, xerrmsg, + maxch, yerrmsg, maxch) + + call sfree (sp) +end + + +# GEO_FTHETA -- Compute the shift and rotation angle required to match one +# set of coordinates to another. + +procedure geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid, + yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit sturcture +pointer sx1 #U pointer to linear x fit surface +pointer sy1 #U pointer to linear y fit surface +double xref[npts] #I reference image x values +double yref[npts] #I reference image y values +double xin[npts] #I input image x values +double yin[npts] #I input image y values +double wts[npts] #I array of weights +double xresid[npts] #O x fit residuals +double yresid[npts] #O y fit residuals +int npts #I number of points +char xerrmsg[ARB] #O returned x fit error message +int xmaxch #I maximum number of characters in x fit error message +char yerrmsg[ARB] #O returned y fit error message +int ymaxch #I maximum number of characters in y fit error message + +int i +double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0 +double syrxi, sxryi, sxrxi, syryi, num, denom, theta, det +double ctheta, stheta, cthetax, sthetax, cthetay, sthetay +double xmin, xmax, ymin, ymax +pointer sp, savefit +bool fp_equald() + +begin + # Allocate some working space + call smark (sp) + call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE) + + # Initialize the fit. + if (sx1 != NULL) + call dgsfree (sx1) + if (sy1 != NULL) + call dgsfree (sy1) + + # Determine the minimum and maximum values + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Compute the sums required to determine the offsets. + sw = 0.0d0 + sxr = 0.0d0 + syr = 0.0d0 + sxi = 0.0d0 + syi = 0.0d0 + do i = 1, npts { + sw = sw + wts[i] + sxr = sxr + wts[i] * xref[i] + syr = syr + wts[i] * yref[i] + sxi = sxi + wts[i] * xin[i] + syi = syi + wts[i] * yin[i] + } + + # Do the fit. + if (sw < 2) { + call sfree (sp) + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, + "Too few data points for X and Y fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for X and Y fits.") + call error (1, "Too few data points for X and Y fits.") + } else { + call sprintf (xerrmsg, xmaxch, + "Too few data points for XI and ETA fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for XI and ETA fits.") + call error (1, "Too few data points for XI and ETA fits.") + } + + } else { + + # Compute the sums required to compute the rotation angle. + xr0 = sxr / sw + yr0 = syr / sw + xi0 = sxi / sw + yi0 = syi / sw + syrxi = 0.0d0 + sxryi = 0.0d0 + sxrxi = 0.0d0 + syryi = 0.0d0 + do i = 1, npts { + syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0) + sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0) + sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0) + syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0) + } + + # Compute the rotation angle. + num = sxrxi * syryi + denom = syrxi * sxryi + if (fp_equald (num, denom)) + det = 0.0d0 + else + det = num - denom + if (det < 0.0d0) { + num = syrxi + sxryi + denom = -sxrxi + syryi + } else { + num = syrxi - sxryi + denom = sxrxi + syryi + } + if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) { + theta = 0.0d0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + theta = atan2 (num, denom) + if (theta < 0.0d0) + theta = theta + TWOPI + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the polynomial coefficients. + ctheta = cos (theta) + stheta = sin (theta) + if (det < 0.0d0) { + cthetax = -ctheta + sthetay = -stheta + } else { + cthetax = ctheta + sthetay = stheta + } + sthetax = stheta + cthetay = ctheta + + # Compute the x fit coefficients. + call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sx1, Memd[savefit]) + call dgsfree (sx1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + Memd[savefit+GS_SAVECOEFF+1] = cthetax + Memd[savefit+GS_SAVECOEFF+2] = sthetax + } else { + Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax * + (ymin + ymax) / 2.0 + Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0 + Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0 + } + call dgsrestore (sx1, Memd[savefit]) + + # Compute the y fit coefficients. + call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sy1, Memd[savefit]) + call dgsfree (sy1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) + Memd[savefit+GS_SAVECOEFF+1] = -sthetay + Memd[savefit+GS_SAVECOEFF+2] = cthetay + } else { + Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay * + (ymin + ymax) / 2.0 + Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0 + Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0 + } + call dgsrestore (sy1, Memd[savefit]) + + # Compute the residuals + call dgsvector (sx1, xref, yref, xresid, npts) + call dgsvector (sy1, xref, yref, yresid, npts) + call asubd (xin, xresid, xresid, npts) + call asubd (yin, yresid, yresid, npts) + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= double(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Compute the rms of the x and y fits. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2 + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2 + + GM_NPTS(fit) = npts + + } + + call sfree (sp) +end + + +# GEO_FMAGNIFY -- Compute the shift, the rotation angle, and the magnification +# factor which is assumed to be the same in x and y, required to match one +# set of coordinates to another. + +procedure geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid, + yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit sturcture +pointer sx1 #U pointer to linear x fit surface +pointer sy1 #U pointer to linear y fit surface +double xref[npts] #I reference image x values +double yref[npts] #I reference image y values +double xin[npts] #I input image x values +double yin[npts] #I input image y values +double wts[npts] #I array of weights +double xresid[npts] #O x fit residuals +double yresid[npts] #O y fit residuals +int npts #I number of points +char xerrmsg[ARB] #O returned x fit error message +int xmaxch #I maximum number of characters in x fit error message +char yerrmsg[ARB] #O returned y fit error message +int ymaxch #I maximum number of characters in y fit error message + +int i +double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0 +double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, det, theta +double mag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay +double xmin, xmax, ymin, ymax +pointer sp, savefit +bool fp_equald() + +begin + # Allocate some working space + call smark (sp) + call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE) + + # Initialize the fit. + if (sx1 != NULL) + call dgsfree (sx1) + if (sy1 != NULL) + call dgsfree (sy1) + + # Determine the minimum and maximum values. + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Compute the sums required to determine the offsets. + sw = 0.0d0 + sxr = 0.0d0 + syr = 0.0d0 + sxi = 0.0d0 + syi = 0.0d0 + do i = 1, npts { + sw = sw + wts[i] + sxr = sxr + wts[i] * xref[i] + syr = syr + wts[i] * yref[i] + sxi = sxi + wts[i] * xin[i] + syi = syi + wts[i] * yin[i] + } + + # Do the fit. + if (sw < 2) { + call sfree (sp) + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, + "Too few data points for X and Y fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for X and Y fits.") + call error (1, "Too few data points for X and Y fits.") + } else { + call sprintf (xerrmsg, xmaxch, + "Too few data points for XI and ETA fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for XI and ETA fits.") + call error (1, "Too few data points for XI and ETA fits.") + } + } else { + + # Compute the sums. + xr0 = sxr / sw + yr0 = syr / sw + xi0 = sxi / sw + yi0 = syi / sw + sxrxr = 0.0d0 + syryr = 0.0d0 + syrxi = 0.0d0 + sxryi = 0.0d0 + sxrxi = 0.0d0 + syryi = 0.0d0 + do i = 1, npts { + sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0) + syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0) + syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0) + sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0) + sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0) + syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0) + } + + # Compute the rotation angle. + num = sxrxi * syryi + denom = syrxi * sxryi + if (fp_equald (num, denom)) + det = 0.0d0 + else + det = num - denom + if (det < 0.0d0) { + num = syrxi + sxryi + denom = -sxrxi + syryi + } else { + num = syrxi - sxryi + denom = sxrxi + syryi + } + if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) { + theta = 0.0d0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + theta = atan2 (num, denom) + if (theta < 0.0d0) + theta = theta + TWOPI + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the magnification factor. + ctheta = cos (theta) + stheta = sin (theta) + num = denom * ctheta + num * stheta + denom = sxrxr + syryr + if (denom <= 0.0d0) { + mag = 1.0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + mag = num / denom + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the polynomial coefficients. + if (det < 0.0d0) { + cthetax = -mag * ctheta + sthetay = -mag * stheta + } else { + cthetax = mag * ctheta + sthetay = mag * stheta + } + sthetax = mag * stheta + cthetay = mag * ctheta + + # Compute the x fit coefficients. + call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sx1, Memd[savefit]) + call dgsfree (sx1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + Memd[savefit+GS_SAVECOEFF+1] = cthetax + Memd[savefit+GS_SAVECOEFF+2] = sthetax + } else { + Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax * + (ymin + ymax) / 2.0 + Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0 + Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0 + } + call dgsrestore (sx1, Memd[savefit]) + + # Compute the y fit coefficients. + call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sy1, Memd[savefit]) + call dgsfree (sy1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) + Memd[savefit+GS_SAVECOEFF+1] = -sthetay + Memd[savefit+GS_SAVECOEFF+2] = cthetay + } else { + Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay * + (ymin + ymax) / 2.0 + Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0 + Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0 + } + call dgsrestore (sy1, Memd[savefit]) + + # Compute the residuals + call dgsvector (sx1, xref, yref, xresid, npts) + call dgsvector (sy1, xref, yref, yresid, npts) + call asubd (xin, xresid, xresid, npts) + call asubd (yin, yresid, yresid, npts) + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= double(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Compute the rms of the x and y fits. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2 + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2 + + GM_NPTS(fit) = npts + + } + + call sfree (sp) +end + + +# GEO_FLINEAR -- Compute the shift, the rotation angle, and the x and y scale +# factors required to match one set of coordinates to another. + +procedure geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, wts, xresid, + yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit sturcture +pointer sx1 #U pointer to linear x fit surface +pointer sy1 #U pointer to linear y fit surface +double xref[npts] #I reference image x values +double yref[npts] #I reference image y values +double xin[npts] #I input image x values +double yin[npts] #I input image y values +double wts[npts] #I array of weights +double xresid[npts] #O x fit residuals +double yresid[npts] #O y fit residuals +int npts #I number of points +char xerrmsg[ARB] #O returned x fit error message +int xmaxch #I maximum number of characters in x fit error message +char yerrmsg[ARB] #O returned y fit error message +int ymaxch #I maximum number of characters in y fit error message + +int i +double sw, sxr, syr, sxi, syi, xr0, yr0, xi0, yi0 +double syrxi, sxryi, sxrxi, syryi, sxrxr, syryr, num, denom, theta +double xmag, ymag, ctheta, stheta, cthetax, sthetax, cthetay, sthetay +double xmin, xmax, ymin, ymax +pointer sp, savefit +bool fp_equald() + +begin + # Allocate some working space + call smark (sp) + call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE) + + # Initialize the fit. + if (sx1 != NULL) + call dgsfree (sx1) + if (sy1 != NULL) + call dgsfree (sy1) + + # Determine the minimum and maximum values. + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Compute the sums required to determine the offsets. + sw = 0.0d0 + sxr = 0.0d0 + syr = 0.0d0 + sxi = 0.0d0 + syi = 0.0d0 + do i = 1, npts { + sw = sw + wts[i] + sxr = sxr + wts[i] * xref[i] + syr = syr + wts[i] * yref[i] + sxi = sxi + wts[i] * xin[i] + syi = syi + wts[i] * yin[i] + } + + # Do the fit. + if (sw < 3) { + call sfree (sp) + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, + "Too few data points for X and Y fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for X and Y fits.") + call error (1, "Too few data points for X and Y fits.") + } else { + call sprintf (xerrmsg, xmaxch, + "Too few data points for XI and ETA fits.") + call sprintf (yerrmsg, ymaxch, + "Too few data points for XI and ETA fits.") + call error (1, "Too few data points for XI and ETA fits.") + } + } else { + xr0 = sxr / sw + yr0 = syr / sw + xi0 = sxi / sw + yi0 = syi / sw + sxrxr = 0.0d0 + syryr = 0.0d0 + syrxi = 0.0d0 + sxryi = 0.0d0 + sxrxi = 0.0d0 + syryi = 0.0d0 + do i = 1, npts { + sxrxr = sxrxr + wts[i] * (xref[i] - xr0) * (xref[i] - xr0) + syryr = syryr + wts[i] * (yref[i] - yr0) * (yref[i] - yr0) + syrxi = syrxi + wts[i] * (yref[i] - yr0) * (xin[i] - xi0) + sxryi = sxryi + wts[i] * (xref[i] - xr0) * (yin[i] - yi0) + sxrxi = sxrxi + wts[i] * (xref[i] - xr0) * (xin[i] - xi0) + syryi = syryi + wts[i] * (yref[i] - yr0) * (yin[i] - yi0) + } + + # Compute the rotation angle. + num = 2.0d0 * (sxrxr * syrxi * syryi - syryr * sxrxi * sxryi) + denom = syryr * (sxrxi - sxryi) * (sxrxi + sxryi) - sxrxr * + (syrxi + syryi) * (syrxi - syryi) + if (fp_equald (num, 0.0d0) && fp_equald (denom, 0.0d0)) { + theta = 0.0d0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + theta = atan2 (num, denom) / 2.0d0 + if (theta < 0.0d0) + theta = theta + TWOPI + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + ctheta = cos (theta) + stheta = sin (theta) + + # Compute the x magnification factor. + num = sxrxi * ctheta - sxryi * stheta + denom = sxrxr + if (denom <= 0.0d0) { + xmag = 1.0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + xmag = num / denom + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the y magnification factor. + num = syrxi * stheta + syryi * ctheta + denom = syryr + if (denom <= 0.0d0) { + ymag = 1.0 + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "Warning singular X fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular Y fit.") + } else { + call sprintf (xerrmsg, xmaxch, "Warning singular XI fit.") + call sprintf (yerrmsg, ymaxch, "Warning singular ETA fit.") + } + } else { + ymag = num / denom + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (xerrmsg, xmaxch, "X fit ok.") + call sprintf (yerrmsg, ymaxch, "Y fit ok.") + } else { + call sprintf (xerrmsg, xmaxch, "XI fit ok.") + call sprintf (yerrmsg, ymaxch, "ETA fit ok.") + } + } + + # Compute the polynomial coefficients. + cthetax = xmag * ctheta + sthetax = ymag * stheta + sthetay = xmag * stheta + cthetay = ymag * ctheta + + # Compute the x fit coefficients. + call dgsinit (sx1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sx1, Memd[savefit]) + call dgsfree (sx1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + Memd[savefit+GS_SAVECOEFF+1] = cthetax + Memd[savefit+GS_SAVECOEFF+2] = sthetax + } else { + Memd[savefit+GS_SAVECOEFF] = xi0 - (xr0 * cthetax + yr0 * + sthetax) + cthetax * (xmax + xmin) / 2.0 + sthetax * + (ymin + ymax) / 2.0 + Memd[savefit+GS_SAVECOEFF+1] = cthetax * (xmax - xmin) / 2.0 + Memd[savefit+GS_SAVECOEFF+2] = sthetax * (ymax - ymin) / 2.0 + } + call dgsrestore (sx1, Memd[savefit]) + + # Compute the y fit coefficients. + call dgsinit (sy1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sy1, Memd[savefit]) + call dgsfree (sy1) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) + Memd[savefit+GS_SAVECOEFF+1] = -sthetay + Memd[savefit+GS_SAVECOEFF+2] = cthetay + } else { + Memd[savefit+GS_SAVECOEFF] = yi0 - (-xr0 * sthetay + yr0 * + cthetay) - sthetay * (xmax + xmin) / 2.0 + cthetay * + (ymin + ymax) / 2.0 + Memd[savefit+GS_SAVECOEFF+1] = -sthetay * (xmax - xmin) / 2.0 + Memd[savefit+GS_SAVECOEFF+2] = cthetay * (ymax - ymin) / 2.0 + } + call dgsrestore (sy1, Memd[savefit]) + + # Compute the residuals + call dgsvector (sx1, xref, yref, xresid, npts) + call dgsvector (sy1, xref, yref, yresid, npts) + call asubd (xin, xresid, xresid, npts) + call asubd (yin, yresid, yresid, npts) + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= double(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Compute the rms of the x and y fits. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * xresid[i] ** 2 + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * yresid[i] ** 2 + + GM_NPTS(fit) = npts + + } + + call sfree (sp) +end + + +# GEO_FXY -- Fit the surface. + +procedure geo_fxyd (fit, sf1, sf2, x, y, z, wts, resid, npts, xfit, errmsg, + maxch) + +pointer fit #I pointer to the fit sturcture +pointer sf1 #U pointer to linear surface +pointer sf2 #U pointer to higher order surface +double x[npts] #I reference image x values +double y[npts] #I reference image y values +double z[npts] #I z values +double wts[npts] #I array of weights +double resid[npts] #O fitted residuals +int npts #I number of points +int xfit #I X fit ? +char errmsg[ARB] #O returned error message +int maxch #I maximum number of characters in error message + +int i, ier, ncoeff +pointer sp, zfit, savefit, coeff +double xmin, xmax, ymin, ymax +bool fp_equald() + +begin + # Allocate working space. + call smark (sp) + call salloc (zfit, npts, TY_DOUBLE) + call salloc (savefit, GS_SAVECOEFF + 3, TY_DOUBLE) + call salloc (coeff, 3, TY_DOUBLE) + + # Determine the minimum and maximum values + if (fp_equald (GM_XMIN(fit), GM_XMAX(fit))) { + xmin = GM_XMIN(fit) - 0.5d0 + xmax = GM_XMAX(fit) + 0.5d0 + } else { + xmin = GM_XMIN(fit) + xmax = GM_XMAX(fit) + } + if (fp_equald (GM_YMIN(fit), GM_YMAX(fit))) { + ymin = GM_YMIN(fit) - 0.5d0 + ymax = GM_YMAX(fit) + 0.5d0 + } else { + ymin = GM_YMIN(fit) + ymax = GM_YMAX(fit) + } + + # Initalize fit + if (sf1 != NULL) + call dgsfree (sf1) + if (sf2 != NULL) + call dgsfree (sf2) + + if (xfit == YES) { + + switch (GM_FIT(fit)) { + + case GM_SHIFT: + call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sf1, Memd[savefit]) + call dgsfree (sf1) + call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax, + ymin, ymax) + call asubd (z, x, Memd[zfit], npts) + call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier) + call dgscoeff (sf1, Memd[coeff], ncoeff) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + Memd[savefit+GS_SAVECOEFF+1] = 1.0d0 + Memd[savefit+GS_SAVECOEFF+2] = 0.0d0 + } else { + Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (xmax + xmin) / + 2.0d0 + Memd[savefit+GS_SAVECOEFF+1] = (xmax - xmin) / 2.0d0 + Memd[savefit+GS_SAVECOEFF+2] = 0.0d0 + } + call dgsfree (sf1) + call dgsrestore (sf1, Memd[savefit]) + sf2 = NULL + + case GM_XYSCALE: + call dgsinit (sf1, GM_FUNCTION(fit), 2, 1, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + sf2 = NULL + + default: + call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgsset (sf1, GSXREF, GM_XO(fit)) + call dgsset (sf1, GSYREF, GM_YO(fit)) + call dgsset (sf1, GSZREF, GM_ZO(fit)) + call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + if (GM_XXORDER(fit) > 2 || GM_XYORDER(fit) > 2 || + GM_XXTERMS(fit) == GS_XFULL) + call dgsinit (sf2, GM_FUNCTION(fit), GM_XXORDER(fit), + GM_XYORDER(fit), GM_XXTERMS(fit), xmin, xmax, ymin, + ymax) + else + sf2 = NULL + } + + } else { + + switch (GM_FIT(fit)) { + + case GM_SHIFT: + call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgssave (sf1, Memd[savefit]) + call dgsfree (sf1) + call dgsinit (sf1, GM_FUNCTION(fit), 1, 1, GS_XNONE, xmin, xmax, + ymin, ymax) + call asubd (z, y, Memd[zfit], npts) + call dgsfit (sf1, x, y, Memd[zfit], wts, npts, WTS_USER, ier) + call dgscoeff (sf1, Memd[coeff], ncoeff) + if (GM_FUNCTION(fit) == GS_POLYNOMIAL) { + Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + Memd[savefit+GS_SAVECOEFF+1] = 0.0d0 + Memd[savefit+GS_SAVECOEFF+2] = 1.0d0 + } else { + Memd[savefit+GS_SAVECOEFF] = Memd[coeff] + (ymin + ymax) / + 2.0d0 + Memd[savefit+GS_SAVECOEFF+1] = 0.0d0 + Memd[savefit+GS_SAVECOEFF+2] = (ymax - ymin) / 2.0d0 + } + call dgsfree (sf1) + call dgsrestore (sf1, Memd[savefit]) + sf2 = NULL + + case GM_XYSCALE: + call dgsinit (sf1, GM_FUNCTION(fit), 1, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + sf2 = NULL + + default: + call dgsinit (sf1, GM_FUNCTION(fit), 2, 2, GS_XNONE, xmin, xmax, + ymin, ymax) + call dgsset (sf1, GSXREF, GM_XO(fit)) + call dgsset (sf1, GSYREF, GM_YO(fit)) + call dgsset (sf1, GSZREF, GM_ZO(fit)) + call dgsfit (sf1, x, y, z, wts, npts, WTS_USER, ier) + if (GM_YXORDER(fit) > 2 || GM_YYORDER(fit) > 2 || + GM_YXTERMS(fit) == GS_XFULL) + call dgsinit (sf2, GM_FUNCTION(fit), GM_YXORDER(fit), + GM_YYORDER(fit), GM_YXTERMS(fit), xmin, xmax, ymin, + ymax) + else + sf2 = NULL + } + } + + + if (ier == NO_DEG_FREEDOM) { + call sfree (sp) + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for X fit.") + call error (1, "Too few data points for X fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for XI fit.") + call error (1, "Too few data points for XI fit.") + } + } else { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for Y fit.") + call error (1, "Too few data points for Y fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for ETA fit.") + call error (1, "Too few data points for ETA fit.") + } + } + } else if (ier == SINGULAR) { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular X fit.") + else + call sprintf (errmsg, maxch, "Warning singular XI fit.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular Y fit.") + else + call sprintf (errmsg, maxch, "Warning singular ETA fit.") + } + } else { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "X fit ok.") + else + call sprintf (errmsg, maxch, "XI fit ok.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Y fit ok.") + else + call sprintf (errmsg, maxch, "ETA fit ok.") + } + } + + call dgsvector (sf1, x, y, resid, npts) + call asubd (z, resid, resid, npts) + + # Calculate higher order fit. + if (sf2 != NULL) { + call dgsfit (sf2, x, y, resid, wts, npts, WTS_USER, ier) + if (ier == NO_DEG_FREEDOM) { + call sfree (sp) + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for X fit.") + call error (1, "Too few data points for X fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for XI fit.") + call error (1, "Too few data points for XI fit.") + } + } else { + if (GM_PROJECTION(fit) == GM_NONE) { + call sprintf (errmsg, maxch, + "Too few data points for Y fit.") + call error (1, "Too few data points for Y fit.") + } else { + call sprintf (errmsg, maxch, + "Too few data points for ETA fit.") + call error (1, "Too few data points for ETA fit.") + } + } + } else if (ier == SINGULAR) { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular X fit.") + else + call sprintf (errmsg, maxch, "Warning singular XI fit.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Warning singular Y fit.") + else + call sprintf (errmsg, maxch, + "Warning singular ETA fit.") + } + } else { + if (xfit == YES) { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "X fit ok.") + else + call sprintf (errmsg, maxch, "XI fit ok.") + } else { + if (GM_PROJECTION(fit) == GM_NONE) + call sprintf (errmsg, maxch, "Y fit ok.") + else + call sprintf (errmsg, maxch, "ETA fit ok.") + } + } + call dgsvector (sf2, x, y, Memd[zfit], npts) + call asubd (resid, Memd[zfit], resid, npts) + } + + # Compute the number of zero weighted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= double(0.0)) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # calculate the rms of the fit + if (xfit == YES) { + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + wts[i] * resid[i] ** 2 + } else { + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + wts[i] * resid[i] ** 2 + } + + GM_NPTS(fit) = npts + + call sfree (sp) +end + + +# GEO_MREJECT -- Reject points from the fit. + +procedure geo_mrejectd (fit, sx1, sy1, sx2, sy2, xref, yref, xin, yin, wts, + xresid, yresid, npts, xerrmsg, xmaxch, yerrmsg, ymaxch) + +pointer fit #I pointer to the fit structure +pointer sx1, sy1 #I pointers to the linear surface +pointer sx2, sy2 #I pointers to the higher order surface +double xref[npts] #I reference image x values +double yref[npts] #I yreference values +double xin[npts] #I x values +double yin[npts] #I yvalues +double wts[npts] #I weights +double xresid[npts] #I residuals +double yresid[npts] #I yresiduals +int npts #I number of data points +char xerrmsg[ARB] #O the output x error message +int xmaxch #I maximum number of characters in the x error message +char yerrmsg[ARB] #O the output y error message +int ymaxch #I maximum number of characters in the y error message + +int i +int nreject, niter +pointer sp, twts +double cutx, cuty +errchk geo_fxyd(), geo_fthetad(), geo_fmagnifyd(), geo_flineard() + +begin + # Allocate working space. + call smark (sp) + call salloc (twts, npts, TY_DOUBLE) + + # Allocate space for the residuals. + if (GM_REJ(fit) != NULL) + call mfree (GM_REJ(fit), TY_INT) + call malloc (GM_REJ(fit), npts, TY_INT) + GM_NREJECT(fit) = 0 + + # Initialize the temporary weights array and the number of rejected + # points. + call amovd (wts, Memd[twts], npts) + nreject = 0 + + niter = 0 + repeat { + + # Compute the rejection limits. + if ((npts - GM_NWTS0(fit)) > 1) { + cutx = GM_REJECT(fit) * sqrt (GM_XRMS(fit) / (npts - + GM_NWTS0(fit) - 1)) + cuty = GM_REJECT(fit) * sqrt (GM_YRMS(fit) / (npts - + GM_NWTS0(fit) - 1)) + } else { + cutx = MAX_REAL + cuty = MAX_REAL + } + + # Reject points from the fit. + do i = 1, npts { + if (Memd[twts+i-1] > 0.0 && ((abs (xresid[i]) > cutx) || + (abs (yresid[i]) > cuty))) { + Memd[twts+i-1] = double(0.0) + nreject = nreject + 1 + Memi[GM_REJ(fit)+nreject-1] = i + } + } + if ((nreject - GM_NREJECT(fit)) <= 0) + break + GM_NREJECT(fit) = nreject + + # Compute number of deleted points. + GM_NWTS0(fit) = 0 + do i = 1, npts { + if (wts[i] <= 0.0) + GM_NWTS0(fit) = GM_NWTS0(fit) + 1 + } + + # Recompute the X and Y fit. + switch (GM_FIT(fit)) { + case GM_ROTATE: + call geo_fthetad (fit, sx1, sy1, xref, yref, xin, yin, + Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch, + yerrmsg, ymaxch) + sx2 = NULL + sy2 = NULL + case GM_RSCALE: + call geo_fmagnifyd (fit, sx1, sy1, xref, yref, xin, yin, + Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch, + yerrmsg, ymaxch) + sx2 = NULL + sy2 = NULL + case GM_RXYSCALE: + call geo_flineard (fit, sx1, sy1, xref, yref, xin, yin, + Memd[twts], xresid, yresid, npts, xerrmsg, xmaxch, + yerrmsg, ymaxch) + sx2 = NULL + sy2 = NULL + default: + GM_ZO(fit) = GM_XOREF(fit) + call geo_fxyd (fit, sx1, sx2, xref, yref, xin, Memd[twts], + xresid, npts, YES, xerrmsg, xmaxch) + GM_ZO(fit) = GM_YOREF(fit) + call geo_fxyd (fit, sy1, sy2, xref, yref, yin, Memd[twts], + yresid, npts, NO, yerrmsg, ymaxch) + } + + # Compute the x fit rms. + GM_XRMS(fit) = 0.0d0 + do i = 1, npts + GM_XRMS(fit) = GM_XRMS(fit) + Memd[twts+i-1] * xresid[i] ** 2 + + # Compute the y fit rms. + GM_YRMS(fit) = 0.0d0 + do i = 1, npts + GM_YRMS(fit) = GM_YRMS(fit) + Memd[twts+i-1] * yresid[i] ** 2 + + niter = niter + 1 + + } until (niter >= GM_MAXITER(fit)) + + call sfree (sp) +end + + +# GEO_MMFREE - Free the space used to fit the surfaces. + +procedure geo_mmfreed (sx1, sy1, sx2, sy2) + +pointer sx1 #U pointer to the x fits +pointer sy1 #U pointer to the y fit +pointer sx2 #U pointer to the higher order x fit +pointer sy2 #U pointer to the higher order y fit + +begin + if (sx1 != NULL) + call dgsfree (sx1) + if (sy1 != NULL) + call dgsfree (sy1) + if (sx2 != NULL) + call dgsfree (sx2) + if (sy2 != NULL) + call dgsfree (sy2) +end + + |