aboutsummaryrefslogtreecommitdiff
path: root/sys/mwcs/wfsamp.x
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /sys/mwcs/wfsamp.x
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'sys/mwcs/wfsamp.x')
-rw-r--r--sys/mwcs/wfsamp.x233
1 files changed, 233 insertions, 0 deletions
diff --git a/sys/mwcs/wfsamp.x b/sys/mwcs/wfsamp.x
new file mode 100644
index 00000000..992f3211
--- /dev/null
+++ b/sys/mwcs/wfsamp.x
@@ -0,0 +1,233 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "mwcs.h"
+
+.help WFSAMP
+.nf -------------------------------------------------------------------------
+WFSAMP -- WCS function driver for the one dimensional sampled wcs function.
+For this driver, the function P<->W (physical to/from world) is defined by
+a sampled WCS curve.
+
+Driver routines:
+
+ FN_INIT wf_smp_init (fc, dir)
+ FN_DESTROY (none)
+ FN_FWD wf_smp_ctran (fc, v1, v2)
+ FN_INV (same)
+
+In this initial implementation, only linear interpolation of the sampled
+curve is provided, but the driver is easily extended to provide additional
+interpolators. NOTE that this entire driver assumes that the sampled function
+is monotonic.
+.endhelp --------------------------------------------------------------------
+
+# Driver specific fields of function call (FC) descriptor.
+define FC_NPTS Memi[$1+FCU] # number of points in curve
+define FC_LOC Memi[$1+FCU+1] # location in IN vector
+define FC_V1 Memi[$1+FCU+2] # pointer to IN vector
+define FC_V2 Memi[$1+FCU+3] # pointer to OUT vector
+define FC_W Memd[P2D($1+FCU+4)] # W value (CRVAL)
+define FC_DIR Memi[$1+FCU+6] # direction of transform
+
+
+# WF_SMP_INIT -- Initialize the function call descriptor for the indicated
+# type of transform (forward or inverse).
+
+procedure wf_smp_init (fc, dir)
+
+pointer fc #I pointer to FC descriptor
+int dir #I type of transformation
+
+int axis, npts
+pointer wp, mw, sp, emsg, pv, wv
+
+begin
+ # Enforce the current restriction to 1-dim sampled functions.
+ if (FC_NAXES(fc) != 1)
+ call error (1, "Sampled wcs functions must be 1-dimensional")
+
+ wp = FC_WCS(fc)
+ mw = CT_MW(FC_CT(fc))
+ axis = CT_AXIS(FC_CT(fc),1)
+
+ # Get pointers to the input and output sample vectors. For our
+ # purposes there is no difference between the forward and inverse
+ # transform; we just swap the vectors for the inverse transform.
+ # The use of direct pointers here assumes that the DBUF is not
+ # reallocated while the CTRAN is being used.
+
+ npts = WCS_NPTS(wp,axis)
+ pv = WCS_PV(wp,axis)
+ wv = WCS_WV(wp,axis)
+
+ # Verify that we have a sampled WCS for this axis.
+ if (npts <= 0 || pv == NULL || wv == NULL) {
+ call smark (sp)
+ call salloc (emsg, SZ_LINE, TY_CHAR)
+ call sprintf (Memc[emsg], SZ_LINE,
+ "No sampled wcs entered for axis %d")
+ call pargi (axis)
+ call error (2, Memc[emsg])
+ call sfree (sp)
+ }
+
+ if (dir == FORWARD) {
+ FC_V1(fc) = MI_DBUF(mw) + pv - 1
+ FC_V2(fc) = MI_DBUF(mw) + wv - 1
+ } else {
+ FC_V1(fc) = MI_DBUF(mw) + wv - 1
+ FC_V2(fc) = MI_DBUF(mw) + pv - 1
+ }
+
+ FC_NPTS(fc) = npts
+ if (WCS_W(wp) == NULL)
+ FC_W(fc) = 0.0
+ else
+ FC_W(fc) = D(mw,WCS_W(wp)+axis-1)
+
+ FC_LOC(fc) = 1
+ FC_DIR(fc) = dir
+end
+
+
+# WF_SMP_CTRAN -- Given the coordinates of a point X in the input curve,
+# locate the sample interval containing the point, and return the coordinate
+# of the same point in the output curve using simple linear interpolation
+# (currently) to evaluate the WCS function value.
+
+procedure wf_smp_ctran (fc, a_x, a_y)
+
+pointer fc #I pointer to FC descriptor
+double a_x #I point to sample WCS at
+double a_y #O value of WCS at that point
+
+int index, i, step
+double frac, x, y
+pointer ip, op, i1, i2
+int wf_smp_binsearch()
+define sample_ 91
+define oor_ 92
+
+begin
+ # Get the input X value.
+ if (FC_DIR(fc) == FORWARD)
+ x = a_x
+ else
+ x = a_x - FC_W(fc)
+
+ # Check for out of bounds and set step.
+ i1 = FC_V1(fc)
+ i2 = i1 + FC_NPTS(fc) - 1
+ if (Memd[i1] <= Memd[i2]) {
+ if (x < Memd[i1] || x > Memd[i2])
+ goto oor_
+ step = 1
+ } else {
+ if (x < Memd[i2] || x > Memd[i1])
+ goto oor_
+ step = -1
+ }
+
+ # Check the endpoints and the last inverval to optimize the case of
+ # repeated samplings of the same region of the curve.
+
+ if (x == Memd[i1])
+ ip = i1 - min (0, step)
+ else if (x == Memd[i2])
+ ip = i2 - max (0, step)
+ else
+ ip = FC_LOC(fc) + i1 - 1
+ if (Memd[ip] <= x && x <= Memd[ip+step])
+ goto sample_
+
+ # Next check several intervals to either side.
+ if (x < Memd[ip]) {
+ do i = 1, 5 {
+ ip = ip - step
+ if (Memd[ip] <= x)
+ goto sample_
+ }
+ } else {
+ do i = 1, 5 {
+ if (Memd[ip+step] >= x)
+ goto sample_
+ ip = ip + step
+ }
+ }
+
+ # Give up and do a full binary search!
+ index = wf_smp_binsearch (x, Memd[i1], FC_NPTS(fc))
+ if (index == 0)
+ goto oor_
+ else
+ ip = i1 + index - 1
+
+ # Having found the proper interval, compute the function value by
+ # interpolating the output vector.
+sample_
+ op = FC_V2(fc) + ip-i1
+ frac = (x - Memd[ip]) / (Memd[ip+step] - Memd[ip])
+ y = (Memd[op+step] - Memd[op]) * frac + Memd[op]
+
+ # Get the output Y value.
+ if (FC_DIR(fc) == FORWARD)
+ a_y = y
+ else
+ a_y = y + FC_W(fc)
+
+ # Save last location.
+ FC_LOC(fc) = ip - i1 + 1
+
+ return
+oor_
+ # Given X value is not in the region covered by the sampled curve,
+ # or at least we couldn't find it with a binary search.
+
+ call error (2, "Out of bounds reference on sampled WCS curve")
+end
+
+
+# WF_SMP_BINSEARCH -- Perform a binary search of a sorted array for the
+# interval containing the given point.
+
+int procedure wf_smp_binsearch (x, v, npts)
+
+double x #I point we want interval for
+double v[ARB] #I array to be searched
+int npts #I number of points in array
+
+int low, high, pos, i
+
+begin
+ low = 1
+ high = max (1, npts)
+
+ # Cut range of search in half until interval is found, or until range
+ # vanishes (high - low <= 1).
+
+ if (v[1] < v[npts]) {
+ do i = 1, npts {
+ pos = min ((high - low) / 2 + low, npts-1)
+ if (pos == low)
+ return (0) # not found
+ else if (v[pos] <= x && x <= v[pos+1])
+ return (pos)
+ else if (x < v[pos])
+ high = pos
+ else
+ low = pos
+ }
+ } else {
+ do i = 1, npts {
+ pos = min ((high - low) / 2 + low, npts-1)
+ if (pos == low)
+ return (0) # not found
+ else if (v[pos+1] <= x && x <= v[pos])
+ return (pos+1)
+ else if (x > v[pos])
+ high = pos
+ else
+ low = pos
+ }
+ }
+end