aboutsummaryrefslogtreecommitdiff
path: root/noao/astcat/src/awcs/dbwcs.x
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /noao/astcat/src/awcs/dbwcs.x
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'noao/astcat/src/awcs/dbwcs.x')
-rw-r--r--noao/astcat/src/awcs/dbwcs.x522
1 files changed, 522 insertions, 0 deletions
diff --git a/noao/astcat/src/awcs/dbwcs.x b/noao/astcat/src/awcs/dbwcs.x
new file mode 100644
index 00000000..f3109050
--- /dev/null
+++ b/noao/astcat/src/awcs/dbwcs.x
@@ -0,0 +1,522 @@
+include <imhdr.h>
+include <math.h>
+include <mwset.h>
+include <pkg/skywcs.h>
+include <pkg/cq.h>
+
+# These should probably go into aimpars.h.
+
+define IMDB_WCSDICT "|wxref|wyref|wxmag|wymag|wxrot|wyrot|wraref|wdecref|\
+wproj|wsystem|"
+
+define IMDB_WCS_WXREF 1
+define IMDB_WCS_WYREF 2
+define IMDB_WCS_WXMAG 3
+define IMDB_WCS_WYMAG 4
+define IMDB_WCS_WXROT 5
+define IMDB_WCS_WYROT 6
+define IMDB_WCS_WLNGREF 7
+define IMDB_WCS_WLATREF 8
+define IMDB_WCS_WPROJ 9
+define IMDB_WCS_WSYSTEM 10
+
+
+# AT_DBWCS -- Compute a FITS WCS from an image using WCS definitions
+# stored in the image surveys configuration file and transferred to the
+# image query results structure. At the moment I am going to keep this
+# routine simple by not worrying about the units of any quantities but the
+# world coordinates of the reference point. This routine can be made more
+# sophisticated later as time permits. The information is there ...
+
+int procedure at_dbwcs (im, res, update, verbose)
+
+pointer im #I the input image descriptor
+pointer res #I the image query results descriptor
+bool update #I update rather than list the wcs
+bool verbose #I verbose mode
+
+double xref, yref, xmag, ymag, xrot, yrot, lngref, latref, dval
+pointer sp, kfield, kname, kvalue, kunits, wtype, ctype, coo, mw
+int i, ip, stat, coostat, ktype, nwcs, wkey, lngunits, latunits
+double imgetd(), at_imhms()
+int cq_istati(), cq_winfon(), strdic(), ctod(), ctowrd(), sk_decwcs()
+bool streq()
+errchk imgetd()
+
+begin
+ # Return if the input is not 2D.
+
+ if (IM_NDIM(im) != 2)
+ return (ERR)
+
+ # Allocate working space.
+
+ call smark (sp)
+ call salloc (kfield, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (kname, CQ_SZ_QPNAME, TY_CHAR)
+ call salloc (kvalue, CQ_SZ_QPVALUE, TY_CHAR)
+ call salloc (kunits, CQ_SZ_QPUNITS, TY_CHAR)
+ call salloc (wtype, SZ_FNAME, TY_CHAR)
+ call salloc (ctype, SZ_FNAME, TY_CHAR)
+
+ # Assume some sensible defaults, e.g. the reference point is at
+ # the center of the image, the orientation is the standard astronomical
+ # orientation with ra increasing to the left and declination increasing
+ # to the top, the projection is tan, the coordinate system is J2000.
+
+ xref = (IM_LEN(im,1) + 1.0d0)/ 2.0d0
+ yref = (IM_LEN(im,2) + 1.0d0)/ 2.0d0
+ xmag = INDEFD
+ ymag = INDEFD
+ xrot = 180.0d0
+ yrot = 0.0d0
+ lngref = INDEFD
+ latref = INDEFD
+ call strcpy ("tan", Memc[wtype], SZ_FNAME)
+ call strcpy ("J2000", Memc[ctype], SZ_FNAME)
+
+ # Loop over the mwcs database quantities.
+
+ nwcs = cq_istati (res, CQNWCS)
+ do i = 1, nwcs {
+
+ # Get the keyword information.
+ if (cq_winfon (res, i, Memc[kfield], CQ_SZ_QPNAME, Memc[kname],
+ CQ_SZ_QPNAME, Memc[kvalue], CQ_SZ_QPVALUE, ktype, Memc[kunits],
+ CQ_SZ_QPUNITS) != i)
+ next
+
+ # Which keyword have we got ?
+ wkey = strdic (Memc[kfield], Memc[kfield], CQ_SZ_QPNAME,
+ IMDB_WCSDICT)
+ ip = 1
+ switch (wkey) {
+
+ # Get the x reference point in pixels.
+ case IMDB_WCS_WXREF:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ if (! IS_INDEFD(dval))
+ xref = dval
+
+ case IMDB_WCS_WYREF:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ if (! IS_INDEFD(dval))
+ yref = dval
+
+ case IMDB_WCS_WXMAG:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ if (! IS_INDEFD(dval))
+ xmag = dval
+
+ case IMDB_WCS_WYMAG:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ if (! IS_INDEFD(dval))
+ ymag = dval
+
+ case IMDB_WCS_WXROT:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ if (! IS_INDEFD(dval))
+ xrot = dval
+
+ case IMDB_WCS_WYROT:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ if (! IS_INDEFD(dval))
+ yrot = dval
+
+ case IMDB_WCS_WLNGREF:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else {
+ dval = at_imhms (im, Memc[kname])
+ if (IS_INDEFD(dval)) {
+ iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ }
+ }
+ if (! IS_INDEFD(dval))
+ lngref = dval
+ lngunits = strdic (Memc[kunits], Memc[kunits], CQ_SZ_QPUNITS,
+ SKY_LNG_UNITLIST)
+
+ case IMDB_WCS_WLATREF:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ dval = INDEFD
+ else if (ctod (Memc[kvalue], ip, dval) <= 0)
+ dval = INDEFD
+ } else {
+ dval = at_imhms (im, Memc[kname])
+ if (IS_INDEFD(dval)) {
+ iferr (dval = imgetd (im, Memc[kname]))
+ dval = INDEFD
+ }
+ }
+ if (! IS_INDEFD(dval))
+ latref = dval
+ latunits = strdic (Memc[kunits], Memc[kunits], CQ_SZ_QPUNITS,
+ SKY_LAT_UNITLIST)
+
+ case IMDB_WCS_WPROJ:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ call strcpy ("tan", Memc[wtype], SZ_FNAME)
+ else if (ctowrd (Memc[kvalue], ip, Memc[wtype],
+ SZ_FNAME) <= 0)
+ call strcpy ("tan", Memc[wtype], SZ_FNAME)
+ } else iferr (call imgstr (im, Memc[kname], Memc[wtype],
+ SZ_FNAME))
+ call strcpy ("tan", Memc[wtype], SZ_FNAME)
+
+ case IMDB_WCS_WSYSTEM:
+ if (streq (Memc[kname], "INDEF")) {
+ if (streq (Memc[kvalue], "INDEF"))
+ call strcpy ("J2000", Memc[ctype], SZ_FNAME)
+ else if (ctowrd (Memc[kvalue], ip, Memc[ctype],
+ SZ_FNAME) <= 0)
+ call strcpy ("J2000", Memc[ctype], SZ_FNAME)
+ } else iferr (call imgstr (im, Memc[kname], Memc[ctype],
+ SZ_FNAME))
+ call strcpy ("J2000", Memc[ctype], SZ_FNAME)
+
+ default:
+ ;
+ }
+ }
+
+ # Check to see of the critical quantities image scale and reference
+ # point are defined. Quit if they are not, otherwise update the
+ # header.
+
+ if (IS_INDEFD(xmag) || IS_INDEFD(ymag) || IS_INDEFD(lngref) ||
+ IS_INDEFD(latref)) {
+
+ stat = ERR
+
+ } else {
+
+ # Open the coordinate system structure.
+ coostat = sk_decwcs (Memc[ctype], mw, coo, NULL)
+
+ # Update hte header.
+ if (coostat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ stat = ERR
+ } else {
+ if (lngunits > 0)
+ call sk_seti (coo, S_NLNGUNITS, lngunits)
+ if (latunits > 0)
+ call sk_seti (coo, S_NLATUNITS, latunits)
+ if (verbose)
+ call printf (" Writing FITS wcs using image survey db\n")
+ call at_uwcs (im, coo, Memc[wtype], lngref, latref, xref,
+ yref, xmag, ymag, xrot, yrot, false, update)
+ stat = OK
+ }
+
+ # Close the coordinate structure
+ if (coo != NULL)
+ call sk_close (coo)
+ }
+
+ call sfree (sp)
+ return (stat)
+end
+
+
+define NEWCD Memd[ncd+(($2)-1)*ndim+($1)-1]
+
+# AT_UWCS -- Compute the image wcs from the user parameters.
+
+procedure at_uwcs (im, coo, projection, lngref, latref, xref, yref,
+ xscale, yscale, xrot, yrot, transpose, update)
+
+pointer im #I pointer to the input image
+pointer coo #I pointer to the coordinate structure
+char projection[ARB] #I the sky projection geometry
+double lngref, latref #I the world coordinates of the reference point
+double xref, yref #I the reference point in pixels
+double xscale, yscale #I the x and y scale in arcsec / pixel
+double xrot, yrot #I the x and y axis rotation angles in degrees
+bool transpose #I transpose the wcs
+bool update #I update rather than list the wcs
+
+
+double tlngref, tlatref
+int l, i, ndim, naxes, axmap, wtype, ax1, ax2, szatstr
+pointer mw, sp, r, w, cd, ltm, ltv, iltm, nr, ncd, axes, axno, axval
+pointer projstr, projpars, wpars, mwnew, atstr
+int mw_stati(), sk_stati(), strdic(), strlen(), itoc()
+pointer mw_openim(), mw_open()
+errchk mw_newsystem(), mw_gwattrs()
+
+begin
+ mw = mw_openim (im)
+ ndim = mw_stati (mw, MW_NPHYSDIM)
+
+ # Allocate working memory for the vectors and matrices.
+ call smark (sp)
+ call salloc (projstr, SZ_FNAME, TY_CHAR)
+ call salloc (projpars, SZ_LINE, TY_CHAR)
+ call salloc (wpars, SZ_LINE, TY_CHAR)
+ call salloc (r, ndim, TY_DOUBLE)
+ call salloc (w, ndim, TY_DOUBLE)
+ call salloc (cd, ndim * ndim, TY_DOUBLE)
+ call salloc (ltm, ndim * ndim, TY_DOUBLE)
+ call salloc (ltv, ndim, TY_DOUBLE)
+ call salloc (iltm, ndim * ndim, TY_DOUBLE)
+ call salloc (nr, ndim, TY_DOUBLE)
+ call salloc (ncd, ndim * ndim, TY_DOUBLE)
+ call salloc (axes, IM_MAXDIM, TY_INT)
+ call salloc (axno, IM_MAXDIM, TY_INT)
+ call salloc (axval, IM_MAXDIM, TY_INT)
+
+ # Open the new wcs
+ mwnew = mw_open (NULL, ndim)
+ call mw_gsystem (mw, Memc[projstr], SZ_FNAME)
+ iferr {
+ call mw_newsystem (mw, "image", ndim)
+ } then {
+ call mw_newsystem (mwnew, Memc[projstr], ndim)
+ } else {
+ call mw_newsystem (mwnew, "image", ndim)
+ }
+
+ # Set the LTERM.
+ call mw_gltermd (mw, Memd[ltm], Memd[ltv], ndim)
+ call mw_sltermd (mwnew, Memd[ltm], Memd[ltv], ndim)
+
+ # Store the old axis map for later use.
+ call mw_gaxmap (mw, Memi[axno], Memi[axval], ndim)
+
+ # Get the 2 logical axes.
+ call mw_gaxlist (mw, 03B, Memi[axes], naxes)
+ axmap = mw_stati (mw, MW_USEAXMAP)
+ ax1 = Memi[axes]
+ ax2 = Memi[axes+1]
+
+ # Set the axes and projection type.
+ if (projection[1] == EOS) {
+ call mw_swtype (mwnew, Memi[axes], ndim, "linear", "")
+ } else {
+ call sscan (projection)
+ call gargwrd (Memc[projstr], SZ_FNAME)
+ call gargstr (Memc[projpars], SZ_LINE)
+ call sprintf (Memc[wpars], SZ_LINE,
+ "axis 1: axtype = ra %s axis 2: axtype = dec %s")
+ call pargstr (Memc[projpars])
+ call pargstr (Memc[projpars])
+ call mw_swtype (mwnew, Memi[axes], ndim, Memc[projstr], Memc[wpars])
+ }
+
+ # Copy in the atrributes of the other axes.
+ szatstr = SZ_LINE
+ call malloc (atstr, szatstr, TY_CHAR)
+ do l = 1, ndim {
+ if (l == ax1 || l == ax2)
+ next
+ iferr {
+ call mw_gwattrs (mw, l, "wtype", Memc[projpars], SZ_LINE)
+ } then {
+ call mw_swtype (mwnew, l, 1, "linear", "")
+ } else {
+ call mw_swtype (mwnew, l, 1, Memc[projpars], "")
+ }
+ for (i = 1; ; i = i + 1) {
+ if (itoc (i, Memc[projpars], SZ_LINE) <= 0)
+ Memc[atstr] = EOS
+ repeat {
+ iferr (call mw_gwattrs (mw, l, Memc[projpars],
+ Memc[atstr], szatstr))
+ Memc[atstr] = EOS
+ if (strlen (Memc[atstr]) < szatstr)
+ break
+ szatstr = szatstr + SZ_LINE
+ call realloc (atstr, szatstr, TY_CHAR)
+ }
+ if (Memc[atstr] == EOS)
+ break
+ call mw_swattrs (mwnew, 1, Memc[projpars], Memc[atstr])
+ }
+ }
+ call mfree (atstr, TY_CHAR)
+
+ # Compute the referemce point world coordinates.
+ switch (sk_stati(coo, S_NLNGUNITS)) {
+ case SKY_DEGREES:
+ tlngref = lngref
+ case SKY_RADIANS:
+ tlngref = RADTODEG(lngref)
+ case SKY_HOURS:
+ tlngref = 15.0d0 * lngref
+ default:
+ tlngref = lngref
+ }
+ switch (sk_stati(coo, S_NLATUNITS)) {
+ case SKY_DEGREES:
+ tlatref = latref
+ case SKY_RADIANS:
+ tlatref = RADTODEG(latref)
+ case SKY_HOURS:
+ tlatref = 15.0d0 * latref
+ default:
+ tlatref = latref
+ }
+
+ if (! transpose) {
+ Memd[w+ax1-1] = tlngref
+ Memd[w+ax2-1] = tlatref
+ } else {
+ Memd[w+ax2-1] = tlngref
+ Memd[w+ax1-1] = tlatref
+ }
+
+ # Compute the reference point pixel coordinates.
+ Memd[nr+ax1-1] = xref
+ Memd[nr+ax2-1] = yref
+
+ # Compute the new CD matrix.
+ if (! transpose) {
+ NEWCD(ax1,ax1) = xscale * cos (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(ax2,ax1) = -yscale * sin (DEGTORAD(yrot)) / 3600.0d0
+ NEWCD(ax1,ax2) = xscale * sin (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(ax2,ax2) = yscale * cos (DEGTORAD(yrot)) / 3600.0d0
+ } else {
+ NEWCD(ax1,ax1) = xscale * sin (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(ax2,ax1) = yscale * cos (DEGTORAD(yrot)) / 3600.0d0
+ NEWCD(ax1,ax2) = xscale * cos (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(ax2,ax2) = -yscale * sin (DEGTORAD(yrot)) / 3600.0d0
+ }
+
+ if (! update)
+ call at_mwshow (mwnew, Memd[ltv], Memd[ltm], Memd[w], Memd[nr],
+ Memd[ncd], ndim)
+
+ # Reset the axis map.
+ call mw_seti (mw, MW_USEAXMAP, axmap)
+
+ # Recompute and store the new wcs if update is enabled.
+ call mw_saxmap (mwnew, Memi[axno], Memi[axval], ndim)
+ if (sk_stati (coo, S_PIXTYPE) == PIXTYPE_PHYSICAL) {
+ call mw_swtermd (mwnew, Memd[nr], Memd[w], Memd[ncd], ndim)
+ } else {
+ call mwmmuld (Memd[ncd], Memd[ltm], Memd[cd], ndim)
+ call mwinvertd (Memd[ltm], Memd[iltm], ndim)
+ call asubd (Memd[nr], Memd[ltv], Memd[r], ndim)
+ call mwvmuld (Memd[iltm], Memd[r], Memd[nr], ndim)
+ call mw_swtermd (mwnew, Memd[nr], Memd[w], Memd[cd], ndim)
+ }
+
+ # Save the fit.
+ if (! transpose) {
+ call sk_seti (coo, S_PLNGAX, ax1)
+ call sk_seti (coo, S_PLATAX, ax2)
+ } else {
+ call sk_seti (coo, S_PLNGAX, ax2)
+ call sk_seti (coo, S_PLATAX, ax1)
+ }
+ if (update) {
+ call sk_saveim (coo, mwnew, im)
+ call mw_saveim (mwnew, im)
+ }
+
+ # Close the wcs,
+ call mw_close (mwnew)
+ call mw_close (mw)
+
+ # Force the CDELT keywords to update. This will be unecessary when
+ # mwcs is updated to deal with non-quoted and / or non left-justified
+ # CTYPE keywords..
+ wtype = strdic (Memc[projstr], Memc[projstr], SZ_FNAME, WTYPE_LIST)
+ if (wtype > 0)
+ call sk_seti (coo, S_WTYPE, wtype)
+ call sk_ctypeim (coo, im)
+
+ # Reset the fit. This will be unecessary when wcs is updated to deal
+ # with non-quoted and / or non left-justified CTYPE keywords.
+ call sk_seti (coo, S_WTYPE, 0)
+ call sk_seti (coo, S_PLNGAX, 0)
+ call sk_seti (coo, S_PLATAX, 0)
+
+ call sfree (sp)
+end
+
+
+# AT_IMHMS -- Fetch a quantity form the image header that is in hms or dms
+# format, e.g. in the form "+/-hh mm ss.x" or "+/-dd mm ss.s".
+
+double procedure at_imhms (im, kname)
+
+pointer im #I the image descriptor
+char kname[ARB] #I the image keyword name
+
+double dval, hours, minutes, seconds
+pointer sp, value
+int nscan()
+errchk imgstr()
+
+begin
+ call smark (sp)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+
+ iferr {
+ call imgstr (im, kname, Memc[value], SZ_FNAME)
+ } then {
+ dval = INDEFD
+ } else {
+ call sscan (Memc[value])
+ call gargd (hours)
+ call gargd (minutes)
+ call gargd (seconds)
+ if (nscan() != 3)
+ dval = INDEFD
+ else if (hours >= 0.0d0)
+ dval = hours + (minutes / 60.0d0) + (seconds / 3600.0d0)
+ else
+ dval = -(abs(hours) + (minutes / 60.0d0) + (seconds / 3600.0d0))
+
+ }
+
+ call sfree (sp)
+
+ return (dval)
+end