aboutsummaryrefslogtreecommitdiff
path: root/noao/obsutil/src/starfocus/t_starfocus.x
diff options
context:
space:
mode:
Diffstat (limited to 'noao/obsutil/src/starfocus/t_starfocus.x')
-rw-r--r--noao/obsutil/src/starfocus/t_starfocus.x1240
1 files changed, 1240 insertions, 0 deletions
diff --git a/noao/obsutil/src/starfocus/t_starfocus.x b/noao/obsutil/src/starfocus/t_starfocus.x
new file mode 100644
index 00000000..2c3213e9
--- /dev/null
+++ b/noao/obsutil/src/starfocus/t_starfocus.x
@@ -0,0 +1,1240 @@
+include <error.h>
+include <imhdr.h>
+include <imset.h>
+include <mach.h>
+include "starfocus.h"
+
+define HELP "nmisc$src/starfocus.key"
+define PROMPT "Options"
+
+
+# T_STARFOCUS -- Stellar focusing task.
+
+procedure t_starfocus ()
+
+begin
+ call starfocus (STARFOCUS)
+end
+
+
+# T_PSFMEASURE -- PSF measuring task.
+
+procedure t_psfmeasure ()
+
+begin
+ call starfocus (PSFMEASURE)
+end
+
+
+# STARFOCUS -- Stellar focusing and PSF measuring main routine.
+
+procedure starfocus (type)
+
+int type #I Task type
+
+int list # List of images
+pointer fvals # Focus values
+pointer fstep # Focus step
+pointer nexposures # Number of exposures
+pointer step # step in pixels
+int direction # Step direction
+int gap # Double step gap
+int coords # Type of image data
+bool display # Display images?
+int frame # Display frame
+int logfd # Log file descriptor
+bool ignore_sat # Ignore saturation?
+
+real wx, wy, f, df, xstep, ystep
+int i, i1, i2, i3, j, k, l, ip, wcs, key, id, ncols, nlines
+int nexp, nsfd, nimages, nstars, ngraph, nmark
+pointer sp, sf, image, system, cmd, rg, mark, im, mw, ct
+pointer sfds, sfd
+
+bool clgetb(), streq()
+real clgetr(), imgetr(), stf_r2i()
+int clgeti(), clgwrd(), clgcur(), imtopenp(), imtgetim(), imgeti()
+int nowhite(), open(), rng_index(), strdic(), ctoi(), ctor()
+pointer rng_open(), immap(), mw_openim(), mw_sctran()
+errchk immap, open, imgetr, imgeti, mw_openim, mw_sctran
+errchk stf_find, stf_bkgd, stf_profile, stf_widths, stf_fwhms, stf_radius
+errchk stf_organize, stf_graph, stf_display
+
+begin
+ call smark (sp)
+ call salloc (sf, SF, TY_STRUCT)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (fvals, SZ_LINE, TY_CHAR)
+ call salloc (fstep, SZ_LINE, TY_CHAR)
+ call salloc (nexposures, SZ_LINE, TY_CHAR)
+ call salloc (step, SZ_LINE, TY_CHAR)
+ call salloc (system, SZ_LINE, TY_CHAR)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+
+ call aclri (Memi[sf], SF)
+ SF_TASK(sf) = type
+
+ # Set task parameters.
+ switch (type) {
+ case STARFOCUS:
+ call clgstr ("focus", Memc[fvals], SZ_LINE)
+ call clgstr ("fstep", Memc[fstep], SZ_LINE)
+ call clgstr ("nexposures", Memc[nexposures], SZ_LINE)
+ call clgstr ("step", Memc[step], SZ_LINE)
+
+ direction = clgwrd ("direction", Memc[cmd], SZ_LINE,
+ "|-line|+line+|-column|+column|")
+ gap = clgwrd ("gap", Memc[cmd], SZ_LINE, "|none|beginning|end|")
+
+ if (nowhite (Memc[fvals], Memc[fvals], SZ_LINE) != 0) {
+ iferr (rg = rng_open (Memc[fvals], -MAX_REAL, MAX_REAL, 1.))
+ rg = NULL
+ } else
+ rg = NULL
+ case PSFMEASURE:
+ Memc[fvals] = EOS
+ rg = NULL
+ nexp = 1
+ }
+
+ list = imtopenp ("images")
+ display = clgetb ("display")
+ frame = clgeti ("frame")
+ coords = clgwrd ("coords", Memc[cmd], SZ_LINE, SF_TYPES)
+ call clgstr ("wcs", Memc[system], SZ_LINE)
+
+ SF_XF(sf) = clgetr ("xcenter")
+ SF_YF(sf) = clgetr ("ycenter")
+ SF_LEVEL(sf) = clgetr ("level")
+ SF_WCODE(sf) = clgwrd ("size", SF_WTYPE(sf), SF_SZWTYPE, SF_WTYPES)
+ SF_BETA(sf) = clgetr ("beta")
+ SF_SCALE(sf) = clgetr ("scale")
+ SF_RADIUS(sf) = max (3., clgetr ("radius"))
+ SF_NIT(sf) = clgeti ("iterations")
+ SF_SBUF(sf) = clgetr ("sbuffer")
+ SF_SWIDTH(sf) = clgetr ("swidth")
+ SF_SAT(sf) = clgetr ("saturation")
+ ignore_sat = clgetb ("ignore_sat")
+ SF_OVRPLT(sf) = NO
+
+ if (SF_LEVEL(sf) > 1.)
+ SF_LEVEL(sf) = SF_LEVEL(sf) / 100.
+ SF_LEVEL(sf) = max (0.05, min (0.95, SF_LEVEL(sf)))
+
+ # Accumulate the psf/focus data.
+ key = 'm'
+ mark = NULL
+ nstars = 0
+ nmark = 0
+ ngraph = 0
+ nimages = 0
+ nsfd = 0
+ while (imtgetim (list, Memc[image], SZ_FNAME) != EOF) {
+ im = immap (Memc[image], READ_ONLY, 0)
+ call imseti (im, IM_TYBNDRY, TYBNDRY)
+ call imseti (im, IM_NBNDRYPIX, NBNDRYPIX)
+ if (streq (Memc[system], "logical")) {
+ mw = NULL
+ ct = NULL
+ } else {
+ mw = mw_openim (im)
+ ct = mw_sctran (mw, Memc[system], "logical", 03)
+ }
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ nimages = nimages + 1
+ if (nimages == 1) {
+ SF_NCOLS(sf) = ncols
+ SF_NLINES(sf) = nlines
+ if (IS_INDEF(SF_XF(sf)))
+ SF_XF(sf) = (SF_NCOLS(sf) + 1) / 2.
+ if (IS_INDEF(SF_YF(sf)))
+ SF_YF(sf) = (SF_NLINES(sf) + 1) / 2.
+ } else if (ncols!=SF_NCOLS(sf)||nlines!=SF_NLINES(sf))
+ call eprintf ("WARNING: Images have different sizes\n")
+
+ # Display the image if needed.
+ if (display) {
+ switch (coords) {
+ case SF_MARK1:
+ if (nimages == 1)
+ call stf_display (Memc[image], frame)
+ case SF_MARKALL:
+ call stf_display (Memc[image], frame)
+ }
+ if (nimages == 1) {
+ call printf (
+ "** Select stars to measure with 'm' and finish with 'q'.\n")
+ call printf (
+ "** Additional options are '?', 'g', and :show.\n")
+ call flush (STDOUT)
+ }
+ }
+
+ # Accumulate objects.
+ repeat {
+ switch (coords) {
+ case SF_CENTER:
+ if (nstars == nimages)
+ break
+ if (rg == NULL && Memc[fvals] == EOS)
+ id = nstars
+ else
+ id = 0
+ wx = 1 + (ncols - 1) / 2.
+ wy = 1 + (nlines - 1) / 2.
+ key = 0
+ case SF_MARK1:
+ if (nimages == 1) {
+ if (clgcur ("imagecur", wx, wy, wcs, key,
+ Memc[cmd], SZ_LINE) == EOF)
+ break
+ switch (key) {
+ case '?':
+ call pagefile (HELP, PROMPT)
+ next
+ case ':':
+ if (strdic (Memc[cmd], Memc[cmd], SZ_LINE,
+ "|show|") == 1) {
+ if (nsfd > 0) {
+ call stf_organize (sf, sfds, nsfd)
+ call mktemp ("tmp$iraf", Memc[cmd], SZ_LINE)
+ logfd = open (Memc[cmd], APPEND, TEXT_FILE)
+ call stf_log (sf, logfd)
+ call close (logfd)
+ call pagefile (Memc[cmd], "starfocus")
+ call delete (Memc[cmd])
+ }
+ }
+ next
+ case 'q':
+ break
+ }
+ id = nstars
+ if (mark == NULL)
+ call malloc (mark, 3*10, TY_REAL)
+ else if (mod (nmark, 10) == 0)
+ call realloc (mark, 3*(nmark+10), TY_REAL)
+ Memr[mark+3*nmark] = id
+ Memr[mark+3*nmark+1] = wx
+ Memr[mark+3*nmark+2] = wy
+ nmark = nmark+1
+ } else {
+ if (nmark == 0)
+ break
+ if (nstars / nmark == nimages)
+ break
+ i = mod (nstars, nmark)
+ id = Memr[mark+3*i]
+ wx = Memr[mark+3*i+1]
+ wy = Memr[mark+3*i+2]
+ key = 0
+ }
+ if (ct != NULL)
+ call mw_c2tranr (ct, wx, wy, wx, wy)
+ case SF_MARKALL:
+ if (clgcur ("imagecur", wx, wy, wcs, key,
+ Memc[cmd], SZ_LINE) == EOF)
+ break
+ switch (key) {
+ case '?':
+ call pagefile (HELP, PROMPT)
+ next
+ case ':':
+ if (strdic(Memc[cmd],Memc[cmd],SZ_LINE,"|show|")==1) {
+ if (nsfd > 0) {
+ call stf_organize (sf, sfds, nsfd)
+ call mktemp ("tmp$iraf", Memc[cmd], SZ_LINE)
+ logfd = open (Memc[cmd], APPEND, TEXT_FILE)
+ call stf_log (sf, logfd)
+ call close (logfd)
+ call pagefile (Memc[cmd], "starfocus")
+ call delete (Memc[cmd])
+ }
+ }
+ next
+ case 'q':
+ break
+ }
+ id = nstars
+ if (ct != NULL)
+ call mw_c2tranr (ct, wx, wy, wx, wy)
+ }
+
+ if (type == STARFOCUS) {
+ ip = 1
+ if (ctoi (Memc[nexposures], ip, nexp) == 0)
+ nexp = imgeti (im, Memc[nexposures])
+ ip = 1
+ if (ctor (Memc[step], ip, f) == 0)
+ f = imgetr (im, Memc[step])
+
+ xstep = 0.
+ ystep = 0.
+ switch (direction) {
+ case 1:
+ ystep = -f
+ case 2:
+ ystep = f
+ case 3:
+ xstep = -f
+ case 4:
+ xstep = f
+ }
+
+ # Set the steps and order of evaluation.
+ # This depends on which star in the sequence is marked.
+ # Below we assume the minimum x or maximum y is marked.
+
+ i1 = 1; i2 = nexp; i3 = 1
+# if (xstep < 0.) {
+# i1 = nexp; i2 = 1; i3 = -1; xstep = -xstep
+# }
+# if (ystep > 0.) {
+# i1 = nexp; i2 = 1; i3 = -1; ystep = -ystep
+# }
+ } else {
+ i1 = 1; i2 = 1; i3 = 1
+ }
+
+ k = nsfd
+ do i = i1, i2, i3 {
+ if (i > 1) {
+ wx = wx + xstep
+ wy = wy + ystep
+ switch (gap) {
+ case 2:
+ if ((i==2 && i3==1) || (i==1 && i3==-1)) {
+ wx = wx + xstep
+ wy = wy + ystep
+ }
+ case 3:
+ if ((i==nexp && i3==1) || (i==nexp-1 && i3==-1)) {
+ wx = wx + xstep
+ wy = wy + ystep
+ }
+ }
+ }
+
+ if (wx < SF_RADIUS(sf)-NBNDRYPIX ||
+ wx > IM_LEN(im,1)-SF_RADIUS(sf)+NBNDRYPIX ||
+ wy < SF_RADIUS(sf)-NBNDRYPIX ||
+ wy > IM_LEN(im,2)-SF_RADIUS(sf)+NBNDRYPIX)
+ next
+ if (nexp == 1)
+ j = nimages
+ else
+ j = i
+ if (nsfd == 0)
+ call malloc (sfds, 10, TY_POINTER)
+ else if (mod (nsfd, 10) == 0)
+ call realloc (sfds, nsfd+10, TY_POINTER)
+ call malloc (sfd, SFD, TY_STRUCT)
+ call strcpy (Memc[image], SFD_IMAGE(sfd), SF_SZFNAME)
+ SFD_ID(sfd) = id
+ SFD_X(sfd) = wx
+ SFD_Y(sfd) = wy
+ if (Memc[fvals] == EOS)
+ f = INDEF
+ else if (Memc[fstep] != EOS) {
+ ip = 1
+ if (ctor (Memc[fvals], ip, f) == 0)
+ f = imgetr (im, Memc[fvals])
+ ip = 1
+ if (ctor (Memc[fstep], ip, df) == 0)
+ df = imgetr (im, Memc[fstep])
+ f = f + (i - 1) * df
+ } else if (rg != NULL) {
+ if (rng_index (rg, j, f) == EOF)
+ call error (1, "Focus list ended prematurely")
+ } else
+ f = imgetr (im, Memc[fvals])
+ SFD_F(sfd) = f
+ SFD_STATUS(sfd) = 0
+ SFD_SFS(sfd) = NULL
+ SFD_SFF(sfd) = NULL
+ SFD_SFI(sfd) = NULL
+
+ iferr {
+ do l = 1, SF_NIT(sf) {
+ if (l == 1)
+ SFD_RADIUS(sfd) = max (3., SF_RADIUS(sf))
+ else
+ SFD_RADIUS(sfd) = max (3., 3. * SFD_DFWHM(sfd))
+ SFD_NPMAX(sfd) = stf_r2i (SFD_RADIUS(sfd)) + 1
+ SFD_NP(sfd) = SFD_NPMAX(sfd)
+ call stf_find (sf, sfd, im)
+ call stf_bkgd (sf, sfd)
+ if (SFD_NSAT(sfd) > 0 && l == 1) {
+ if (ignore_sat)
+ call error (0,
+ "Saturated pixels found - ignoring object")
+ else
+ call eprintf (
+ "WARNING: Saturated pixels found.\n")
+ }
+ call stf_profile (sf, sfd)
+ call stf_widths (sf, sfd)
+ call stf_fwhms (sf, sfd)
+ }
+ Memi[sfds+nsfd] = sfd
+ nsfd = nsfd + 1
+ wx = SFD_X(sfd)
+ wy = SFD_Y(sfd)
+ } then {
+ call erract (EA_WARN)
+ call mfree (sfd, TY_STRUCT)
+ }
+ }
+ if (nsfd > k) {
+ nstars = nstars + 1
+ if (key == 'g') {
+ if (nsfd - k > 0) {
+ call stf_organize (sf, sfds+k, nsfd-k)
+ call stf_graph (sf)
+ ngraph = ngraph + 1
+ }
+ }
+ }
+ }
+ if (mw != NULL)
+ call mw_close (mw)
+ call imunmap (im)
+ }
+
+ if (nsfd == 0)
+ call error (1, "No input data")
+
+ # Organize the objects, graph the data, and log the results.
+ if (nstars > 1 || ngraph != nstars) {
+ call stf_organize (sf, sfds, nsfd)
+ call stf_graph (sf)
+ }
+ call stf_log (sf, STDOUT)
+ call clgstr ("logfile", Memc[image], SZ_FNAME)
+ ifnoerr (logfd = open (Memc[image], APPEND, TEXT_FILE)) {
+ call stf_log (sf, logfd)
+ call close (logfd)
+ }
+
+ # Finish up
+ call rng_close (rg)
+ call imtclose (list)
+ call stf_free (sf)
+ do i = 1, SF_NSFD(sf) {
+ sfd = SF_SFD(sf,i)
+ call asifree (SFD_ASI1(sfd))
+ call asifree (SFD_ASI2(sfd))
+ call mfree (sfd, TY_STRUCT)
+ }
+ call mfree (SF_SFDS(sf), TY_POINTER)
+ call mfree (mark, TY_REAL)
+ call sfree (sp)
+end
+
+
+# STF_FREE -- Free the starfocus data structures.
+
+procedure stf_free (sf)
+
+pointer sf #I Starfocus structure
+int i
+
+begin
+ do i = 1, SF_NSTARS(sf)
+ call mfree (SF_SFS(sf,i), TY_STRUCT)
+ do i = 1, SF_NFOCUS(sf)
+ call mfree (SF_SFF(sf,i), TY_STRUCT)
+ do i = 1, SF_NIMAGES(sf)
+ call mfree (SF_SFI(sf,i), TY_STRUCT)
+ call mfree (SF_STARS(sf), TY_POINTER)
+ call mfree (SF_FOCUS(sf), TY_POINTER)
+ call mfree (SF_IMAGES(sf), TY_POINTER)
+ SF_NSTARS(sf) = 0
+ SF_NFOCUS(sf) = 0
+ SF_NIMAGES(sf) = 0
+end
+
+
+# STF_ORGANIZE -- Organize the individual object structures by star, focus,
+# and image. Compute focus, radius, and magnitude by group and over all
+# data.
+
+procedure stf_organize (sf, sfds, nsfd)
+
+pointer sf #I Starfocus structure
+pointer sfds #I Pointer to array of object structures
+int nsfd #I Number of object structures
+
+int i, j, k, nstars, nfocus, nimages, key
+real f
+pointer stars, focus, images, sfd, sfs, sff, sfi
+pointer sp, image
+bool streq()
+errchk malloc
+
+int stf_focsort(), stf_magsort()
+extern stf_focsort, stf_magsort
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+
+ # Free previous structures.
+ call stf_free (sf)
+
+ # Organize sfds by star.
+ nstars = 0
+ for (i = 0; i < nsfd; i = i + 1) {
+ key = SFD_ID(Memi[sfds+i])
+ for (j = 0; SFD_ID(Memi[sfds+j]) != key; j = j + 1)
+ ;
+ if (j == i)
+ nstars = nstars + 1
+ }
+ call malloc (stars, nstars, TY_POINTER)
+
+ nstars = 0
+ for (i = 0; i < nsfd; i = i + 1) {
+ key = SFD_ID(Memi[sfds+i])
+ for (j = 0; j < nstars; j = j + 1)
+ if (SFS_ID(Memi[stars+j]) == key)
+ break
+ if (j == nstars) {
+ k = 0
+ for (j = i; j < nsfd; j = j + 1)
+ if (SFD_ID(Memi[sfds+j]) == key)
+ k = k + 1
+ call malloc (sfs, SFS(k), TY_STRUCT)
+ SFS_ID(sfs) = key
+ SFS_NSFD(sfs) = k
+ k = 0
+ for (j = i; j < nsfd; j = j + 1) {
+ sfd = Memi[sfds+j]
+ if (SFD_ID(sfd) == key) {
+ k = k + 1
+ SFD_SFS(sfd) = sfs
+ SFS_SFD(sfs,k) = sfd
+ }
+ }
+ Memi[stars+nstars] = sfs
+ nstars = nstars + 1
+ }
+ }
+
+ # Organize sfds by focus values. Sort by magnitude.
+ nfocus = 0
+ for (i = 0; i < nsfd; i = i + 1) {
+ f = SFD_F(Memi[sfds+i])
+ for (j = 0; SFD_F(Memi[sfds+j]) != f; j = j + 1)
+ ;
+ if (j == i)
+ nfocus = nfocus + 1
+ }
+ call malloc (focus, nfocus, TY_POINTER)
+
+ nfocus = 0
+ for (i = 0; i < nsfd; i = i + 1) {
+ f = SFD_F(Memi[sfds+i])
+ for (j = 0; j < nfocus; j = j + 1)
+ if (SFF_F(Memi[focus+j]) == f)
+ break
+ if (j == nfocus) {
+ k = 0
+ for (j = i; j < nsfd; j = j + 1)
+ if (SFD_F(Memi[sfds+j]) == f)
+ k = k + 1
+ call malloc (sff, SFF(k), TY_STRUCT)
+ SFF_F(sff) = f
+ SFF_NSFD(sff) = k
+ k = 0
+ for (j = i; j < nsfd; j = j + 1) {
+ sfd = Memi[sfds+j]
+ if (SFD_F(sfd) == f) {
+ k = k + 1
+ SFD_SFF(sfd) = sff
+ SFF_SFD(sff,k) = sfd
+ }
+ }
+ Memi[focus+nfocus] = sff
+ nfocus = nfocus + 1
+ }
+ }
+
+ # Organize sfds by image.
+ nimages = 0
+ for (i = 0; i < nsfd; i = i + 1) {
+ call strcpy (SFD_IMAGE(Memi[sfds+i]), Memc[image], SZ_FNAME)
+ for (j = 0; !streq (SFD_IMAGE(Memi[sfds+j]), Memc[image]); j = j+1)
+ ;
+ if (j == i)
+ nimages = nimages + 1
+ }
+ call malloc (images, nimages, TY_POINTER)
+
+ nimages = 0
+ for (i = 0; i < nsfd; i = i + 1) {
+ call strcpy (SFD_IMAGE(Memi[sfds+i]), Memc[image], SZ_FNAME)
+ for (j = 0; j < nimages; j = j + 1)
+ if (streq (SFI_IMAGE(Memi[images+j]), Memc[image]))
+ break
+ if (j == nimages) {
+ k = 0
+ for (j = i; j < nsfd; j = j + 1)
+ if (streq (SFD_IMAGE(Memi[sfds+j]), Memc[image]))
+ k = k + 1
+ call malloc (sfi, SFI(k), TY_STRUCT)
+ call strcpy (Memc[image], SFI_IMAGE(sfi), SF_SZFNAME)
+ SFI_NSFD(sfi) = k
+ k = 0
+ for (j = i; j < nsfd; j = j + 1) {
+ sfd = Memi[sfds+j]
+ if (streq (SFD_IMAGE(sfd), Memc[image])) {
+ k = k + 1
+ SFD_SFI(sfd) = sfi
+ SFI_SFD(sfi,k) = sfd
+ }
+ }
+ Memi[images+nimages] = sfi
+ nimages = nimages + 1
+ }
+ }
+
+ SF_NSFD(sf) = nsfd
+ SF_SFDS(sf) = sfds
+ SF_NSTARS(sf) = nstars
+ SF_STARS(sf) = stars
+ SF_NFOCUS(sf) = nfocus
+ SF_FOCUS(sf) = focus
+ SF_NIMAGES(sf) = nimages
+ SF_IMAGES(sf) = images
+
+ # Find the average and best focus values. Sort the focus groups
+ # by magnitude and the star groups by focus.
+
+ call stf_fitfocus (sf)
+ do i = 1, SF_NFOCUS(sf) {
+ sff = SF_SFF(sf,i)
+ call qsort (SFF_SFD(sff,1), SFF_NSFD(sff), stf_magsort)
+ }
+ do i = 1, SF_NSTARS(sf) {
+ sfs = SF_SFS(sf,i)
+ call qsort (SFS_SFD(sfs,1), SFS_NSFD(sfs), stf_focsort)
+ }
+
+ call sfree (sp)
+end
+
+
+# STF_LOG -- Print log of results
+
+procedure stf_log (sf, fd)
+
+pointer sf #I Main data structure
+int fd #I File descriptor
+
+int i, j, n
+pointer sp, str, sfd, sfs, sff, sfi
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print banner and overall result.
+ call sysid (Memc[str], SZ_LINE)
+ call fprintf (fd, "%s\n\n")
+ call pargstr (Memc[str])
+
+ # Print each individual object organized by image.
+ call fprintf (fd, "%15.15s %7s %7s %7s")
+ call pargstr ("Image")
+ call pargstr ("Column")
+ call pargstr ("Line")
+ call pargstr ("Mag")
+ if (IS_INDEF(SF_F(sf))) {
+ call fprintf (fd, " %7s")
+ call pargstr (SF_WTYPE(sf))
+ } else {
+ call fprintf (fd, " %7s %7s")
+ call pargstr ("Focus")
+ call pargstr (SF_WTYPE(sf))
+ }
+ if (SF_WCODE(sf) == 4) {
+ call fprintf (fd, " %4s")
+ call pargstr ("Beta")
+ }
+ call fprintf (fd, " %7s %7s %3s\n")
+ call pargstr ("Ellip")
+ call pargstr ("PA")
+ call pargstr ("SAT")
+
+ do i = 1, SF_NIMAGES(sf) {
+ sfi = SF_SFI(sf,i)
+ n = 0
+ do j = 1, SFI_NSFD(sfi) {
+ sfd = SFI_SFD(sfi,j)
+ if (SFD_STATUS(sfd) != 0)
+ next
+ if (n == 0) {
+ call fprintf (fd, "%15.15s")
+ call pargstr (SFD_IMAGE(sfd))
+ } else
+ call fprintf (fd, "%15w")
+ call fprintf (fd, " %7.2f %7.2f %7.2f")
+ call pargr (SFD_X(sfd))
+ call pargr (SFD_Y(sfd))
+ call pargr (-2.5*log10 (SFD_M(sfd) / SF_M(sf)))
+ if (IS_INDEF(SFD_F(sfd))) {
+ call fprintf (fd,
+ " %7.3f")
+ call pargr (SFD_W(sfd))
+ } else {
+ call fprintf (fd, " %7.6g %7.3f")
+ call pargr (SFD_F(sfd))
+ call pargr (SFD_W(sfd))
+ }
+ if (SF_WCODE(sf) == 4) {
+ call fprintf (fd, " %4.1f")
+ call pargr (SFD_BETA(sfd))
+ }
+ call fprintf (fd, " %7.2f %7d")
+ call pargr (SFD_E(sfd))
+ call pargr (SFD_PA(sfd))
+ if (SFD_NSAT(sfd) == 0)
+ call fprintf (fd, "\n")
+ else
+ call fprintf (fd, " *\n")
+ n = n + 1
+ }
+ }
+ if (n > 0)
+ call fprintf (fd, "\n")
+
+ # Print best values by star.
+ if (SF_NS(sf) > 1) {
+ n = 0
+ do i = 1, SF_NSTARS(sf) {
+ sfs = SF_SFS(sf,i)
+ if (SFS_NF(sfs) > 1 || SFS_N(sfs) > 1) {
+ call stf_title (sf, NULL, sfs, NULL, Memc[str], SZ_LINE)
+ call fprintf (fd, " %s\n")
+ call pargstr (Memc[str])
+ n = n + 1
+ }
+ }
+ if (n > 0)
+ call fprintf (fd, "\n")
+ }
+
+ # Print averages at each focus.
+ if (SF_NF(sf) > 1) {
+ n = 0
+ do i = 1, SF_NFOCUS(sf) {
+ sff = SF_SFF(sf,i)
+ if (SFF_N(sff) > 1) {
+ call stf_title (sf, NULL, NULL, sff, Memc[str], SZ_LINE)
+ call fprintf (fd, " %s\n")
+ call pargstr (Memc[str])
+ n = n + 1
+ }
+ }
+ if (n > 0)
+ call fprintf (fd, "\n")
+ }
+
+ call stf_title (sf, NULL, NULL, NULL, Memc[str], SZ_LINE)
+ call fprintf (fd, "%s\n")
+ call pargstr (Memc[str])
+end
+
+
+# STF_TITLE -- Return result title string.
+# The title is dependent on whether an overall title, a title for a star
+# group, for a focus group, or for an indivdual object is desired.
+# The title also is adjusted for the select size type and the number
+# of objects in a group.
+
+procedure stf_title (sf, sfd, sfs, sff, title, sz_title)
+
+pointer sf #I Starfocus pointer
+pointer sfd #I Data pointer
+pointer sfs #I Star pointer
+pointer sff #I Focus pointer
+char title[sz_title] #O Title string
+int sz_title #I Size of title string
+
+pointer ptr
+int i, fd, stropen()
+errchk stropen
+
+begin
+ fd = stropen (title, sz_title, WRITE_ONLY)
+
+ if (sfd != NULL) {
+ call fprintf (fd, "%s @ (%.2f, %.2f):")
+ call pargstr (SFD_IMAGE(sfd))
+ call pargr (SFD_X(sfd))
+ call pargr (SFD_Y(sfd))
+ switch (SF_WCODE(sf)) {
+ case 4:
+ call fprintf (fd, " %s=%.2f (%3.1f), e=%.2f, pa=%d")
+ call pargstr (SF_WTYPE(sf))
+ call pargr (SFD_W(sfd))
+ call pargr (SFD_BETA(sfd))
+ call pargr (SFD_E(sfd))
+ call pargr (SFD_PA(sfd))
+ default:
+ call fprintf (fd, " %s=%.2f, e=%.2f, pa=%d")
+ call pargstr (SF_WTYPE(sf))
+ call pargr (SFD_W(sfd))
+ call pargr (SFD_E(sfd))
+ call pargr (SFD_PA(sfd))
+ }
+ if (SFD_SFS(sfd) != NULL) {
+ if (SFS_M(SFD_SFS(sfd)) != SF_M(sf)) {
+ call fprintf (fd, " , m=%.2f")
+ call pargr (-2.5*log10 (SFS_M(SFD_SFS(sfd)) / SF_M(sf)))
+ }
+ }
+ if (!IS_INDEF(SFD_F(sfd))) {
+ call fprintf (fd, ", f=%.4g")
+ call pargr (SFD_F(sfd))
+ }
+ } else if (sfs != NULL) {
+ ptr = SFS_SFD(sfs,1)
+ call fprintf (fd, "%s")
+ if (SFS_NF(sfs) > 1)
+ call pargstr ("Best focus estimate")
+ else if (SFS_N(sfs) > 1)
+ call pargstr ("Average star")
+ else {
+ for (i=1; SFD_STATUS(SFS_SFD(sfs,i))!=0; i=i+1)
+ ;
+ call pargstr (SFD_IMAGE(SFS_SFD(sfs,i)))
+ }
+ call fprintf (fd, " @ (%.2f, %.2f): %s=%.2f")
+ call pargr (SFD_X(ptr))
+ call pargr (SFD_Y(ptr))
+ call pargstr (SF_WTYPE(sf))
+ call pargr (SFS_W(sfs))
+ #if (SFS_M(sfs) != SF_M(sf)) {
+ call fprintf (fd, ", m=%.2f")
+ call pargr (-2.5 * log10 (SFS_M(sfs) / SF_M(sf)))
+ #}
+ if (!IS_INDEF(SFS_F(sfs))) {
+ call fprintf (fd, ", f=%.4g")
+ call pargr (SFS_F(sfs))
+ }
+ } else if (sff != NULL) {
+ if (SFF_NI(sff) == 1) {
+ for (i=1; SFD_STATUS(SFF_SFD(sff,i))!=0; i=i+1)
+ ;
+ call fprintf (fd, "%s")
+ call pargstr (SFD_IMAGE(SFF_SFD(sff,i)))
+ if (!IS_INDEF(SFF_F(sff))) {
+ call fprintf (fd, " at focus %.4g")
+ call pargr (SFF_F(sff))
+ }
+ call fprintf (fd, " with average")
+ } else {
+ if (IS_INDEF(SFF_F(sff)))
+ call fprintf (fd, "Average")
+ else {
+ call fprintf (fd, "Focus %.4g with average")
+ call pargr (SFF_F(sff))
+ }
+ }
+ call fprintf (fd, " %s of %.2f")
+ call pargstr (SF_WTYPE(sf))
+ call pargr (SFF_W(sff))
+ } else {
+ if (IS_INDEF(SF_F(sf))) {
+ if (SF_WCODE(sf) == 1) {
+ call fprintf (fd, " %s%d%% enclosed flux radius of ")
+ if (SF_N(sf) > 1)
+ call pargstr ("Average ")
+ else
+ call pargstr ("")
+ call pargr (100 * SF_LEVEL(sf))
+ } else {
+ if (SF_N(sf) > 1)
+ call fprintf (fd,
+ " Average full width at half maximum (%s) of ")
+ else
+ call fprintf (fd,
+ " Full width at half maximum (%s) of ")
+ call pargstr (SF_WTYPE(sf))
+ }
+ call fprintf (fd, "%.4f")
+ call pargr (SF_W(sf))
+ } else {
+ call fprintf (fd, " %s of %.6g with ")
+ if (SF_NS(sf) > 1) {
+ if (SF_NF(sf) > 1)
+ call pargstr ("Average best focus")
+ else
+ call pargstr ("Average focus")
+ } else {
+ if (SF_NF(sf) > 1)
+ call pargstr ("Best focus")
+ else
+ call pargstr ("Focus")
+ }
+ call pargr (SF_F(sf))
+ if (SF_WCODE(sf) == 1) {
+ call fprintf (fd, "%d%% enclosed flux radius of ")
+ call pargr (100 * SF_LEVEL(sf))
+ } else {
+ call fprintf (fd, "%s of ")
+ call pargstr (SF_WTYPE(sf))
+ }
+ call fprintf (fd, "%.2f")
+ call pargr (SF_W(sf))
+ }
+ }
+
+ call strclose (fd)
+end
+
+
+# STF_FITFOCUS -- Find the best focus.
+
+procedure stf_fitfocus (sf)
+
+pointer sf #I Starfocus pointer
+
+int i, j, k, n, jmin
+pointer x, y, sfd, sfs, sff, sfi
+real f, r, m, wr, wf
+bool fp_equalr()
+
+begin
+ # Set number of valid points, stars, focuses, images.
+ SF_N(sf) = 0
+ SF_YP1(sf) = 0
+ SF_YP2(sf) = 0
+ do i = 1, SF_NSFD(sf) {
+ sfd = SF_SFD(sf,i)
+ if (SFD_STATUS(sfd) == 0) {
+ SF_N(sf) = SF_N(sf) + 1
+ SF_YP1(sf) = min (SF_YP1(sf), SFD_YP1(sfd))
+ SF_YP2(sf) = max (SF_YP2(sf), SFD_YP2(sfd))
+ }
+ }
+ SF_NS(sf) = 0
+ do i = 1, SF_NSTARS(sf) {
+ sfs = SF_SFS(sf,i)
+ SFS_N(sfs) = 0
+ SFS_M(sfs) = 0.
+ SFS_NF(sfs) = 0
+ do j = 1, SFS_NSFD(sfs) {
+ sfd = SFS_SFD(sfs,j)
+ if (SFD_STATUS(SFS_SFD(sfs,j)) != 0)
+ next
+ SFS_N(sfs) = SFS_N(sfs) + 1
+ SFS_M(sfs) = SFS_M(sfs) + SFD_M(sfd)
+ sff = SFD_SFF(sfd)
+ for (k = 1; SFD_SFF(SFS_SFD(sfs,k)) != sff; k = k + 1)
+ ;
+ if (k == j)
+ SFS_NF(sfs) = SFS_NF(sfs) + 1
+ }
+ if (SFS_N(sfs) > 0) {
+ SFS_M(sfs) = SFS_M(sfs) / SFS_N(sfs)
+ SF_NS(sf) = SF_NS(sf) + 1
+ }
+ }
+ SF_NF(sf) = 0
+ do i = 1, SF_NFOCUS(sf) {
+ sff = SF_SFF(sf,i)
+ SFF_W(sff) = 0.
+ SFF_N(sff) = 0
+ SFF_NI(sff) = 0
+ wr = 0
+ do j = 1, SFF_NSFD(sff) {
+ sfd = SFF_SFD(sff,j)
+ if (SFD_STATUS(sfd) != 0)
+ next
+ m = SFS_M(SFD_SFS(sfd))
+ wr = wr + m
+ SFF_W(sff) = SFF_W(sff) + m * SFD_W(sfd)
+ SFF_N(sff) = SFF_N(sff) + 1
+ sfi = SFD_SFI(sfd)
+ for (k = 1; SFD_SFI(SFF_SFD(sff,k)) != sfi; k = k + 1)
+ ;
+ if (k == j)
+ SFF_NI(sff) = SFF_NI(sff) + 1
+ }
+ if (SFF_N(sff) > 0) {
+ SFF_W(sff) = SFF_W(sff) / wr
+ SF_NF(sf) = SF_NF(sf) + 1
+ }
+ }
+ SF_NI(sf) = 0
+ do i = 1, SF_NIMAGES(sf) {
+ sfi = SF_SFI(sf,i)
+ SFI_N(sfi) = 0
+ do j = 1, SFI_NSFD(sfi)
+ if (SFD_STATUS(SFI_SFD(sfi,j)) == 0)
+ SFI_N(sfi) = SFI_N(sfi) + 1
+ if (SFI_N(sfi) > 0)
+ SF_NI(sf) = SF_NI(sf) + 1
+ }
+
+ # Find the average magnitude, best focus, and radius for each star.
+ # Find the brightest magnitude and average best focus and radius
+ # over all stars.
+
+ SF_BEST(sf) = SF_SFD(sf,1)
+ SF_F(sf) = 0.
+ SF_W(sf) = 0.
+ SF_M(sf) = 0.
+ SF_NS(sf) = 0
+ wr = 0.
+ wf = 0.
+ do i = 1, SF_NSTARS(sf) {
+ sfs = SF_SFS(sf,i)
+ call malloc (x, SFS_NSFD(sfs), TY_REAL)
+ call malloc (y, SFS_NSFD(sfs), TY_REAL)
+ k = 0
+ n = 0
+ do j = 1, SFS_NSFD(sfs) {
+ sfd = SFS_SFD(sfs,j)
+ if (SFD_STATUS(sfd) != 0)
+ next
+ r = SFD_W(sfd)
+ f = SFD_F(sfd)
+ if (!IS_INDEF(f))
+ k = k + 1
+ Memr[x+n] = f
+ Memr[y+n] = r
+ n = n + 1
+ if (r < SFD_W(SF_BEST(sf)))
+ SF_BEST(sf) = sfd
+ }
+
+ # Find the best focus and radius.
+ if (n == 0) {
+ SFS_F(sfs) = INDEF
+ SFS_W(sfs) = INDEF
+ SFS_M(sfs) = INDEF
+ SFS_N(sfs) = 0
+ } else if (k == 0) {
+ call alimr (Memr[y], n, f, r)
+ f = INDEF
+ m = SFS_M(sfs)
+ wr = wr + m
+ SFS_F(sfs) = f
+ SFS_W(sfs) = r
+ SFS_M(sfs) = m
+ SFS_N(sfs) = n
+ SF_W(sf) = SF_W(sf) + m * r
+ SF_M(sf) = max (SF_M(sf), m)
+ SF_NS(sf) = SF_NS(sf) + 1
+ } else {
+ SFS_N(sfs) = n
+ if (k < n) {
+ k = 0
+ do j = 0, n-1 {
+ if (!IS_INDEF(Memr[x+j])) {
+ Memr[x+k] = Memr[x+j]
+ Memr[y+k] = Memr[y+j]
+ k = k + 1
+ }
+ }
+ }
+ call xt_sort2 (Memr[x], Memr[y], k)
+ n = 0
+ do j = 1, k-1 {
+ if (fp_equalr (Memr[x+j], Memr[x+n])) {
+ if (Memr[y+j] < Memr[y+n])
+ Memr[y+n] = Memr[y+j]
+ } else {
+ n = n + 1
+ Memr[x+n] = Memr[x+j]
+ Memr[y+n] = Memr[y+j]
+ }
+ }
+ n = n + 1
+
+ # Find the minimum radius
+ jmin = 0
+ do j = 0, n-1
+ if (Memr[y+j] < Memr[y+jmin])
+ jmin = j
+
+ # Use parabolic interpolation to find the best focus
+ if (jmin == 0 || jmin == n-1) {
+ f = Memr[x+jmin]
+ r = Memr[y+jmin]
+ } else
+ call stf_parab (Memr[x+jmin-1], Memr[y+jmin-1], f, r)
+
+ m = SFS_M(sfs)
+ wr = wr + m
+ wf = wf + m
+ SFS_F(sfs) = f
+ SFS_W(sfs) = r
+ SFS_M(sfs) = m
+ SF_F(sf) = SF_F(sf) + m * f
+ SF_W(sf) = SF_W(sf) + m * r
+ SF_M(sf) = max (SF_M(sf), m)
+ SF_NS(sf) = SF_NS(sf) + 1
+ }
+ call mfree (x, TY_REAL)
+ call mfree (y, TY_REAL)
+ }
+
+ if (wr > 0.)
+ SF_W(sf) = SF_W(sf) / wr
+ else {
+ SF_W(sf) = INDEF
+ SF_M(sf) = INDEF
+ }
+ if (wf > 0.)
+ SF_F(sf) = SF_F(sf) / wf
+ else
+ SF_F(sf) = INDEF
+end
+
+
+# STF_PARAB -- Find the minimum of a parabolic fit to three points.
+
+procedure stf_parab (x, y, xmin, ymin)
+
+real x[3]
+real y[3]
+real xmin
+real ymin
+
+double x12, x13, x23, x213, x223, y13, y23, a, b, c
+
+begin
+ x12 = x[1] - x[2]
+ x13 = x[1] - x[3]
+ x23 = x[2] - x[3]
+ x213 = x13 * x13
+ x223 = x23 * x23
+ y13 = y[1] - y[3]
+ y23 = y[2] - y[3]
+ c = (y13 - y23 * x13 / x23) / (x213 - x223 * x13 / x23)
+ b = (y23 - c * x223) / x23
+ a = y[3]
+ xmin = -b / (2 * c)
+ ymin = a + b * xmin + c * xmin * xmin
+ xmin = xmin + x[3]
+end
+
+
+# STF_MAGSORT -- Compare two star structures by average magnitude.
+
+int procedure stf_magsort (sfd1, sfd2)
+
+pointer sfd1, sfd2 # Structures to compare
+pointer sfs1, sfs2 # Star structures for magnitudes
+
+begin
+ sfs1 = SFD_SFS(sfd1)
+ sfs2 = SFD_SFS(sfd2)
+ if (SFS_M(sfs1) > SFS_M(sfs2))
+ return (-1)
+ else if (SFS_M(sfs1) < SFS_M(sfs2))
+ return (1)
+ else
+ return (0)
+end
+
+
+# STF_FOCSORT -- Compare two star structures by focus.
+
+int procedure stf_focsort (sfd1, sfd2)
+
+pointer sfd1, sfd2 # Structures to compare
+
+begin
+ if (SFD_F(sfd1) < SFD_F(sfd2))
+ return (-1)
+ else if (SFD_F(sfd1) > SFD_F(sfd2))
+ return (1)
+ else
+ return (0)
+end
+
+
+# STF_DISPLAY -- Display image if necessary.
+# The user is required to display the first image separately.
+
+procedure stf_display (image, frame)
+
+char image[ARB] #I Image to display
+int frame #I Display frame to use
+
+int i, status
+pointer sp, dname, ds, iw, imd_mapframe(), iw_open()
+bool xt_imnameeq()
+errchk clcmdw
+
+begin
+ call smark (sp)
+ call salloc (dname, SZ_LINE, TY_CHAR)
+
+ ds = imd_mapframe (1, READ_WRITE, NO)
+ do i = 1, MAX_FRAMES {
+ iferr (iw = iw_open (ds, i, Memc[dname], SZ_LINE, status))
+ next
+ call iw_close (iw)
+ if (xt_imnameeq (image, Memc[dname]))
+ break
+ }
+ call imunmap (ds)
+
+ if (!xt_imnameeq (image, Memc[dname])) {
+ call sprintf (Memc[dname], SZ_LINE, "display %s frame=%d fill=yes")
+ call pargstr (image)
+ call pargi (frame)
+ call clcmdw (Memc[dname])
+ }
+
+ call sfree (sp)
+end
+
+
+# STFCUR -- Debugging routine.
+# Replace calls to clgcur with stfcur so that an text file containing the
+# cursor coordinates may be specified when running standalone (such as
+# under a debugger).
+
+int procedure stfcur (cur, wx, wy, wcs, key, cmd, sz_cmd)
+
+char cur[ARB] # Cursor name
+real wx, wy # Cursor coordinate
+int wcs # WCS
+int key # Key
+char cmd[sz_cmd] # Command
+int sz_cmd # Size of command
+
+int fd, stat, open(), fscan()
+pointer fname
+errchk open
+
+begin
+ if (fd == NULL) {
+ call malloc (fname, SZ_FNAME, TY_CHAR)
+ call clgstr (cur, Memc[fname], SZ_FNAME)
+ fd = open (Memc[fname], READ_ONLY, TEXT_FILE)
+ call mfree (fname, TY_CHAR)
+ }
+
+ stat = fscan (fd)
+ if (stat == EOF) {
+ call close (fd)
+ return (stat)
+ }
+
+ call gargr (wx)
+ call gargr (wy)
+ call gargi (wcs)
+ call gargi (key)
+
+ return (stat)
+end