aboutsummaryrefslogtreecommitdiff
path: root/noao/digiphot/daophot/daolib/profile.x
diff options
context:
space:
mode:
Diffstat (limited to 'noao/digiphot/daophot/daolib/profile.x')
-rw-r--r--noao/digiphot/daophot/daolib/profile.x506
1 files changed, 506 insertions, 0 deletions
diff --git a/noao/digiphot/daophot/daolib/profile.x b/noao/digiphot/daophot/daolib/profile.x
new file mode 100644
index 00000000..96e1a531
--- /dev/null
+++ b/noao/digiphot/daophot/daolib/profile.x
@@ -0,0 +1,506 @@
+include "../lib/daophotdef.h"
+
+define NGL 4
+
+# DP_PROFILE -- Evaluate the analytic part of the psf function and its
+# derivatives.
+
+real procedure dp_profile (ipstyp, dx, dy, par, dhdxc, dhdyc, term, ideriv)
+
+int ipstyp # the analytic psf function type
+real dx, dy # distance of point from center of function
+real par[ARB] # the current parameter values
+real dhdxc, dhdyc # derivatives of the function integral wrt x,y
+real term[ARB] # derivatives of the function wrt parameters
+int ideriv # compute the derivatives ?
+
+int npt, ix, iy
+real d[NGL,NGL], w[NGL,NGL], x[NGL], xsq[NGL], p1xsq[NGL]
+real p1p2, dhdsx, dhdsy, erfx, erfy, p1sq, p2sq, y, ysq, p2ysq, profile
+real xy, wt, denom, alpha, func, p4fod, wp4fod, f, e, rsq, wf
+real wfsq, onemp3, dfby, deby, dbyx0, dbyy0
+real daoerf()
+
+data d / 0.0, 0.0, 0.0, 0.0,
+ -0.28867513, 0.28867513, 0.0, 0.0,
+ -0.38729833, 0.0, 0.38729833, 0.0,
+ -0.43056816, -0.16999052, 0.16999052, 0.43056816 /
+data w / 1.0, 0.0, 0.0, 0.0,
+ 0.5, 0.5, 0.0, 0.0,
+ 0.27777778, 0.44444444, 0.27777778, 0.0,
+ 0.17392742, 0.32607258, 0.32607258, 0.17392742 /
+begin
+ # Initialize.
+ profile = 0.0
+ dhdxc = 0.0
+ dhdyc = 0.0
+
+ # Compute the analytic part of the profile for a given x and y.
+
+ switch (ipstyp) {
+
+ # Evaluate the Gaussian function
+ # f = erfx * erfy / (par[1] * par[2])
+ # par[1] is the hwhm in x; sigma(x) = 0.8493218 * hwhm
+ # par[2] is the hwhm in y; sigma(y) = 0.8493218 * hwhm
+
+ case FCTN_GAUSS:
+
+ p1p2 = par[1] * par[2]
+ erfx = daoerf (dx, 0.0, par[1], dhdxc, dhdsx)
+ erfy = daoerf (dy, 0.0, par[2], dhdyc, dhdsy)
+ profile = erfx * erfy / p1p2
+ dhdxc = dhdxc * erfy / p1p2
+ dhdyc = dhdyc * erfx / p1p2
+ if (ideriv > 0) {
+ term[1] = (dhdsx - erfx / par[1]) * erfy / p1p2
+ term[2] = (dhdsy - erfy / par[2]) * erfx / p1p2
+ }
+
+ # Evaluate the Moffat25 function
+ #
+ # f = (beta - 1) / (ax * ay * (1 + (x/ax) ** 2 + (y/ay) ** 2 +
+ # (xy * axy)) ** beta)
+ #
+ # par[1] is the hwhm in x at y = 0.0
+ # 1/2 = 1 / (1 + (par[1] / ax) ** 2) ** beta
+ # so
+ # 2 ** (1/ beta) - 1 = (par[1] / ax) ** 2
+ # ax ** 2 = par[1] ** 2 / (2 ** (1 / beta) - 1)
+ #
+ # when beta = 2.5 ax ** 2 = 3.129813 * par[1] ** 2
+ #
+ # f = 1 / par[1] * par[2] * (1 + 0.3195079 * ((x / par[1]) ** 2 +
+ # (y / par[2]) ** 2 + xy * par[3])) ** 2.5
+ #
+
+ case FCTN_MOFFAT25:
+
+ alpha = 0.3195079
+ #talpha = 0.6390158
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ p1p2 = par[1] * par[2]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 4)
+
+ denom = 1.0 + alpha * (dx ** 2 / p1sq + dy ** 2 / p2sq + xy *
+ par[3])
+ if (denom > 1.0e4)
+ return (profile)
+ func = 1.0 / (p1p2 * denom ** par[4])
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = (par[4] - 1.0) * func
+ p4fod = par[4] * alpha * profile / denom
+ dhdxc = p4fod * (2.0 * dx / p1sq + dy * par[3])
+ dhdyc = p4fod * (2.0 * dy / p2sq + dx * par[3])
+ if (ideriv > 0) {
+ term[1] = (2.0 * p4fod * dx ** 2 / p1sq - profile) /
+ par[1]
+ term[2] = (2.0 * p4fod * dy ** 2 / p2sq - profile) /
+ par[2]
+ term[3] = - p4fod * xy
+ term[4] = profile * (1.0 / (par[4] - 1.0) - log (denom))
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ xsq[ix] = x[ix] ** 2
+ p1xsq[ix] = xsq[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ ysq = y ** 2
+ p2ysq = ysq / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ denom = 1.0 + alpha * (p1xsq[ix] + p2ysq + xy * par[3])
+ func = (par[4] - 1.0) / (p1p2 * denom ** par[4])
+ p4fod = par[4] * alpha * func / denom
+ wp4fod = wt * p4fod
+ wf = wt * func
+ profile = profile + wf
+ dhdxc = dhdxc + wp4fod * (2.0 * x[ix] / p1sq +
+ y * par[3])
+ dhdyc = dhdyc + wp4fod * (2. * y / p2sq + x[ix] *
+ par[3])
+ if (ideriv > 0) {
+ term[1] = term[1] + (2.0 * wp4fod * p1xsq[ix] - wf) /
+ par[1]
+ term[2] = term[2] + (2.0 * wp4fod * p2ysq - wf) /
+ par[2]
+ term[3] = term[3] - wp4fod * xy
+ term[4] = term[4] + wf * (1.0 / (par[4] - 1.0) -
+ log (denom))
+ }
+ }
+ }
+
+ #
+ # Penny function which has a gaussian core and lorentzian wings.
+ # The lorentzian is elongated along the x and y axes.
+
+ case FCTN_PENNY1:
+
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ onemp3 = 1.0 - par[3]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 4)
+
+ rsq = dx ** 2 / p1sq + dy ** 2 / p2sq
+ if (rsq > 1.0e10)
+ return (profile)
+
+ f = 1.0 / (1.0 + rsq)
+ rsq = rsq + xy * par[4]
+ if (rsq < 34.0) {
+ e = exp (-0.6931472 * rsq)
+ func = par[3] * e + onemp3 * f
+ } else {
+ e = 0.0
+ func = onemp3 * f
+ }
+
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = func
+ dfby = onemp3 * f ** 2
+ deby = 0.6931472 * par[3] * e
+ dbyx0 = 2.0 * dx / p1sq
+ dbyy0 = 2.0 * dy / p2sq
+ dhdxc = deby * (dbyx0 + dy * par[4]) + dfby * dbyx0
+ dhdyc = deby * (dbyy0 + dx * par[4]) + dfby * dbyy0
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ dfby = dfby + deby
+ term[1] = dfby * dbyx0
+ term[2] = dfby * dbyy0
+ term[3] = e - f
+ term[4] = - deby * xy / (0.5 - abs(par[4]))
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ p1xsq[ix] = x[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ p2ysq = y / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ rsq = p1xsq[ix] * x[ix] + p2ysq * y
+ f = 1.0 / (1.0 + rsq)
+ rsq = rsq + xy * par[4]
+ if (rsq < 34.0) {
+ e = exp (- 0.6931472 * rsq)
+ func = par[3] * e + onemp3 * f
+ deby = 0.6931472 * wt * par[3] * e
+ } else {
+ e = 0.0
+ func = onemp3 * f
+ deby = 0.0
+ }
+ profile = profile + wt * func
+ dfby = wt * onemp3 * f ** 2
+ dbyx0 = 2.0 * p1xsq[ix]
+ dbyy0 = 2.0 * p2ysq
+ dhdxc = dhdxc + deby * (dbyx0 + dy * par[4]) + dfby * dbyx0
+ dhdyc = dhdyc + deby * (dbyy0 + dx * par[4]) + dfby * dbyy0
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ term[1] = term[1] + (dfby + deby) * dbyx0
+ term[2] = term[2] + (dfby + deby) * dbyy0
+ term[3] = term[3] + wt * (e - f)
+ term[4] = term[4] - deby * xy
+ }
+ }
+ }
+
+ # Penny function which has a gaussian core and lorentzian wings.
+ # The gaussian and lorentzian may be tilted in different directions.
+
+ case FCTN_PENNY2:
+
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ onemp3 = 1.0 - par[3]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 5)
+
+ rsq = dx ** 2 / p1sq + dy ** 2 / p2sq
+ dfby = rsq + par[5] * xy
+ if (dfby > 1.0e10)
+ return (profile)
+ f = 1.0 / (1.0 + dfby)
+
+ deby = rsq + par[4] * xy
+ if (deby < 34.0)
+ e = exp (-0.6931472 * deby)
+ else
+ e = 0.0
+
+ func = par[3] * e + onemp3 * f
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = func
+ dfby = onemp3 * f ** 2
+ deby = 0.6931472 * par[3] * e
+ dbyx0 = 2.0 * dx / p1sq
+ dbyy0 = 2.0 * dy / p2sq
+ dhdxc = deby * (dbyx0 + dy * par[4]) + dfby * (dbyx0 + dy *
+ par[5])
+ dhdyc = deby * (dbyy0 + dx * par[4]) + dfby * (dbyy0 + dx *
+ par[5])
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ term[5] = -dfby * xy
+ dfby = dfby + deby
+ term[1] = dfby * dbyx0
+ term[2] = dfby * dbyy0
+ term[3] = e - f
+ term[4] = - deby * xy
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ p1xsq[ix] = x[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ p2ysq = y / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ rsq = p1xsq[ix] * x[ix] + p2ysq * y
+ f = 1.0 / (1.0 + rsq + par[5] * xy)
+ deby = rsq + par[4] * xy
+ if (deby < 34.0) {
+ e = exp (- 0.6931472 * deby)
+ func = par[3] * e + onemp3 * f
+ deby = 0.6931472 * wt * par[3] * e
+ } else {
+ e = 0.0
+ func = onemp3 * f
+ deby = 0.0
+ }
+ profile = profile + wt * func
+ dfby = wt * onemp3 * f ** 2
+ dbyx0 = 2.0 * p1xsq[ix]
+ dbyy0 = 2.0 * p2ysq
+ dhdxc = dhdxc + deby * (dbyx0 + dy * par[4]) + dfby *
+ (dbyx0 + dy * par[5])
+ dhdyc = dhdyc + deby * (dbyy0 + dx * par[4]) + dfby *
+ (dbyy0 + dx * par[5])
+ if (ideriv > 0) {
+ dbyx0 = dbyx0 * dx / par[1]
+ dbyy0 = dbyy0 * dy / par[2]
+ term[1] = term[1] + (dfby + deby) * dbyx0
+ term[2] = term[2] + (dfby + deby) * dbyy0
+ term[3] = term[3] + wt * (e - f)
+ term[4] = term[4] - deby * xy
+ term[5] = term[5] - dfby * xy
+ }
+ }
+ }
+
+ # Evaluate the Moffat15 function
+ #
+ # f = (beta - 1) / (ax * ay * (1 + (x/ax) ** 2 + (y/ay) ** 2 +
+ # (xy * axy)) ** beta)
+ #
+ # par[1] is the hwhm in x at y = 0.0
+ # 1/2 = 1 / (1 + (par[1] / ax) ** 2) ** beta
+ # so
+ # 2 ** (1/ beta) - 1 = (par[1] / ax) ** 2
+ # ax ** 2 = par[1] ** 2 / (2 ** (1 / beta) - 1)
+ #
+ # when beta = 1.5 ax ** 2 = 1.7024144 * par[1] ** 2
+ #
+ # f = 1 / par[1] * par[2] * (1 + 0.5874011 * ((x / par[1]) ** 2 +
+ # (y / par[2]) ** 2 + xy * par[3])) ** 2.5
+ #
+
+ case FCTN_MOFFAT15:
+
+ alpha = 0.5874011
+ #talpha = 1.1748021
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ p1p2 = par[1] * par[2]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 4)
+
+ denom = 1.0 + alpha * (dx ** 2 / p1sq + dy ** 2 / p2sq + xy *
+ par[3])
+ if (denom > 5.0e6)
+ return (profile)
+ func = 1.0 / (p1p2 * denom ** par[4])
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = (par[4] - 1.0) * func
+ p4fod = par[4] * alpha * profile / denom
+ dhdxc = p4fod * (2.0 * dx / p1sq + dy * par[3])
+ dhdyc = p4fod * (2.0 * dy / p2sq + dx * par[3])
+ if (ideriv > 0) {
+ term[1] = (2.0 * p4fod * dx ** 2 / p1sq - profile) /
+ par[1]
+ term[2] = (2.0 * p4fod * dy ** 2 / p2sq - profile) /
+ par[2]
+ term[3] = - p4fod * xy
+ term[4] = profile * (1.0 / (par[4] - 1.0) - log (denom))
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ xsq[ix] = x[ix] ** 2
+ p1xsq[ix] = xsq[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ ysq = y ** 2
+ p2ysq = ysq / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ denom = 1.0 + alpha * (p1xsq[ix] + p2ysq + xy *
+ par[3])
+ func = (par[4] - 1.0) / (p1p2 * denom ** par[4])
+ p4fod = par[4] * alpha * func / denom
+ wp4fod = wt * p4fod
+ wf = wt * func
+ profile = profile + wf
+ dhdxc = dhdxc + wp4fod * (2.0 * x[ix] / p1sq + y *
+ par[3])
+ dhdyc = dhdyc + wp4fod * (2. * y / p2sq + x[ix] *
+ par[3])
+ if (ideriv > 0) {
+ term[1] = term[1] + (2.0 * wp4fod * p1xsq[ix] - wf) /
+ par[1]
+ term[2] = term[2] + (2.0 * wp4fod * p2ysq - wf) /
+ par[2]
+ term[3] = term[3] - wp4fod * xy
+ term[4] = term[4] + wf * (1.0 / (par[4] - 1.0) -
+ log (denom))
+ }
+ }
+ }
+
+ case FCTN_LORENTZ:
+
+ p1sq = par[1] ** 2
+ p2sq = par[2] ** 2
+ p1p2 = par[1] * par[2]
+ xy = dx * dy
+ if (ideriv > 0)
+ call aclrr (term, 3)
+
+ denom = 1.0 + dx ** 2 / p1sq + dy ** 2 / p2sq + xy * par[3]
+ if (denom > 1.0e10)
+ return (profile)
+ func = 1.0 / denom
+ if (func >= 0.046) {
+ npt = 4
+ } else if (func >= 0.0022) {
+ npt = 3
+ } else if (func >= 0.0001) {
+ npt = 2
+ } else if (func >= 1.0e-10) {
+ profile = func
+ wfsq = func ** 2
+ dhdxc = wfsq * (2.0 * dx / p1sq + dy * par[3])
+ dhdyc = wfsq * (2.0 * dy / p2sq + dx * par[3])
+ if (ideriv > 0) {
+ term[1] = wfsq * (2.0 * dx ** 2 / p1sq) / par[1]
+ term[2] = wfsq * (2.0 * dy ** 2 / p2sq) / par[2]
+ term[3] = - wfsq * xy
+ }
+ return (profile)
+ } else {
+ return (profile)
+ }
+
+ do ix = 1, npt {
+ x[ix] = dx + d[ix,npt]
+ xsq[ix] = x[ix] ** 2
+ p1xsq[ix] = xsq[ix] / p1sq
+ }
+
+ do iy = 1, npt {
+ y = dy + d[iy,npt]
+ ysq = y ** 2
+ p2ysq = ysq / p2sq
+ do ix = 1, npt {
+ wt = w[iy,npt] * w[ix,npt]
+ xy = x[ix] * y
+ denom = 1.0 + p1xsq[ix] + p2ysq + xy * par[3]
+ func = 1.0 / denom
+ wf = wt * func
+ wfsq = wf * func
+ profile = profile + wf
+ dhdxc = dhdxc + wfsq * (2.0 * x[ix] / p1sq + y * par[3])
+ dhdyc = dhdyc + wfsq * (2.0 * y / p2sq + x[ix] * par[3])
+ if (ideriv > 0) {
+ term[1] = term[1] + wfsq * (2.0 * p1xsq[ix]) / par[1]
+ term[2] = term[2] + wfsq * (2.0 * p2ysq) / par[2]
+ term[3] = term[3] - wfsq * xy
+ }
+ }
+ }
+
+ default:
+ profile = INDEFR
+ }
+
+ return (profile)
+end