aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/imcoords
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 /pkg/images/imcoords
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'pkg/images/imcoords')
-rw-r--r--pkg/images/imcoords/Revisions2026
-rw-r--r--pkg/images/imcoords/ccfind.par48
-rw-r--r--pkg/images/imcoords/ccget.par36
-rw-r--r--pkg/images/imcoords/ccmap.par54
-rw-r--r--pkg/images/imcoords/ccsetwcs.par28
-rw-r--r--pkg/images/imcoords/ccstd.par31
-rw-r--r--pkg/images/imcoords/cctran.par28
-rw-r--r--pkg/images/imcoords/ccxymatch.par41
-rw-r--r--pkg/images/imcoords/doc/ccfind.hlp596
-rw-r--r--pkg/images/imcoords/doc/ccget.hlp463
-rw-r--r--pkg/images/imcoords/doc/ccmap.hlp1028
-rw-r--r--pkg/images/imcoords/doc/ccsetwcs.hlp562
-rw-r--r--pkg/images/imcoords/doc/ccstd.hlp480
-rw-r--r--pkg/images/imcoords/doc/cctran.hlp412
-rw-r--r--pkg/images/imcoords/doc/ccxymatch.hlp781
-rw-r--r--pkg/images/imcoords/doc/hpctran.hlp109
-rw-r--r--pkg/images/imcoords/doc/imcctran.hlp598
-rw-r--r--pkg/images/imcoords/doc/mkcwcs.hlp93
-rw-r--r--pkg/images/imcoords/doc/mkcwwcs.hlp110
-rw-r--r--pkg/images/imcoords/doc/skyctran.hlp861
-rw-r--r--pkg/images/imcoords/doc/starfind.hlp304
-rw-r--r--pkg/images/imcoords/doc/wcsctran.hlp340
-rw-r--r--pkg/images/imcoords/doc/wcsedit.hlp429
-rw-r--r--pkg/images/imcoords/doc/wcsreset.hlp272
-rw-r--r--pkg/images/imcoords/hpctran.par9
-rw-r--r--pkg/images/imcoords/imcctran.par9
-rw-r--r--pkg/images/imcoords/imcoords.cl27
-rw-r--r--pkg/images/imcoords/imcoords.hd23
-rw-r--r--pkg/images/imcoords/imcoords.men16
-rw-r--r--pkg/images/imcoords/imcoords.par1
-rw-r--r--pkg/images/imcoords/mkpkg5
-rw-r--r--pkg/images/imcoords/skyctran.par29
-rw-r--r--pkg/images/imcoords/src/ccfunc.x639
-rw-r--r--pkg/images/imcoords/src/ccstd.x252
-rw-r--r--pkg/images/imcoords/src/ccxytran.x740
-rw-r--r--pkg/images/imcoords/src/healpix.x492
-rw-r--r--pkg/images/imcoords/src/mkcwcs.cl94
-rw-r--r--pkg/images/imcoords/src/mkcwwcs.cl102
-rw-r--r--pkg/images/imcoords/src/mkpkg47
-rw-r--r--pkg/images/imcoords/src/rgstr.gx109
-rw-r--r--pkg/images/imcoords/src/rgstr.x215
-rw-r--r--pkg/images/imcoords/src/sfconvolve.x398
-rw-r--r--pkg/images/imcoords/src/sffind.x739
-rw-r--r--pkg/images/imcoords/src/sftools.x68
-rw-r--r--pkg/images/imcoords/src/skyctran.x2057
-rw-r--r--pkg/images/imcoords/src/skycur.key38
-rw-r--r--pkg/images/imcoords/src/starfind.h51
-rw-r--r--pkg/images/imcoords/src/t_ccfind.x782
-rw-r--r--pkg/images/imcoords/src/t_ccget.x1201
-rw-r--r--pkg/images/imcoords/src/t_ccmap.x2079
-rw-r--r--pkg/images/imcoords/src/t_ccsetwcs.x751
-rw-r--r--pkg/images/imcoords/src/t_ccstd.x468
-rw-r--r--pkg/images/imcoords/src/t_cctran.x374
-rw-r--r--pkg/images/imcoords/src/t_ccxymatch.x576
-rw-r--r--pkg/images/imcoords/src/t_hpctran.x136
-rw-r--r--pkg/images/imcoords/src/t_imcctran.x922
-rw-r--r--pkg/images/imcoords/src/t_skyctran.x221
-rw-r--r--pkg/images/imcoords/src/t_starfind.x224
-rw-r--r--pkg/images/imcoords/src/t_wcsctran.x643
-rw-r--r--pkg/images/imcoords/src/t_wcsedit.x792
-rw-r--r--pkg/images/imcoords/src/t_wcsreset.x142
-rw-r--r--pkg/images/imcoords/src/ttycur.key49
-rw-r--r--pkg/images/imcoords/src/wcsedit.key24
-rw-r--r--pkg/images/imcoords/src/x_starfind.x1
-rw-r--r--pkg/images/imcoords/starfind.par25
-rw-r--r--pkg/images/imcoords/wcsctran.par12
-rw-r--r--pkg/images/imcoords/wcsedit.par13
-rw-r--r--pkg/images/imcoords/wcsreset.par5
68 files changed, 25330 insertions, 0 deletions
diff --git a/pkg/images/imcoords/Revisions b/pkg/images/imcoords/Revisions
new file mode 100644
index 00000000..5c411d45
--- /dev/null
+++ b/pkg/images/imcoords/Revisions
@@ -0,0 +1,2026 @@
+.help revisions Jan97 images.imcoords
+.nf
+
+===============================
+Package Reorganization
+===============================
+
+pkg/images/imarith/t_imsum.x
+pkg/images/imarith/t_imcombine.x
+pkg/images/doc/imsum.hlp
+pkg/images/doc/imcombine.hlp
+ Provided options for USHORT data. (12/10/96, Valdes)
+
+pkg/images/imarith/icsetout.x
+pkg/images/doc/imcombine.hlp
+ A new option for computing offsets from the image WCS has been added.
+ (11/30/96, Valdes)
+
+pkg/images/imarith/t_imcombine.x
+pkg/images/imarith/icombine.gx
+ Changed the error checking to catch additional errors relating to too
+ many files. (11/12/96, Valdes)
+
+pkg/images/imarith/icsort.gx
+ There was an error in the ic_2sort routine when there are exactly
+ three images that one of the explicit cases did not properly keep
+ the image identifications. See buglog 344. (8/1/96, Valdes)
+
+pkg/images/filters/median.x
+ The routine mde_yefilter was being called with the wrong number of
+ arguments.
+ (7/18/96, Davis)
+
+pkg/images/imarith/t_imcombine.x
+pkg/images/imarith/icombine.gx
+pkg/images/imarith/icimstack.x +
+pkg/images/imarith/iclog.x
+pkg/images/imarith/mkpkg
+pkg/images/doc/imcombine.hlp
+ The limit on the maximum number of images that can be combined, set by
+ the maximum number of logical file descriptors, has been removed. If
+ the condition of too many files is detected the task now automatically
+ stacks all the images in a temporary image and then combines them with
+ the project option.
+ (5/14/96, Valdes)
+
+pkg/images/geometry/xregister/rgxfit.x
+ Changed several Memr[] references to Memi[] in the rg_fit routine.
+ This bug was causing a floating point error in the xregister task
+ on the Dec Alpha if the coords file was defined, and could potentially
+ cause problems on other machines.
+ (Davis, April 3, 1996)
+
+pkg/images/geometry/t_geotran.x
+pkg/images/geometry/geograph.x
+pkg/images/doc/geomap.hlp
+ Corrected the definition of skew in the routines which compute a geometric
+ interpretation of the 6-coefficient fit, which compute the coefficients
+ from the geometric parameters, and in the relevant help pages.
+ (2/19/96, Davis)
+
+pkg/images/median.par
+pkg/images/rmedian.par
+pkg/images/mode.par
+pkg/images/rmode.par
+pkg/images/fmedian.par
+pkg/images/frmedian.par
+pkg/images/fmode.par
+pkg/images/frmode.par
+pkg/images/doc/median.hlp
+pkg/images/doc/rmedian.hlp
+pkg/images/doc/mode.hlp
+pkg/images/doc/rmode.hlp
+pkg/images/doc/fmedian.hlp
+pkg/images/doc/frmedian.hlp
+pkg/images/doc/fmode.hlp
+pkg/images/doc/frmode.hlp
+pkg/images/filters/t_median.x
+pkg/images/filters/t_rmedian.x
+pkg/images/filters/t_mode.x
+pkg/images/filters/t_rmode.x
+pkg/images/filters/t_fmedian.x
+pkg/images/filters/t_frmedian.x
+pkg/images/filters/t_fmode.x
+pkg/images/filters/t_frmode.x
+ Added a verbose parameter to the median, rmedian, mode, rmode, fmedian,
+ frmedian, fmode, and frmode tasks. (11/27/95, Davis)
+
+pkg/images/geometry/doc/geotran.hlp
+ Fixed an error in the help page for geotran. The default values for
+ the xscale and yscale parameters were incorrectly listed as INDEF,
+ INDEF instead of 1.0, 1.0. (11/14/95, Davis)
+
+pkg/images/imarith/icpclip.gx
+ Fixed a bug where a variable was improperly used for two different
+ purposes causing the algorithm to fail (bug 316). (10/19/95, Valdes)
+
+pkg/images/doc/imcombine.hlp
+ Clarified a point about how the sigma is calculated with the SIGCLIP
+ option. (10/11/95, Valdes)
+
+pkg/images/imarith/icombine.gx
+ To deal with the case of readnoise=0. and image data which has points with
+ negative mean or median and very small minimum readnoise is set
+ internally to avoid computing a zero sigma and dividing by it. This
+ applies to the noise model rejection options. (8/11/95, Valdes)
+
+pkg/images/frmedian.hlp
+pkg/images/frmode.hlp
+pkg/images/rmedian.hlp
+pkg/images/rmode.hlp
+pkg/images/frmedian.par
+pkg/images/frmode.par
+pkg/images/rmedian.par
+pkg/images/rmode.par
+pkg/images/filters/frmedian.h
+pkg/images/filters/frmode.h
+pkg/images/filters/rmedian.h
+pkg/images/filters/rmode.h
+pkg/images/filters/t_frmedian.x
+pkg/images/filters/t_frmode.x
+pkg/images/filters/t_rmedian.x
+pkg/images/filters/t_rmode.x
+pkg/images/filters/frmedian.x
+pkg/images/filters/frmode.x
+pkg/images/filters/rmedian.x
+pkg/images/filters/rmode.x
+pkg/images/filters/med_utils.x
+ Added new ring median and modal filtering tasks frmedian, rmedian,
+ frmode, and rmode to the images package.
+ (6/20/95, Davis)
+
+pkg/images/fmedian.hlp
+pkg/images/fmode.hlp
+pkg/images/median.hlp
+pkg/images/mode.hlp
+pkg/images/fmedian.par
+pkg/images/fmode.par
+pkg/images/median.par
+pkg/images/mode.par
+pkg/images/filters/fmedian.h
+pkg/images/filters/fmode.h
+pkg/images/filters/median.h
+pkg/images/filters/mode.h
+pkg/images/filters/t_fmedian.x
+pkg/images/filters/t_fmode.x
+pkg/images/filters/t_median.x
+pkg/images/filters/t_mode.x
+pkg/images/filters/fmedian.x
+pkg/images/filters/fmode.x
+pkg/images/filters/median.x
+pkg/images/filters/mode.x
+pkg/images/filters/fmd_buf.x
+pkg/images/filters/fmd_hist.x
+pkg/images/filters/fmd_maxmin.x
+pkg/images/filters/med_buf.x
+pkg/images/filters/med_sort.x
+ Added minimum and maximum good data parameters to the fmedian, fmode,
+ median, and mode filtering tasks. Removed the 64X64 kernel size limit
+ in the median and mode tasks. Replaced the common blocks with structures
+ and .h files.
+ (6/20/95, Davis)
+
+pkg/images/geometry/t_geotran.x
+pkg/images/geometry/geotran.x
+pkg/images/geometry/geotimtran.x
+ Fixed a bug in the buffering of the x and y coordinate surface interpolants
+ which can cause a memory corruption error if, nthe nxsample or nysample
+ parameters are > 1, and the nxblock or nyblock parameters are less
+ than the x and y dimensions of the input image. Took the opportunity
+ to clean up the code.
+ (6/13/95, Davis)
+
+=======
+V2.10.4
+=======
+
+pkg/images/geometry/t_geomap.x
+ Corrected a harmless typo in the code which determines the minimum
+ and maximum x values and improved the precision of the test when the
+ input is double precision.
+ (4/18/95, Davis)
+
+pkg/images/doc/fit1d.hlp
+ Added a description of the interactive parameter to the fit1d help page.
+ (4/17/95, Davis)
+
+pkg/images/imarith/t_imcombine.x
+ If an error occurs while opening an input image header the error
+ recovery will close all open images and then propagate the error.
+ For the case of running out of file descriptors with STF format
+ images this will allow the error message to be printed rather
+ than the error code. (4/3/95, Valdes)
+
+pkg/images/geometry/xregister/t_xregister.x
+ Added a test on the status code returned from the fitting routine so
+ the xregister tasks does not go ahead and write an output image when
+ the user quits the task in in interactive mode.
+ (3/31/95, Davis)
+
+pkg/images/imarith/icscale.x
+pkg/images/doc/imcombine.hlp
+ The behavior of the weights when using both multiplicative and zero
+ point scaling was incorrect; the zero levels have to account for
+ the scaling. (3/27/95, Valdes)
+
+pkg/images/geometry/xregister/rgxtools.x
+ Changed some amovr and amovi calls to amovkr and amovki calls.
+ (3/15/95, Davis)
+
+pkg/images/geometry/t_imshift.x
+pkg/images/geometry/t_magnify.x
+pkg/images/geometry/geotran.x
+pkg/images/geometry/xregister/rgximshift.x
+ The buffering margins set for the bicubic spline interpolants were
+ increased to improve the flux conservation properties of the interpolant
+ in cases where the data is undersampled. (12/6/94, Davis)
+
+pkg/images/xregister/rgxbckgrd.x
+ In several places the construct array[1++nx-wborder] was being used
+ instead of array[1+nx-wborder]. Apparently caused by a typo which
+ propagated through the code, the Sun compilers did not catch this, but
+ the IBM/RISC6000 compilers did. (11/16/94, Davis)
+
+
+pkg/images/xregister.par
+pkg/images/doc/xregister.hlp
+pkg/images/geometry/xregister/t_xregister.x
+pkg/images/geometry/xregister/rgxcorr.x
+pkg/images/geometry/xregister/rgxicorr.x
+pkg/images/geometry/xregister/rgxcolon.x
+pkg/images/geometry/xregister/rgxdbio.x
+ The xregister task was modified to to write the output shifts file
+ in either text database format (the current default) or in simple text
+ format. The change was made so that the output of xregister could
+ both be edited more easily by the user and be used directly with the
+ imshift task. (11/11/94, Davis)
+
+pkg/images/imfit/fit1d.x
+ A Memc in the ratio output option was incorrectly used instead of Memr
+ when the bug fix of 11/16/93 was made. (10/14/94, Valdes)
+
+pkg/images/geometry/xregister/rgxcorr.x
+ The procedure rg_xlaplace was being incorrectly declared as an integer
+ procedure.
+ (8/1/94, Davis)
+
+pkg/images/geometry/xregister/rgxregions.x
+ The routine strncmp was being called (with a missing number of characters
+ argument) instead of strcmp. This was causing a bus error under solaris
+ but not sun os whenever the user set regions to "grid ...". (7/27/94 LED)
+
+pkg/images/tv/imexaine/ierimexam.x
+ The Gaussian fitting can return a negative sigma**2 which would cause
+ an FPE when the square root is taken. This will only occur when
+ there is no reasonable signal. The results of the gaussian fitting
+ are now set to INDEF if this unphysical result occurs. (7/7/94, Valdes)
+
+pkg/images/geometry/geofit.x
+ A routine expecting two char arrays was being passed two real arrays
+ instead resulting in a segmentation violation if calctype=real
+ and reject > 0.
+ (6/21/94, Davis)
+
+pkg/images/imarith/t_imarith.x
+ IMARITH now deletes the CCDMEAN keyword if present. (6/21/94, Valdes)
+
+pkg/images/imarith/icaclip.gx
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/icpclip.gx
+pkg/images/imarith/icsclip.gx
+ 1. The restoration of deleted pixels to satisfy the nkeep parameter
+ was being done inside the iteration loop causing the possiblity
+ of a non-terminating loop; i.e. pixels are rejected, they are
+ restored, and the number left then does not statisfy the termination
+ condition. The restoration step was moved following the iterative
+ rejection.
+ 2. The restoration was also incorrectly when mclip=no and could
+ lead to a segmentation violation.
+ (6/13/94, Valdes)
+
+pkg/images/geometry/xregister/rgxicorr.x
+ The path names to the xregister task interactive help files was incorrect.
+ (6/13/94, Davis)
+
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/icsclip.gx
+ Found and fixed another typo bug. (6/7/94, Valdes/Zhang)
+
+pkg/images/imarith/icscale.x
+ The sigma scaling flag, doscale1, would not be set in the case of
+ a mean offset of zero though the scale factors could be different.
+ (5/25/94, Valdes/Zhang)
+
+pkg/images/imarith/icsclip.gx
+ There was a missing line: l = Memi[mp1]. (5/25/94, Valdes/Zhang)
+
+pkg/images/imarith/icaclip.gx
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/icpclip.gx
+pkg/images/imarith/icsclip.gx
+ The reordering step when a central median is used during rejection
+ but the final combining is average was incorrect if the number
+ of rejected low pixels was greater than the number of pixel
+ number of pixels not rejected. (5/25/94, Valdes)
+
+pkg/images/geometry/t_geotran.x
+ In cases where there was no input geomap database, geotran was
+ unnecessarily overiding the size of the input image requested by the
+ user if the size of the image was bigger than the default output size
+ (the size of the output image which would include all the input image
+ pixels is no user shifts were applied).
+ (5/10/94, Davis)
+
+pkg/images/imarith/icscale.x
+pkg/images/imarith/t_imcombine.x
+ 1. There is now a warning error if the scale, zero, or weight type
+ is unknown.
+ 2. An sfree was being called before the allocated memory was finished
+ being used.
+ (5/2/94, Valdes)
+
+pkg/images/tv/imexaine/ierimexam.x
+ For some objects the moment analysis could fail producing a floating
+ overflow error in imexamine, because the code was trying to use
+ INDEF as the initial value of the object fwhm. Changed the gaussian
+ fitting code to use a fraction of the fitting radius as the initial value
+ for the fitted full-width half-maximum in cases where the moment analysis
+ cannot compute an initial value.
+ (4/15/94 LED)
+
+pkg/images/imarith/iclog.x
+ Changed the mean, median, mode, and zero formats from 6g to 7.5g to
+ insure 5 significant digits regardless of signs and decimal points.
+ (4/13/94, Valdes)
+
+pkg/images/doc/imcombine.hlp
+ Tried again to clarify the scaling as multiplicative and the offseting
+ as additive for file input and for log output. (3/22/94, Valdes)
+
+pkg/images/imarith/iacclip.gx
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/iscclip.gx
+ The image sigma was incorrectly computed when an offset scaling is used.
+ (3/8/94, Valdes)
+
+pkg/images/doc/imcombine.hlp
+ The MINMAX example confused low and high. (3/7/94, Valdes)
+
+pkg/images/geometry/t_geomap.x
+pkg/images/geometry/geofit.x
+pkg/images/geometry/geograph.x
+ Fixed a bug in the geomap code which caused the linear portion of the transformation
+ to be computed incorrectly if the x and y fits had a different functional form.
+ (12/29/93, Davis)
+
+pkg/images/imarith/t_imcombine.x
+pkg/images/imcombine.par
+pkg/images/do/imcombine.hlp
+ The output pixel datatypes now include unsigned short integer.
+ (12/4/93, Valdes)
+
+pkg/images/doc/imcombine.hlp
+ Fixed an error in the example of offseting. (11/23/93, Valdes)
+
+pkg/images/imfit/fit1d.x
+ When doing operations in place the input and output buffers are the
+ same and the difference and ratio operations assumed they were not
+ causing the final results to be wrong. (11/16/93, Valdes)
+
+pkg/images/imarith/t_imarith.x
+pkg/images/doc/imarith.hlp
+ If no calculation type is specified then it will be at least real
+ for a division. Since the output pixel type defaults to the
+ calculation type if not specified this will also result in a
+ real output if dividing two integer images. (11/12/93, Valdes)
+
+pkg/images/imarith/icgrow.gx
+pkg/images/imarith/icpclip.gx
+pkg/images/imarith/icsclip.gx
+pkg/images/imarith/icaclip.gx
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/t_imcombine.x
+pkg/images/doc/imcombine.hlp
+ If there were fewer initial pixels than specified by nkeep then the
+ task would attempt to add garbage data to achieve nkeep pixels. This
+ could occur when using offsets, bad pixel masks, or thresholds. The
+ code was changed to check against the initial number of pixels rather
+ than the number of images. Also a negative nkeep is no longer
+ converted to a positive value based on the number of images. Instead
+ it specifies the maximum number of pixels to reject from the initial
+ set of pixels. (11/8/93, Valdes)
+
+=======
+V2.10.2
+=======
+
+pkg/images/imarith/icsetout.x
+ Added MWCS calls to update the axis mapping when using the project
+ option in IMCOMBINE. (10/8/93, Valdes)
+
+pkg$images/imarith/icscale.x
+pkg$images/doc/imcombine.hlp
+ The help indicated that user input scale or zero level factors
+ by an @file or keyword are multiplicative and additive while the
+ task was using then as divisive and subtractive. This was
+ corrected to agree with the intend of the documentation.
+ Also the factors are no longer normalized. (9/24/93, Valdes)
+
+pkg$images/imarith/icsetout.x
+ The case in which absolute offsets are specified but the offsets are
+ all the same did not work correctly. (9/24/93, Valdes)
+
+pkg$images/imfit/imsurfit.h
+pkg$images/imfit/t_imsurfit.x
+pkg$images/imfit/imsurfit.x
+pkg$images/lib/ranges.x
+ Fixed two bugs in the imsurfit task bad pixel rejection code. For low
+ k-sigma rejections factors the bad pixel list could overflow resulting
+ in a segmentation violation or a hung task. Overlapping ranges were
+ not being decoded into a bad pixel list properly resulting in
+ oscillating bad pixel rejection behavior where certain groups of
+ bad pixels were alternately being included and excluded from the fit.
+ Both bugs are fixed in iraf 2.10.3
+ (9/21/93, Davis)
+
+pkg$images/doc/imcombine.hlp
+ Clarified how bad pixel masks work with the "project" option.
+ (9/13/93, Valdes)
+
+pkg$images/imfit/fit1d.x
+ When the input and output images are the same there was an typo error
+ such that the output was opened separately but then never unmapped
+ resulting in the end of the image not being updated. (8/6/93, Valdes)
+
+pkg$images/imarith/t_imcombine.x
+ The algorithm for making sure there are enough file descriptors failed
+ to account for the need to reopen the output image header for an
+ update. Thus when the number of input images + output images + logfile
+ was exactly 60 the task would fail. The update occurs when the output
+ image is unmapped so the solution was to close the input images first
+ except for the first image whose pointer is used in the new copy of the
+ output image. (8/4/93, Valdes)
+
+pkg$images/filters/t_mode.x
+pkg$images/filters/t_median.x
+ Fixed a bug in the error trapping code in the median and mode tasks.
+ The call to eprintf contained an extra invalid error code agument.
+ (7/28/93, Davis)
+
+pkg$images/geometry/geomap.par
+pkg$images/geometry/t_geomap.x
+pkg$images/geometry/geogmap.x
+pkg$images/geometry/geofit.x
+ Fixed a bug in the error handling code in geomap which was producing
+ a segmentation violation on exit if the user's coordinate list
+ had fewer than 3 data points. Also improved the error messages
+ presented to the user in both interactive and non-interactive mode.
+ (7/7/93, Davis)
+
+pkg$images/imarith/icgdata.gx
+ There was an indexing error in setting up the ID array when using
+ the grow option. This caused the CRREJECT/CCDCLIP algorithm to
+ fail with a floating divide by zero error when there were non-zero
+ shifts. (5/26/93, Valdes)
+
+pkg$images/imarith/icmedian.gx
+ The median calculation is now done so that the original input data
+ is not lost. This slightly greater inefficiency is required so
+ that an output sigma image may be computed if desired. (5/10/93, Valdes)
+
+pkg$images/geometry/t_imshift.x
+ Added support for type ushort to the imshift task in cases where the
+ pixel shifts are integral.
+ (5/8/93, Davis)
+
+pkg$images/doc/rotate.hlp
+ Fixed a bug in the rotate task help page which implied that automatic
+ image size computation would occur if ncols or nlines were set no 0
+ instead of ncols and nlines.
+ (4/17/93, Davis)
+
+pkg$images/imarith/imcombine.gx
+ There was no error checking when writing to the output image. If
+ an error occurred (the example being when an imaccessible imdir was
+ set) obscure messages would result. Errchks were added.
+ (4/16/93, Valdes)
+
+pkg$images/doc/gauss.hlp
+ Fixed 2 sign errors in the equations in the documentation describing
+ the elliptical gaussian fucntion.
+ (4/13/92, Davis)
+
+pkg/images/imutil/t_imslice.x
+ Removed an error check in the imslice task, which was preventing it from
+ being used to reduce the dimensionality of images where the length of
+ the slice dimension is 1.0.
+ (2/16/83, Davis)
+
+pkg/images/filters/fmedian.x
+ The fmedian task was printing debugging information under iraf 2.10.2.
+ (1/25/93, Davis)
+
+pkg/images/imarith/icaclip.gx
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/icpclip.gx
+pkg/images/imarith/icsclip.gx
+ When using mclip=yes and when more pixels are rejected than allowed by
+ the nkeep parameter there was a subtle bug in how the pixels are added
+ back which can result in a segmentation violation.
+ if (nh == n2) ==> if (nh == n[i])
+ (1/20/93, Valdes)
+
+
+=======
+V2.10.1
+=======
+
+pkg/images/imarith/t_imcombine.x
+pkg/images/imarith/icaclip.gx
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/icgrow.gx
+pkg/images/imarith/iclog.x
+pkg/images/imarith/icombine.com
+pkg/images/imarith/icombine.gx
+pkg/images/imarith/icombine.h
+pkg/images/imarith/icpclip.gx
+pkg/images/imarith/icscale.x
+pkg/images/imarith/icsclip.gx
+pkg/images/imarith/icsetout.x
+pkg/images/imcombine.par
+pkg/images/doc/combine.hlp
+ The weighting was changed from using the square root of the exposure time
+ or image statistics to using the values directly. This corresponds
+ to variance weighting. Other options for specifying the scaling and
+ weighting factors were added; namely from a file or from a different
+ image header keyword. The \fInkeep\fR parameter was added to allow
+ controlling the maximum number of pixels to be rejected by the clipping
+ algorithms. The \fIsnoise\fR parameter was added to include a sensitivity
+ or scale noise component to the noise model. Errors will now delete
+ the output image.
+ (9/30/92, Valdes)
+
+pkg/images/imutil/imcopy.x
+ Added a call to flush after the status line printout so that the output
+ will appear immediately. (8/19/92, Davis)
+
+pkg/images/filters/mkpkg
+pkg/images/filters/t_fmedian.x
+pkg/images/filters/fmedian.x
+pkg/images/filters/fmd_buf.x
+pkg/images/filters/fmd_maxmin.x
+ The fmedian task could crash with a segmentation violation if mapping
+ was turned off (hmin = zmin and hmax = zmax) and the input image
+ contained data outside the range defined by zmin and zmax. (8/18/92, Davis)
+
+pkg/images/imarith/icaclip.gx
+pkg/images/imarith/iccclip.gx
+pkg/images/imarith/icpclip.gx
+pkg/images/imarith/icsclip.gx
+ There was a very unlikely possibility that if all the input pixels had
+ exactly the same number of rejected pixels the weighted average would
+ be done incorrectly because the dflag would not be set. (8/11/92, Valdes)
+
+pkg/images/imarith/icmm.gx
+ This procedure failed to set the dflag resulting in the weighted average
+ being computed in correctly. (8/11/92, Valdes)
+
+pkg/images/imfit/fit1d.x
+ At some point changes were made but not documented dealing with image
+ sections on the input/output. The changes seem to have left off the
+ final step of opening the output image using the appropriate image
+ sections. Because of this it is an error to use an image section
+ on an input image when the output image is different; i.e.
+
+ cl> fit1d dev$pix[200:400,*] junk
+
+ This has now been fixed. (8/10/92, Valdes)
+
+pkg/images/imarith/icscales.x
+ The zero levels were incorrectly scaled twice. (8/10/92, Valdes)
+
+pkg/images/imarith/icstat.gx
+ Contained the statement
+ nv = max (1., (Memi[v2+i] - Memi[v1+i]) / Memi[dv+i] + 1)
+ which is max(real,int). Changed the 1. to a 1. (8/10/92, Valdes)
+
+pkg$images/imarith/icaclip.gx
+pkg$images/imarith/iccclip.gx
+pkg$images/imarith/icsclip.gx
+ These files contained multiple cases (ten or so) of constructs such as
+ "max (1., ...)" or "max (0., ...)" where the ... could be either real
+ or double. In the double cases the DEC compiler complained about a
+ type mismatch since 1. is real. (8/10/92, Valdes)
+
+pkg$images/imfit/t_imsurfit.x
+ Fixed a bug in the section reading code. Imsurfit is supposed to switch
+ the order of the section delimiters in x and y if x2 < x1 or y2 < 1.
+ Unfortunately the y test was actually "if (y2 < x1)" instead of
+ "if (y2 < y1)". Whether or not the code actually works correctly
+ depends on the value of x1 relative to y2. This bug was not present
+ in 2.9.1 but is present in subsequent releases. (7/30/92 LED)
+
+=======
+V2.10.1
+=======
+
+pkg$images/filters/t_gauss.x
+ The case theta=90 and ratio > 0.0 but < 1.0 was producing an incorrect
+ convolution if bilinear=yes, because the major axis sigmas being
+ input along the x and y axes were sigma and ratio * sigma respectively
+ instead of ratio * sigma and sigma in this case.
+
+pkg$images/imutil/imcopy.x
+ Modified imcopy to write its verbose output to STDOUT instead of
+ STDERR. (6/24/92, Davis)
+
+pkg$images/imarith/imcombine.gx
+ The step where impl1$t is called to check if there is enough memory
+ did not set the return buffer because the values are irrelevant for
+ this check. However, depending on history, this buffer could have
+ arbitrary values and later when IMIO attempts to flush this buffer,
+ at least in the case of image type coersion, cause arithmetic errors.
+ The fix was to clear the returned buffers. (4/27/92, Valdes)
+
+pkg$images/imutil/t_imstack.x
+ Modified the imslice task to read the old and write a new axis map.
+ (4/23/92, Davis)
+
+pkg$images/geometry/t_imslice.x
+ Modified the imslice task to read the old and write a new axis map.
+ (4/23/92, Davis)
+
+pkg$images/geometry/t_blkavg.x
+pkg$images/geometry/t_blkrep.x
+ Modified the calls to mw_shift and mw_scale to explicitly set the
+ number of logical axes instead of using the default of 0.
+ (4/23/92, Davis)
+
+pkg$images/geometry/t_imtrans.x
+ Modified imtranspose so that it correctly picks up the axis map
+ and writes it to the output image wcs. (4/23/92, Davis)
+
+pkg$images/register.par
+pkg$images/geotran.par
+pkg$images/doc/register.hlp
+pkg$images/doc/geotran.hlp
+ Changed the default values of the parameters xscale and yscale in
+ the register and geotran tasks from INDEF to 1.0 (4/23/92, Davis)
+
+pkg$images/geometry/t_imtrans.x
+pkg$images/doc/imtranspose.hlp
+ Modified the imtranspose task so it does a true transpose of the
+ axes instead of simply modifying the lterm. (4/8/92, Davis)
+
+pkg$images/iminfo/listpixels.x
+ Added the formats parameter for formatting the output pixel coordinates
+ to the listpixels task. These formats take precedence over the formats
+ stored in the WCS in the image header and the previous default format.
+ (4/7/92, Davis)
+
+pkg$images/imutil/t_imstack.x
+ Added wcs support to the imstack task. (4/2/92, Davis)
+
+pkg$images/iminfo/listpixels.x
+ Modified listpixels so that it will work correctly if the dimension
+ of the wcs is less than the dimension of the image. (3/16/92, Davis)
+
+pkg$images/geometry/t_geotran.x
+ Modified the rotate, imlintran, register and geotran tasks wcs updating
+ code to deal correclty with dimensionally reduced data. (3/16/92, Davis)
+
+pkg$images/imarith/icalip.gx
+pkg$images/imarith/icclip.gx
+pkg$images/imarith/ipslip.gx
+pkg$images/imarith/icslip.gx
+pkg$images/imarith/icmedian.gx
+ The median calculation with an even number of points for short data
+ could overflow (addition of two short values) and be incorrect.
+ (3/16/92, Valdes)
+
+pkg$images/geometry/t_blkavg.x
+pkg$images/geometry/t_blkrep.x
+ 1. Improved the precision of the blkavg task wcs updating code.
+ 2. Changed the blkrep task wcs updating code so that it is consistent
+ with blkavg. This means that a blkrep command followed by a blkavg
+ command or vice versa will return the original coordinate system
+ to within machine precision. (3/16/92, Davis)
+
+pkg$images/iminfo/listpixels.x
+ Modified listpixels to print out an error if it could not open the
+ wcs in the image. (3/15/92, Davis)
+
+pkg$images/geometry/t_magnify.x
+ Fixed a bug in the magnify task wcs updating code which was not
+ working correctly for dimensionally reduced images. (3/15/92, Davis)
+
+pkg$images/geometry/t_imtrans.x
+ Fixed a bug in the imtranspose task wcs updating code which was not
+ working correctly for dimensionally reduced images. (3/14/92, Davis)
+
+pkg$images/imarith/icalip.gx
+pkg$images/imarith/icclip.gx
+pkg$images/imarith/icslip.gx
+ There was a bug allowing the number of valid pixels counter to become
+ negative. Also there was a step which should not be done if the
+ number of valid pixels is less than 1; i.e. all pixels rejected.
+ A test was put in to skip this step. (3/13/92, Valdes)
+
+pkg$images/iminfo/t_imslice.x
+pkg$images/doc/imslice.hlp
+ Added wcs support to the imslice task.
+ (3/12/92, Davis)
+
+pkg$images/iminfo/t_imstat.x
+ Fixed a bug in the code for computing the standard deviation, kurtosis,
+ and skew, wherein precision was being lost because two of the intermediate
+ variables in the computation were real instead of double precision.
+ (3/10/92, Davis)
+
+pkg$images/iminfo/listpixels.x
+ 1. Modified listpixels task to use the MWCS axis "format" attributes
+ if they are present in the image header.
+ 2. Added support for dimensionally reduced images, i.e.
+ images which are sections of larger images and whose coordinate
+ transformations depend on the reduced axes, to the listpixels task.
+ (3/6/92, Davis)
+
+pkg$images/imarith/t_imcombine.x
+pkg$images/imarith/icsetout.x
+ Changed error messages to say IMCOMBINE instead of ICOMBINE.
+ (3/2/92, Valdes)
+
+pkg$images/imarith/iclog.x
+ Added listing of read noise and gain. (2/10/92, Valdes)
+
+pkg$images/imarith/icscale.x
+pkg$images/imarith/icpclip.gx
+ 1. Datatype declaration for asumi was incorrect.
+ 2. Reduced the minimum number of images allowed for PCLIP to 3.
+ (1/7/92, Valdes)
+
+pkg$images/imarith/icgrow.gx
+ The first pixel to be checked was incorrectly set to 0 instead of 1
+ resulting in a segvio when using the grow option. (12/6/91, Valdes)
+
+pkg$images/imarith/icgdata.gx
+pkg$images/imarith/icscale.x
+ Fixed datatype declaration errors found by SPPLINT. (11/22/91, Valdes)
+
+pkg$images/iminfo/t_imstat.x
+ Fixed a bug in the kurtosis computation found by ST.
+ (Davis 10/11/91)
+
+pkg$images/iminfo/t_imstat.x
+pkg$images/doc/imstat.hlp
+ Corrected a bug in the mode computation in imstatistics. The parabolic
+ interpolation correction for computing the histogram peak was being
+ applied in the wrong direction. Note that for dev$pix the wrong answer
+ is actually closer to the expected answer than the correct answer
+ due to binning effects.
+ (Davis 9/24/91)
+
+pkg$images/filters/t_gauss.x
+ The code which computes the gaussian kernel was producing a divide by
+ zero error if ratio=0.0 and bilinear=yes (2.10 version only).
+ (Davis 9/18/91)
+
+pkg$images/doc/magnify.hlp
+ Corrected a bug in the magnify help page.
+ (Davis 9/18/91)
+
+pkg$images/imarith/icsclip.gx
+pkg$images/imarith/icaclip.gx
+pkg$images/imarith/iccclip.gx
+ There was a typo, Memr[d[k]+k] --> Memr[d[j]+k]. (9/17/91, Valdes)
+
+pkg$images/imarith/icstat.gx
+pkg$images/imarith/icmask.x
+ The offsets were used improperly in computing image statistics.
+ (Valdes, 9/17/91)
+
+pkg$images/geometry/t_imshift.x
+ The shifts file pointer was not being correctly initialized to NULL
+ in the case where no shifts file was declared. When the task
+ was invoked repeatedly from a script, this could result in an array being
+ referenced, for which space had not been previously allocated.
+ (Davis 7/29/91)
+
+pkg$images/imarith/imc* -
+pkg$images/imarith/ic* +
+pkg$images/imarith/t_imcombine.x
+pkg$images/imarith/mkpkg
+pkg$images/imarith/generic/mkpkg
+pkg$images/imcombine.par
+pkg$images/doc/imcombine.hlp
+ Replaced old version of IMCOMBINE with new version supporting masks,
+ offsets, and new algorithms. (Valdes 7/19/91)
+
+pkg$images/iminfo/imhistogram.x
+ Imhistogram has been modified to print the value of the middle of
+ histogram bin instead of the left edge if the output type is list
+ instead of plot. (Davis 6/11/91)
+
+pkg$images/t_imsurfit.x
+ Modified the sections file reading code to check the order of the
+ x1 x2 y1 y2 parameters and switch (x1,x2) or (y1,y2) if x2 < x1 or
+ y2 < y1 respectively. (Davis 5/28/91)
+
+pkg$images/listpixels.par
+pkg$images/iminfo/listpixels.x
+pkg$images/doc/listpixels.hlp
+ Modified the listpixels task to be able to print the pixel coordinates
+ in logical, physical or world coordinates. The default coordinate
+ system is still logical as before. (Davis 5/17/91)
+
+pkg$images/images.par
+pkg$images/doc/minmax.hlp
+pkg$images/imutil/t_minmax.x
+pkg$images/imutil/minmax.x
+ Minmax was modified to do the minimum and maximum values computations
+ in double precision or complex instead of real if the input image
+ pixel type is double precision or complex. Note that the minimum and
+ maximum header values are still stored as real however.
+ (Davis 5/16/91)
+
+imarith/t_imarith.x
+ There was a missing statement to set the error flag if the image
+ dimensions did not match. (5/14/91, Valdes)
+
+doc/imarith.hlp
+ Fixed some formatting problems in the imarith help page. (5/2/91 Davis)
+
+imarith$imcombine.x
+ Changed the order in which images are unmapped to have the output images
+ closed last. This is to allow file descriptors for the temporary image
+ used when updating STF headers. (4/22/91, Valdes)
+
+pkg$images/geometry/t_blkavg.x
+pkg$images/geometry/blkavg.gx
+pkg$images/geometry/blkavg.x
+ The blkavg task was partially modified to support complex image data.
+ The full modifications cannot be made because of an error in abavx.x
+ and the missing routine absux.x.
+ (4/18/91 Davis)
+
+pkg$images/geometry/geofit.x
+ The x and y fits cross-terms switch was not being set correctly to "yes"
+ in the case where xxorder=2 and xyorder=2 or in the case where yxorder=2
+ and yyorder=2.
+ (4/9/91 Davis)
+
+pkg$images/geometry/geogmap.x
+ Modified the line which prints the geometric parameters to use the
+ variable name xshift and yshift instead of delx and dely.
+ (4/9/91 Davis)
+
+pkg$images/imfit/imsurfit.x
+ Fixed a bug in the pixel rejection code which occurred when upper was >
+ 0.0 and lower = 0.0 or lower > 0 and upper = 0.0. The problem was that
+ the code was simply setting the rejection limits to the computed sigma
+ times the upper and lower parameters without checking for the 0.0
+ condition first. In the first case this results in all points with
+ negative residuals being rejected and in the latter all points with
+ positive residuals are rejected.
+ (2/25/91 Davis)
+
+pkg$images/doc/hedit.hlp
+pkg$images/doc/hselect.hlp
+pkg$images/doc/imheader.hlp
+pkg$images/doc/imgets.hlp
+ Added a reference to imgets in the SEE ALSO sections of the hedit and
+ hselect tasks.
+ Added a reference to hselect and hedit in the SEE ALSO sections of the
+ imheader and imgets tasks.
+ (2/22/91 Davis)
+
+pkg$images/gradient.hlp
+pkg$images/laplace.hlp
+pkg$images/gauss.hlp
+pkg$images/convolve.hlp
+pkg$images/gradient.par
+pkg$images/laplace.par
+pkg$images/gauss.par
+pkg$images/convolve.par
+pkg$images/t_gradient.x
+pkg$images/t_laplace.x
+pkg$images/t_gauss.x
+pkg$images/t_convolve.x
+pkg$images/convolve.x
+pkg$images/xyconvolve.x
+pkg$images/radcnv.x
+ The convolution operators were modified to run more efficiently in
+ certain cases. The LAPLACE task was modified to make use of the
+ radial symmetry of the convolution kernel in the y direction as well
+ as the x direction resulting in a modest speedup in execution time.
+ A new parameter bilinear was added to the GAUSS and CONVOLVE tasks.
+ By default and if appropriate mathematically, GAUSS now makes use of
+ the bilinearity or separability of the Gaussian function,
+ to separate the 2D convolution in x and y into two equivalent
+ 1D convolutions in x and y, resulting in a considerable speedup
+ in execution time. Similarly the user can know program CONVOLVE to
+ compute a bilinear convolution instead of a full 2D 1 if appropriate.
+ (1/29/91 Davis)
+
+pkg$images/filters/t_convolve.x
+ CONVOLVE was not decoding the legal 1D kernel "1.0 2.0 1.0" correctly
+ although the alternate form "1.0 2.0 1.0;" worked. Leading
+ blanks in string kernels as in for example " 1.0 2.0 1.0" also generated
+ and error. Fixed these bugs and added some additional error checking code.
+ (11/28/90 Davis)
+
+pkg$images/doc/gauss.hlp
+ Added a detailed mathematical description of the gaussian kernel used
+ by the GAUSS task to the help page.
+
+pkg$images/images.hd
+pkg$images/rotate.cl
+pkg$images/imlintran.cl
+pkg$images/register.cl
+pkg$images/register.par
+ Added src="script file name" entries to the IMAGES help database
+ for the tasks ROTATE, IMLINTRAN, and REGISTER. Changed the CL
+ script for REGISTER to a procedure script to remove the ugly
+ local variable declarations. Added a few comments to the scripts.
+ (12/11/90, Davis)
+
+pkg$images/iminfo/imhistogram.x
+ Added a new parameter binwidth to imhistogram. If binwidth is defined
+ it determines the histogram resolution in intensity units, otherwise
+ nbins determines the resolution as before. (10/26/90, Davis)
+
+pkg$images/doc/sections.hlp
+ Clarified what is meant by an image template and that the task itself
+ does not check whether the specified names are actually images.
+ The examples were improved. (10/3/90, Valdes)
+
+pkg$images/doc/fit1d.hlp
+ Changed lines to columns in example 2. (10/3/90, Valdes)
+
+pkg$images/imarith/imcscales.x
+ When an error occured while parsing the mode section the untrapped error
+ caused further problems downstream. Because it would require adding
+ lots of errchks to cause the program to gracefully abort I instead made
+ it a warning. (10/2/90, Valdes)
+
+pkg$images/imutil/hedit.x
+ Hedit was computing but not using min_lenarea. If the user specified
+ a min_lenuserarea greater than the default of 28800 then the default
+ was being used instead of the larger number.
+
+pkg$imarith/imasub.gx
+ The case of subtracting an image from the constant zero had a bug
+ which is now fixed. (8/14/90, Valdes)
+
+pkg$images/t_imtrans.x
+ Modified the imtranspose task so it will work on type ushort images.
+ (6/6/90 Davis)
+
+pkg$images
+ Added world coordinate system support to the following tasks: imshift,
+ shiftlines, magnify, imtranspose, blkrep, blkavg, rotate, imlintran,
+ register and geotran. The only limitation is that register and geotran
+ will only support simple linear transformations.
+ (2/24/90 Davis)
+
+pkg$images/geometry/geotimtran.x
+ Fixed a problem in the boundary extension "reflect" option code for small
+ images which was causing odd values to be inserted at the edges of the
+ image.
+ (2/14/90 Davis)
+
+pkg$images/iminfo/imhistogram.x
+ A new parameter "hist_type" was added to the imhistogram task giving
+ the user the option of plotting the integral, first derivative and
+ second derivative of the histogram as well as the normal histogram.
+ Code was contributed by Rob Seaman.
+ (2/2/90 Davis)
+
+pkg$images/geometry/geogmap.x
+ The path name of the help file was being erroneously renamed with
+ the result that when users ran the double precision version of the
+ code they could not find the help file.
+ (26/1/90 Davis)
+
+pkg$images/filters/t_boxcar.x,t_convolve.x
+ Added some checks for 1-D images.
+ (1/20/90 Davis)
+
+pkg$images/iminfo/t_imstat.x,imstat.h
+ Made several minor bug fixes and alterations in the imstatistics task
+ in response to user complaints and suggestions.
+
+ 1. Changed the verbose parameter to the format parameter. If format is
+ "yes" (the default) then the selected fields are printed in fixed format
+ with column labels. Other wise the fields are printed in free format
+ separated by 2 blanks. This fixes the problem of fields running together.
+
+ 2. Fixed a bug in the code which estimates the median from the image
+ histogram by linearly interpolating around the midpt of the integrated
+ histogram. The bug occurred when more than half the pixels were in the
+ first bin.
+
+ 3. Added a check to ensure that the number of fields did not overflow
+ the fields array.
+
+ 4. Removed the extraneous blank line printed after the title.
+
+ 5. The pound sign is now printed at the beginning of the column header
+ string regardless of which field is printed first. In the previous
+ versions it was only being printed if the image name field was
+ printed first.
+
+ 6. Changed the name of the median field to midpt in response to user
+ confusions about how the median is computed.
+
+ (1/20/90, Davis)
+
+pkg$images/imutil/t_imslice.hlp
+ The imslice was not correctly computing the number of lines in the
+ output image in the case where the slice dimension was 1.
+ (12/4/89, Davis)
+
+pkg$images/doc/imcombine.hlp
+ Clarified and documented definitions of the scale, offset, and weights.
+ (11/30/89, Valdes)
+
+pkg$images/geometry/geotran.x
+ High order surfaces of a certain functional form could occasionally
+ produce out of bounds pixel errors. The bug was caused by not properly
+ computing the distortion of the image boundary for higher order
+ surfaces.
+ (11/21/89, Davis)
+
+pkg$images/geometry/imshift.x
+ The circulating buffer space was not being freed after each execution
+ of IMSHIFT. This did not cause an error in execution but for a long
+ list of frames could result in alot of memory being tied up.
+ (10/25/89, Davis)
+
+pkg$images/imarith/t_imarith.x
+ IMARITH is not prepared to deal with images sections in the output.
+ It used to look for '[' to decide if the output specification included
+ and image section. This has been changed to call the IMIO procedure
+ imgsection and check if a non-null section string is returned.
+ Thus it is up to IMIO to decide what part of the image name is
+ an image section. (9/5/89, Valdes)
+
+pkg$images/imarith/imcmode.gx
+ Fixed bug causing infinite loop when computing mode of constant value
+ section. (8/14/89, Valdes)
+
+====
+V2.8
+====
+
+pkg$images/iminfo/t_imstat.x
+ Davis, Jun 15, 1989
+ Added a couple of switches to that skew and kurtosis are not computed
+ if they are not to be printed.
+
+pkg$images/iminfo/t_imstat.x
+ Davis, Jun 14, 1989
+ A simple mod was made to the skew and kurtosis computation to avoid
+ divide by zero errors in case of underflow.
+
+pkg$images/imutil/chpixtype.par
+ Davis, Jun 13, 1989
+ The parameter file has been modified to accept an output pixel
+ type of ushort.
+
+pkg$images/imarith/imcombine.gx
+ Valdes, Jun 2, 1989
+ A new scheme to detect file errors is now used.
+
+pkg$images/imfit/t_imsurfit.x
+ Davis, Jun 1, 1989
+ 1. If the user set regions = "sections" but the sections file
+ did not exist the task would go into an infinite loop. The problem
+ was a missing error check on the open statement.
+
+pkg$images/iminfo/imhistogram.x,imhistogram.par
+ Davis, May 31, 1989
+ A new version of imhistogram has been installed. These mods have
+ been made over a period of a month by Doug Tody and Rob Seaman.
+ The mods include
+ 1. An option to turn off log scaling of the y axis of the histogram plot.
+ 2. A new autoscale parameter which avoids aliasing problems for integer
+ data.
+ 3. A new parameter top_close which resolves the ambiguity in the top
+ bin of the histogram.
+
+pkg$images/imarith/imcombine.gx
+ Valdes, May 9, 1989
+ Because a file descriptor was not reserved for string buffer operations
+ and a call to stropen in cnvdate was not error checked the task would
+ hang when more than 115 images were combined. Better error checking
+ was added and now an error message is printed when the maximum number
+ of images that can be combined is exceeded.
+
+pkg$images/imarith/t_imarith.x
+ Valdes, May 6, 1989
+ Operations in which the output image has an image section are now
+ skipped with a warning message.
+
+pkg$images/imarith/sigma.gx
+pkg$images/imarith/imcmode.gx
+ Valdes, May 6, 1989
+ 1. The weighted sigma was being computed incorrectly.
+ 2. The argument declarations were wrong for integer input images.
+ Namely the mean vector is always real.
+ 3. Minor change to imcmode.gx to return correct datatype.
+
+pkg$images/imstack,imslice
+ Davis, April 1, 1989
+ The proto images tasks imstack and imslice have been moved from the
+ proto package to the images package. Imstack is unchanged except that
+ it now supports the image data types USHORT and COMPLEX. Imslice has
+ been modified to allow slicing along any dimension of the image instead
+ of just the highest dimension.
+
+pkg$images/imstatistics.
+ Davis, Mar 31, 1989
+ 1. A totally new version of the imstatistics task has been written
+ and replaces the old version. The new task allows the user to select
+ which statistical parameters to compute and print. These include
+ the mean, median, mode, standard deviation, skew, kurtosis and the
+ minimum and maximum pixel values.
+
+pkg$images/imhistogram.par
+pkg$images/iminfo/imhistogram.x
+pkg$images/doc/imhistogram.hlp
+ Davis, Mar 31, 1989
+ 1. The imhistogram task has been modified to plot "box" style histograms
+ as well as "line" type histograms. Type "line" remains the default.
+
+pkg$images/geometry/geotran.par,register.par,geomap.par
+pkg$images/doc/geomap.hlp,register.hlp,geotran.hlp
+ Davis, Mar 6, 1989
+ 1. Improved the parameter prompting in GEOMAP, REGISTER and GEOTRAN
+ and improved the help pages.
+ 2. Changed GEOMAP database quantities "xscale" and "yscale" to "xmag"
+ and "ymag" for consistency . Geotran was changed appropriately.
+
+pkg$images/imarith/imcmode.gx
+ For short data a short variable was wraping around when there were
+ a significant number of saturated pixels leading to an infinite loop.
+ The variables were made real regardless of the image datatype.
+ (3/1/89, Valdes)
+
+pkg$images/imutil/imcopy.x
+ Davis, Feb 28, 1989
+ 1. Added support for type USHORT to the imcopy task. This is a merged
+ ST modification.
+
+pkg$images/imarith/imcthreshold.gx
+pkg$images/imcombine.par
+pkg$images/doc/imcombine.hlp
+pkg$images/imarith/imcscales.x
+ Valdes, Feb 16, 1989
+ 1. Added provision for blank value when all pixels are rejected by the
+ threshold.
+ 2. Fixed a bug that was improperly scaling images in the threshold option.
+ 3. The offset printed in the log now has the opposite sign so that it
+ is the value "added" to bring images to a common level.
+
+pkg$images/imfit/imsurfit.x
+ Davis, Feb 23, 1989
+ Fixed a bug in the median fitting code which could cause the porgram
+ to go into an infinite loop if the region to be fitted was less than
+ the size of the whole image.
+
+pkg$images/geometry/t_magnify.x
+ Davis, Feb 16, 1989
+ Modified magnify to work on 1D images as well as 2D images. The
+ documentation has been updated.
+
+pkg$images/geometry/t_geotran.x
+ Davis, Feb 15, 1989
+ Modified the GEOTRAN and REGISTER tasks so that they can handle a list
+ of transform records one for each input image.
+
+pkg$images/imarith/imcmode.gx
+ Valdes, Feb 8, 1989
+ Added test for nx=1.
+
+pkg$images/imarith/t_imcombine.x
+ Valdes, Feb 3, 1989
+ The test for the datatype of the output sigma image was wrong.
+
+pkg$images/iminfo/listpixels.x,listpixels.par
+ Davis, Feb 6, 1989
+ The listpixels task has been modified to print out the pixels for a
+ list of images instead of a single image only. A title line for each
+ image listed can optionally be printed on the standard output if
+ the new parameter verbose is set to yes.
+
+pkg$images/geometry/t_imshift.x
+ Davis, Feb 2, 1989
+ Added a new parameter shifts_file to the imshift task. Shifts_file
+ is the name of a text file containing the the x and yshifts for
+ each input image to be shifted. The number of input shifts must
+ equal the number of input images.
+
+pkg$images/geometry/t_geomap.x
+ Davis, Jan 17, 1989
+ Added an error message for the case where the coordinates is empty
+ of there are no points in the specified data range. Previously the
+ task would proceed to the next coordinate file without any message.
+
+pkg$images/geometry/t_magnify.x
+ Davis, Jan 14, 1989
+ Added the parameter flux conserve to the magnify task to bring it into
+ line with all the other geometric transformation tasks.
+
+pgk$images/geometry/geotran.x,geotimtran.x
+ Davis, Jan 2, 1989
+ A bug was fixed in the flux conserve code. If the x and y reference
+ coordinates are not in pixel units and are not 1 then
+ the computed flux per pixel was too small by xscale * yscale.
+
+pkg$images/filters/acnvrr.x,convolve.x,boxcar.x,aboxcar.x
+ Davis, Dec 27, 1988
+ I changed the name of the acnvrr procedure to cnv_radcnvr to avoid
+ a name conflict with a vops library procedure. This only showed
+ up when shared libraries were implemented. I also changed the name
+ of the aboxcarr procedure to cnv_aboxr to avoid conflict with the
+ vops naming conventions.
+
+pkg$images/imarith/imcaverage.gx
+ Davis, Dec 22, 1988
+ Added an errchk statement for imc_scales and imgnl$t to stop the
+ program bombing with segmentation violations when mode <= 0.
+
+pkg$images/imarith/imcscales.x
+ Valdes, Dec 8, 1988
+ 1. IMCOMBINE now prints the scale as a multiplicative quantity.
+ 2. The combined exposure time was not being scaled by the scaling
+ factors resulting in a final exposure time inconsistent with the
+ data.
+
+pkg$images/iminfo/imhistogram.x
+ Davis, Nov 30, 1988
+ Changed the list+ mode so that bin value and count are printed out instead
+ of bin count and value. This makes the plot and list modes compatable.
+
+pkg$images/iminfo/t_imstat.x
+ Davis, Nov 17, 1988
+ Added the n=n+1 back into the inner loop of imstat.
+
+pkg$images/geotran.par,register.par
+ Davis, Nov 11 , 1988
+ Fixed to glaring errors in the parameter files for register and geotran.
+ Xscale and yscale were described as pixels per reference unit when
+ they should be reference units per pixel. The appropriate bug fix has been
+ made.
+
+pkg$images/geometry/t_geotran.x
+ Davis, November 7, 1988
+ The routine gsrestore was not being error checked. If either of the
+ input x or y coordinate surface was linear and the other was not,
+ the message came back GSRESTORE: Illegal x coordinate. This bug has
+ been fixed.
+
+pkg$images/imarith/imcombine.gx
+ Valdes, October 19, 1988
+ A vops clear routine was not called generically causing a crash with
+ double images.
+
+pkg$images/filters/t_fmedian.x,t_median.x,t_fmode.x,t_mode.x,t_gradient.x
+ t_gauss.x,t_boxcar.x,t_convolve.x,t_laplace.x
+ Davis, October 4, 1988
+ I fixed a bug in the error handling code for the filters tasks. If
+ and error occurred during task execution and the input image name was
+ the same as the output image name then the input image was trashed.
+
+pkg$images/imarith/imcscales.gx
+ Valdes, September 28, 1988
+ It is now an error for the mode to be nonpositive when scaling or weighting.
+
+pkg$images/imarith/imcmedian.gx
+ Valdes, August 16, 1988
+ The median option was selecting the n/2 value instead of (n+1)/2. Thus,
+ for an odd number of images the wrong value was being determined for the
+ median.
+
+pkg$images/geometry/t_imshift.x
+ Davis, August 11, 1988
+ 1. Imshift has been modified to uses the optimized code if nearest
+ neighbour interpolation is requested. A nint is done on the shifts
+ before calling the quick shift routine.
+ 2. If the requested pixel shift is too large imshift will now
+ clean up any pixelless header files before continuing execution.
+
+pkg$images/geometry/blkavg.gx
+ Davis, July 13, 1988
+ Blkavg has been fixed so that it will work on 1D images.
+
+pkg$images/geometry/t_imtrans.x,imtrans.x
+ Davis, July 12, 1988
+ Imtranspose has been modified to work on complex images.
+
+pkg$images/imutil/t_chpix.x
+ Davis, June 29, 1988
+ A new task chpixtype has been added to the images package. Chpixtype
+ changes the pixel types of a list of images to a specified output pixel
+ type. Seven data types are supported "short", "ushort", "int", "long"
+ "real" and "double".
+
+pkg$images/geometry/rotate.cl,imlintran.cl,t_geotran.x
+ Davis, June 10, 1988
+ The rotate and imlintran scripts have been rewritten to use procedure
+ scripts. This removes all the annoying temporary cl variables which
+ appear when the user does an lpar. In previous versions of these
+ two tasks the output was restricted to being the same size as the input
+ image. This is still the default case, but the user can now set the
+ ncols and nrows parameters to the desired output size. I ncols or nlines
+ < 0 then then the task compute the output image size required to contain
+ the whole input image.
+
+pkg$images/filters/t_convolve.x,t_laplace.x,t_gradient.x,t_gauss.x,convolve.x
+ Davis, June 1, 1988
+ The convolution operators laplace, gauss and convolve have been modified
+ to make use of radial symmetry in the convolution kernel. In gauss and
+ laplace the change is transparent to the user. For the convolve operator
+ the user must indicate that the kernel is radially symmetric by setting
+ the parameter radsym. For kernels of 7 by 7 or greater the speedup
+ in timings is on the order of 30% on the Vax 750 with the fpa.
+
+pkg$images/imarith/imcmode.gx
+ Valdes, Apr 11, 1988
+ 1. The use of a mode sections was handled incorrectly.
+
+pkg$images/imfit/fit1d.x
+ Valdes, Jan 4, 1988
+ 1. Added an error check for a failure in IMMAP. The missing error check
+ caused FIT1D to hang when a bad input image was specified.
+
+pkg$images/magnify.par
+pkg$images/imcombine.par
+pkg$images/imarith/imcmode.gx
+pkg$images/doc/imarith.hlp
+ Valdes, Dec 7, 1987
+ 1. Added option list to parameter prompts.
+ 2. Fixed minor typo in help page
+ 3. The mode calculation in IMCOMBINE would go into an infinite loop
+ if all the pixel values were the same. If all the pixels are the
+ same them it skips searching for the mode and returns the constant
+ number.
+
+pkg$images/geometry/geotimtran.x
+ Davis, Nov 25, 1987
+ 1. A bug in the boundary extension = wrap option was found in the
+ IMLINTRAN task. The problem occured in computing values for out of
+ bounds pixels in the range 0.0 < x < 1.0, ncols < x < ncols + 1.0,
+ 0.0 < y < 1.0 and nlines < y < nlines + 1. The computed coordinates
+ were falling outside the boundaries of the interpolation array.
+
+pkg$images/geometry/t_geomap.x,geograph.x
+ Davis, Nov 19, 1987
+ 1. The geomap task now writes the name of the output file into the database.
+ 2. Rotation angles of 360. degrees have been altered to 0 degrees.
+
+pkg$images/imfit/t_imsurfit.x,imsurfit.x
+pkg$images/lib/ranges.x
+ Davis, Nov 2, 1987
+ A bug in the regions fitting option of the IMSURFIT task has been found
+ and fixed. This bug would occur when the user set the regions parameter
+ to sections and then listed section which overlapped each other. The
+ modified ranges package was not handling the overlap correctly and
+ computing a number of points which was incorrect.
+
+pkg$images/imarith/* +
+ Valdes, Sep 30, 1987
+ The directory was reorganized to put generic code in the subdirectory
+ generic.
+
+ A new task called IMCOMBINE has been added. It provides for combining
+ images by a number of algorithms, statistically weighting the images
+ when averaging, scaling or offsetting the images by the exposure time
+ or image mode before combining, and rejecting deviant pixels. It is
+ almost fully generic including complex images and works on images of
+ any dimension.
+
+pkg$images/geometry/geotran.x
+ Davis, Sept 3, 1987
+ A bug in the flux conserving algorithm was found in the geotran code.
+ The symptom was that the flux of the output image occasionally was
+ negative. This would happen when two conditions were met, the transformation
+ was of higher order than a simple rotation, magnification, translation
+ and an axis flip was involved. The mathematical interpretation of this
+ bug is that the coordinate surface had turned upside down. The solution
+ for people running systems with this bug is to multiply there images
+ by -1.
+
+pkg$images/imfit/imsurfit.h,t_imsurfit.x
+ Davis, Aug 6, 1987
+ A new option was added to the parameter regions in the imsurfit task.
+ Imsurfit will now fit a surface to a single circular region defined
+ by an x and y center and a radius.
+
+pkg$images/geometry/geotimtran.x
+ Davis, Jun 15, 1987
+ Geotran and register were failing when the output image number of rows
+ and columns was different from the input number of rows and columns.
+ Geotran was mistakenly using the input images sizes to determine the
+ number of output lines that should be produced. The same problem occurred
+ when the values of the boundary pixels were being computed. The program
+ was using the output image dimensions to compute the boundary pixels
+ instead of the input image dimensions.
+
+pkg$images/geometry/geofit.x,geogmap.x
+ Davis, Jun 11, 1987
+ A bug in the error checking code in the geomap task was fixed. The
+ condition of too few points for a reasonable was not being trapped
+ correctly. The appropriate errchk statements were added.
+
+pkg$images/geomap.par
+ Davis, Jun 10, 1987
+ The default fitting function was changed to polynomial. This will satisfy
+ most users who wish to do shifts, rotations, and magnifications and
+ avoid the neccessity of correctly setting the xmin, xmax, ymin, and ymax
+ parameters. For the chebyshev and legendre polynomial functions these
+ parameters must be explicitly set. For reference coordinates in pixel
+ units the normal settings are 1, ncols, 1 and nlines respectively.
+
+pkg$images/iminfo/hselect.x,imheader.x,images$/imutil/hselect.x
+ Davis, Jun 8, 1987
+ Imheader has been modified to open an image with the default min_lenuserarea
+ Hselect and hedit will now open the image setting the user area to the
+ maximum of 28800 chars or the min_lenuser environment variable.
+
+pkg$images/iminfo/t_imstat.x
+ Davis, May 22, 1987
+ An error in the image minimum computation was corrected. This error
+ would show up most noiticeably if imstat was run on a 1 pixel image.
+ The min value would be left set to MAX_REAL.
+
+pkg$images/filters/mkpkg
+ Davis, May 22, 1987
+ I added mach.h to the dependency file list of t_fmedian.x and
+ recompiled. The segmentation violations I had been getting in the
+ program disappeared.
+
+pkg$images/t_shiftlines.x,shiftlines.x
+ Davis, April 15, 1987
+ 1. I changed the names of the procedures shiftlines and shiftlinesi
+ to sh_lines and sh_linesi. When the original names were contracted
+ to 6 letter fortran names they became shifti and shifts which just
+ so happens to collide with shifti and shifts in the subdirectory
+ osb. On VMS this was causing problems with the shareable libraries.
+ If images was linked with -z there was no problem.
+
+pkg$images/imarith/t_imsum.x
+ Valdes, March 24, 1987
+ 1. IMSUM was failing to unmap images opened to check image dimensions
+ in a quick first pass through the image list. This is probably
+ the source of the out of files problem with STF images. It may
+ be the source of the out of memory problem reported from AOS/IRAF.
+
+pkg$images/imfit/fit1d.x
+pkg$images/imfit/mkpkg
+ Valdes, March 17, 1987
+ 1. Added error checking for the illegal operation in which both input
+ and output image had an image section. This was causing the task
+ to crash. The task now behaves properly in this circumstance and
+ even allows the fitted output to be placed in an image section of
+ an existing output image (even different than the input image
+ section) provided the input and output images have the same sizes.
+
+pkg$images/t_convolve.x
+ Davis, March 3, 1987
+ 1. Fixed the kernel decoding routine in the convolve task so that
+ it now recognizes the row delimter character in string entry mode.
+
+pkg$images/geometry,filters
+ Davis, February 27, 1987
+ 1. Changed all the imseti (im, TY_BNDRYPIXVAL, value) calls to imsetr.
+
+pkg$images/t_minmax.x,minmax.x
+ Davis, February 24, 1987
+ 1. Minmax has been changed to compute the minimum and maximum pixel
+ as well as the minimum and maximum pixel values. The pixels are output
+ in section notation and stored in the minmax parameter file.
+
+pkg$images/t_magnify.x
+ Davis, February 19, 1987
+ 1. Magnify was aborting with the error MSIFIT: Too few datapoints
+ when trying to reduce an image using the higher order interpolants
+ poly3, poly5 and spline3. I increased the NEDGE defined constant
+ from 2 to three and modified the code to use the out of bounds
+ imio.
+
+pkg$images/geograph.x,geogmap.x
+ Davis, February 17, 1987
+ 1. Geomap now uses the gpagefile routine to page the .keys file.
+ The :show command deactivates the workstation before printing a
+ block of text and reactivates it when it is finished.
+
+pkg$images/geometry/geomap,geotran
+ Davis, January 26, 1987
+ 1. There have been substantial changes to the geomap, and geotrans
+ tasks and those tasks rotate, imlintran and register which depend
+ on them.
+ 2. Geomap has been changed to be able to compute a transformation
+ in both single and double precision.
+ 3. The geotran code has been speeded up considerably. A simple rotate
+ now takes 70 seconds instead of 155 seconds using bilinear interpolation.
+ 4. Two new cl parameters nxblock and nyblock have been added to the
+ rotate, imlintran, register and geotran tasks. If the output image
+ is smaller than these parameters then the entire output image
+ is computed at once. Otherwise the output image is computed in blocks
+ nxblock by nyblock in size.
+ 5. The 3 geotran parameters rotation, scangle and flip have been replaced
+ with two parameters xrotation and yrotation which serve the same purpose.
+
+pkg$images/geometry/t_shiftlines.x,shiftlines.x
+ Davis, January 19, 1987
+ 1. The shiftlines task has been completely rewritten. The following
+ are the major changes.
+ 2. Shiftlines now makes use of the imio boundary extension operations.
+ Therefore the four options: nearest pixel, reflect, wrap and constant
+ boundary extension are available.
+ 3. The interpolation code has been vectorised. The previous version
+ was using the function call asieval for every output pixel evaluated.
+ The asieval call were replaced with asivector calls.
+ 4. An extra CL parameter constant to support constant boundary
+ exension was added.
+ 5. The shiftlines help page was modified and the date changed to
+ January 1987.
+
+pkg$images/imfit/imsurfit.x
+ Davis, January 12, 1987
+ 1. I changed the amedr call to asokr calls. For my application it did
+ not matter whether the input array is left partially sorted and the asokr
+ routine is more efficient.
+
+pkg$images/lib/pixlist.x
+ Davis, December 12, 1986
+ 1. A bug in the pl_get_ranges routine caused the routine to fail when the
+ number of ranges got too large. The program could not detect the end of
+ the ranges and would go into an infinite loop.
+
+pkg$images/iminfo/t_imstat.x
+ Davis, December 3, 1986
+ 1. Imstat was failing on constant images because finite machine precision
+ could result in a negative sigma squared. Added a check for this condition.
+
+pkg$images/filters/fmode.x
+ Davis, October 27, 1986
+ 1. Added a check for 0 data range before calling amapr.
+
+pkg$images/imarith/imsum.gx
+ Valdes, October 20, 1986
+ 1. Found and fixed bug in this routine which caused pixel rejection
+ to fail some fraction of the time.
+
+pkg$images/geometry/blkrp.gx
+ Valdes, October 13, 1986
+ 1. There was a bug when the replication factor for axis 1 was 1.
+
+pkg$images/iminfo/imhistogram.x
+ Hammond, October 8, 1986
+ 1. Running imhistogram on a constant valued image would result in
+ a "floating divide by zero fault" in ahgm. This condition is
+ now trapped and a warning printed if there is no range in the data.
+
+pkg$images/tv/doc/cvl.hlp
+ Valdes, October 7, 1986
+ 1. Typo in V2.3 documentation fixed: "zcale" -> "zscale".
+
+pkg$images/fit1d.par
+ Valdes, October 7, 1986
+ 1. When querying for the output type the query was:
+
+Type of output (fit, difference, ratio) (fit|difference|ratio) ():
+
+ The enumerated values were removed since they are given in the
+ prompt string.
+
+pkg$images/imarith/t_imsum.x
+pkg$images/imarith/imsum.gx
+pkg$images/do/imsum.hlp
+ Valdes, October 7, 1986
+ 1. Medians or pixel rejection with more than 15 images is now
+ correct. There was an error in buffering.
+ 2. Averages of integer datatype images are now correct. The error
+ was caused by summing the pixel values divided by the number
+ of images instead of summing the pixel values and then dividing
+ by the number of images.
+ 3. Option keywords may now be abbreviated.
+ 4. The output pixel datatype now defaults to the calculation datatype
+ as is done in IMARITH. The help page was modified to indicate this.
+ 5. Dynamic memory is now used throughout to reduce the size of the
+ executable.
+ 6. The bugs 1-2 are present in V2.3 and not in V2.2.
+
+pkg$images/imarith/t_imarith.x
+pkg$images/imarith.par
+pkg$images/doc/imarith.hlp
+ Valdes, October 6, 1986
+ 1. The parameter "debug" was changed to "noact". "debug" is reserved
+ for debugging information.
+ 2. The output pixel type now defaults to the calculation datatype.
+ 3. The datatype of constant operands is determined with LEXNUM. This
+ fixes a bug in which a constant such as "1." was classified as an
+ integer.
+ 4. Trailing whitespace in the string for a constant operand is allowed.
+ This fixes a bug with using "@" files created with the task FIELDS
+ from a table of numbers. Trailing whitespace in image names is
+ not checked for since this should be taken care of by lower level
+ system services.
+ 5. The reported bug with the "max" operation not creating a pixel file
+ was the result of the previous round of changes. This has been
+ corrected. This problem does not exist in the released version.
+ 6. All strings are now dynamically allocated. Also IMTOPENP is used
+ to open a CL list directly.
+ 7. The help page was revised for points (1) and (2).
+
+pkg$images/fmode.par
+pkg$images/fmd_buf.x
+pkg$images/med_sort.x
+ Davis, September 29, 1986
+ 1. Changed the default value of the unmap parameter in fmode to yes. The
+ documentation was changed and the date modified.
+ 2. Added a test to make sure that the input image was not a constant
+ image in fmode and fmedian.
+ 3. Fixed the recently added swap macro in the sort routines which
+ was giving erroneous results for small boxes in tasks median and mode.
+
+pkg$images/imfit/fit1d.x
+ Valdes, September 24, 1986
+ 1. Changed subroutine name with a VOPS prefix to one with a FIT1D
+ prefix.
+
+pkg$images/imarith/t_imdivide.x
+pkg$images/doc/imdivide.hlp
+pkg$images/imdivide.par
+ Valdes, September 24, 1986
+ 1. Modified this ancient and obsolete task to remove redundant
+ subroutines now available in the VOPS library.
+ 2. The option to select action on zero divide was removed since
+ there was only one option. Parameter file changed.
+ 3. Help page revised.
+
+pkg$images/geometry/t_blkrep.x +
+pkg$images/geometry/blkrp.gx +
+pkg$images/geometry/blkrep.x +
+pkg$images/doc/blkrep.hlp +
+pkg$images/doc/mkpkg
+pkg$images/images.cl
+pkg$images/images.men
+pkg$images/images.hd
+pkg$images/x_images.x
+ Valdes, September 24, 1986
+ 1. A new task called BLKREP for block replicating images has been added.
+ This task is a complement to BLKAVG and performs a function not
+ available in any other way.
+ 2. Help for BLKREP has been added.
+
+pkg$images/imarith/t_imarith.x
+pkg$images/imarith/imadiv.gx
+pkg$images/doc/imarith.hlp
+pkg$images/imarith.par
+ Valdes, September 24, 1986
+ 1. IMARITH has been modified to provide replacement of divisions
+ by zero with a constant parameter value.
+ 2. The documentation has been revised to include this change and to
+ clarify and emphasize areas of possible confusion.
+
+pkg$images/doc/magnify.hlp
+pkg$images/doc/blkavg.hlp
+ Valdes, September 18, 1986
+ 1. The MAGNIFY help document was expanded to clarify that images with axis
+ lengths of 1 cannot be magnified. Also a discussion of the output
+ size of a magnified image. This has been misunderstood often.
+ 2. Minor typo fix for BLKAVG.
+
+images$geometry/blkav.gx: Davis, September 7, 1986
+ 1. The routine blkav$t was declared a function but called everywhere as
+ a procedure. Removed the function declaration.
+
+images$filters/med_sort.x: Davis, August 14, 1986
+ 1. A bug in the sorting routine for MEDIAN and MODE in which the doop
+ loop increment was being set to zero has been fixed. This bug was
+ causing MEDIAN and MODE to fail on class 6 for certain sized windows.
+
+images$imfit/fit1d.x: Davis, July 24, 1986
+ 1. A bug in the type=ratio option of fit1d was fixed. The iferr call
+ on the vector operator adivr was not trapping a divide by zero
+ condition. Changed adivr to adivzr.
+
+images$iminfo/listpixels.x: Davis, July 21, 1986
+ 1. I changed a pargl to pargi for writing out the column number of the
+ pixels.
+
+images$iminfo/t_imstat.x: Davis, July 21, 1986
+ 1. I changed a pargr to a pargd for the double precision quantitiies
+ sum(MIN) and sum(MAX).
+
+images$imfit/t_lineclean.x: Davis, July 14, 1986
+ 1. Bug in the calling sequence for ic_clean fixed. The ic pointer
+ was not being passed to ic_clean causing access violation and/or
+ segmentation violation errors.
+
+images$imfit/fit1d.x, lineclean.x: Valdes, July 3, 1986
+ 1. FIT1D and LINECLEAN modified to use new ICFIT package.
+
+From Valdes June 19, 1986
+
+1. The help page for IMSUM was modified to explicitly state what the
+median of an even number of images does.
+
+-----------------------------------------------------------------------------
+
+From Davis June 13, 1986
+
+1. A bug in CONVOLVE in which insufficient space was being allocated for
+long (> 161 elements) 1D kernels has been fixed. CONVOLVE was not
+allocating sufficent extra space.
+
+-----------------------------------------------------------------------------
+
+From Davis June 12, 1986
+
+1. I have changed the default value of parameter unmap in task FMEDIAN to
+yes to preserve the original data range.
+
+2. I have changed the value of parameter row_delimiter from \n to ;.
+
+-----------------------------------------------------------------------------
+
+From Davis May 12, 1986
+
+1. Changed the angle convention in GAUSS so that theta is the angle of the
+major axis with respect to the x axis measured counter-clockwise as specified
+in the help page instead of the negative of that angle.
+
+-----------------------------------------------------------------------------
+
+From Davis Apr 28, 1986
+
+1. Moved geomap.key to lib$scr and made redefined HELPFILE in geogmap.x
+appropriately.
+
+------------------------------------------------------------------------------
+
+images$imarith/imsum.gx: Valdes Apr 25, 1986
+ 1. Fixed bug in generic code which called the real VOPS operator
+ regardless of the datatype. This caused IMSUM to fail on short
+ images.
+
+From Davis Apr 17, 1986
+
+1. Changed constructs of the form boolean == false in the file imdelete.x
+to ! boolean.
+
+------------------------------------------------------------------------------
+
+images$imarith: Valdes, April 8, 1986
+ 1. IMARITH has been modified to also operate on a list of specified
+ header parameters. This is primarily used when adding images to
+ also added the exposure times. A new parameter was added and the
+ help page modified.
+ 2. IMSUM has been modified to also operate on a list of specified
+ header parameters. This is primarily used when summing images to
+ also sum the exposure times. A new parameter was added and the
+ help page modified.
+
+------------------------------------------------------------------------------
+
+From Valdes Mar 24, 1986:
+
+1. When modifying IMARITH to handle mixed dimensions the output image header
+was made a copy of the image with the higher dimension. However, the default
+when the images were of the same dimension changed to be a copy of the second
+operand. This has been changed back to being a copy of the first operand
+image.
+
+------------------------------------------------------------------------------
+
+From Davis Mar 21, 1986:
+
+1. A NULL pointer bug in the subroutine plfree inside IMSURFIT was causing
+segmentation violation errors. A null pointer test was added to plfree.
+
+------------------------------------------------------------------------------
+
+From Davis Mar 20, 1986:
+
+1. A bug involving in place operations in several image tasks has been fixed.
+
+------------------------------------------------------------------------------
+
+From Davis Mar 19, 1986:
+
+1. IMSURFIT no longer permits the input image to be replaced by the output
+image.
+
+2. The tasks IMSHIFT, IMTRANSPOSE, SHIFTLINES, and GEOTRAN have been modified
+to use the images tools xt_mkimtemp and xt_delimtemp for in place
+calculations.
+
+-------------------------------------------------------------------------------
+
+From Valdes Mar 13, 1986:
+
+1. Bug dealing with type coercion in short datatype images in IMARITH and IMSUM
+which occurs on the SUN has been fixed.
+------
+From Valdes Mar 10, 1986:
+
+1. IMSUM has been modified to work on any number of images.
+
+2. Modified the help page
+------
+From Valdes Feb 25, 1986:
+
+There have been two changes to IMARITH:
+
+1. A bug preventing use of image sections has been removed.
+
+2. An improvement allowing use of images of different dimension.
+The algorithm is as follow:
+
+ a. Check if both operands are images. If not the output
+ image is a copy of the operand image.
+
+ b. Check that the axes lengths are the same for the dimensions
+ in common. For example a 3D and 2D image must have the same
+ number of columns and lines.
+
+ c. Set the output image to be a copy of the image with the
+ higher dimension.
+
+ d. Repeat the operation over the lower dimensions for each of
+ the higher dimensions.
+
+For example, consider subtracting a 2D image from a 3D image. The output
+image will be 3D and the 2D image is subtracted from each band of the
+3D image. This will work for any combination of dimensions. Another
+example is dividing a 3D image by a 1D image. Then each line of each
+plane and each band will be divided by the 1D image. Likely applications
+will be subtracting biases and darks and dividing by response calibrations
+in stacked observations.
+
+3. Modified the help page
+===========
+Release 2.2
+===========
+From Davis Mar 6, 1986:
+
+1. A serious bug had crept into GAUSS after I made some changes. For 2D
+images the sense of the sigma was reversed, i.e sigma = 2.0 was actually
+sigma = 0.5. This bug has now been fixed.
+
+---------------------------------------------------------------------------
+
+From Davis Jan 13, 1986:
+
+1. Listpixels will now print out complex pixel values correctly.
+
+---------------------------------------------------------------------------
+
+From Davis Dec 12, 1985:
+
+1. The directional gradient operator has been added to the images package.
+
+---------------------------------------------------------------------------
+
+From Valdes Dec 11, 1985:
+
+1. IMARITH has been modified to first check if an operand is an existing
+file. This allows purely numeric image names to be used.
+
+---------------------------------------------------------------------------
+
+From Davis Dec 11, 1985:
+
+1. A Laplacian (second derivatives) operator has been added to the images
+package.
+
+---------------------------------------------------------------------------
+
+From Davis Dec 10, 1985:
+
+1. The new convolution tasks boxcar, gauss and convolve have been added
+to the images package. Convolve convolves an image with an arbitrary
+user supplied rectangular kernel. Gauss convolves an image with a 2D
+Gaussian of arbitrary size. Boxcar will smooth an image using a smoothing
+window of arbitrary size.
+
+2. The images package source code has been reorganized into the following
+subdirectories: 1) filters 2) geometry 3) imfit 4) imarith 4) iminfo and
+5) imutil 6) lib. Lib contains routines which may be of use to several IRAF
+tasks such as ranges. The imutil subdirectory contains tasks which modify
+images in some way such as hedit. The iminfo subdirectory contains code
+for displaying header and pixel values and other image characteristics
+such as the histogram. Image arithmetic and fitting routines are found
+in imarith and imfit respectively. Filters contains the convolution and
+median filtering routines and geometry contains the geometric distortion
+corrections routines.
+
+3. The documentation of the main images package has been brought into
+conformity with the new IRAF standards.
+
+4. Documentation for imdelete, imheader, imhistogram, listpixels and
+sections has been added to the help database.
+
+5. The parameter structure for imhistogram has been simplified. The
+redundant parameters sections and setranges have been removed.
+
+---------------------------------------------------------------------------
+
+
+From Valdes Nov 4, 1985:
+
+1. IMCOPY modified so that the output image may be a directory. Previously
+logical directories were not correctly identified.
+------
+
+From Davis Oct 21, 1985:
+
+1. A bug in the pixel rejection cycle of IMSURFIT was corrected. The routine
+make_ranges in ranges.x was not successfully converting a sorted list of
+rejected pixels into a list of ranges in all cases.
+
+2. Automatic zero divide error checking has been added to IMSURFIT.
+------
+From Valdes Oct 17, 1985:
+
+1. Fit1d now allows averaging of image lines or columns when interactively
+setting the fitting parameters. The syntax is "Fit line = 10 30"; i.e.
+blank separated line or column numbers. A single number selects just one
+line or column. Be aware however, that the actual fitting of the image
+is still done on each column or line individually.
+
+2. The zero line in the interactive curve fitting graphs has been removed.
+This zero line interfered with fitting data near zero.
+------
+From Rooke Oct 10, 1985:
+
+1. Blkaverage was changed to "blkavg" and modified to support any allowed
+number of dimensions. It was also made faster in most cases, depending on
+the blocking factors in each dimension.
+------
+From Valdes Oct 4, 1985:
+
+1. Fit1d and lineclean modified to allow separate low and high rejection
+limits and rejection iterations.
+------
+From Davis Oct 3, 1985:
+
+1. Minmax was not calculating the minimum correctly for integer images.
+because the initial values were not being set correctly.
+------
+From Valdes Oct 1, 1985:
+
+1. Imheader was modified to print the image history. Though the history
+mechanism is little used at the moment it should become an important part
+of any image.
+
+2. Task revisions renamed to revs.
+------
+From Davis Sept 30, 1985:
+
+1. Two new tasks median and fmedian have been added to the images package.
+Fmedian is a fast median filtering algorithm for integer data which uses
+the histogram of the image to calculate the median at each window. Median
+is a slower but more general algorithm which performs the same task.
+------
+From Valdes August 26, 1985:
+
+1. Blkaverage has been modified to include an new parameter called option.
+The current options are to average the blocks or sum the blocks.
+------
+From Valdes August 7, 1985
+
+1. Fit1d and lineclean wer recompiled with the modified icfit package.
+The new package contains better labeling and graph documentation.
+
+2. The two tasks now have parameters for setting the graphics device
+and reading cursor input from a file.
+______
+From: /u2/davis/ Tue 08:27:09 06-Aug-85
+Package: images
+Title: imshift bug
+
+Imshift was shifting incorrectly when an integral pixel shift in x and
+a fractional pixel shift in y was requested. The actual x shift was
+xshift + 1. The bug has been fixed and imshift will now work correctly for
+any combination of fractional and integral pixel shifts
+------
+From: /u2/davis/ Fri 18:14:12 02-Aug-85
+Package: images
+Title: new images task
+
+A new task GEOMAP has been added to the images package. GEOMAP calculates
+the spatial transformation required to map one image onto another.
+------
+From: /u2/davis/ Thu 16:47:49 01-Aug-85
+Package: images
+Title: new images tasks
+
+The tasks ROTATE, IMLINTRAN and GEODISTRAN have been added to the images
+package. ROTATE rotates and shifts an image. IMLINTRAN will rotate, rescale
+and shift an an image. GEODISTRAN corrects an image for geometric distortion.
+------
+From Valdes July 26, 1985:
+
+1. The task revisions has been added to page revisions to the images
+package. The intent is that each package will have a revisions task.
+Note that this means there may be multiple tasks named revisions loaded
+at one time. Typing revisions alone will give the revisions for the
+current package. To get the system revisions type system.revisions.
+
+2. A new task called fit1d replaces linefit. It is essentially the same
+as linefit except for an extra parameter "axis" which selects the axis along
+which the functions are to be fit. Axis 1 is lines and axis 2 is columns.
+The advantages of this change are:
+
+ a. Column fitting can now be done without transposing the image.
+ This allows linefit to be used with image sections along
+ both axes.
+ b. For 1D images there is no prompt for the line number.
+.endhelp
diff --git a/pkg/images/imcoords/ccfind.par b/pkg/images/imcoords/ccfind.par
new file mode 100644
index 00000000..bbc980f8
--- /dev/null
+++ b/pkg/images/imcoords/ccfind.par
@@ -0,0 +1,48 @@
+# Parameters for the CCFIND task
+
+# Input and output files and images
+input,f,a,,,,The list input celestial coordinate files
+output,f,a,"",,,The output matched coordinates files
+images,f,a,"",,,The input images
+
+# The input coordinate file format
+lngcolumn,i,h,1,,,Column containing the ra / longitude
+latcolumn,i,h,2,,,Column containing the dec / latitude
+lngunits,s,h,"",,,Input ra / longitude units
+latunits,s,h,"",,,Input dec / latitude units
+insystem,s,h,"j2000",,,Input celestial coordinate system
+
+# The celestial coordinate system reference point parameters
+usewcs,b,h,no,,,Locate objects using the existing image wcs ?
+xref,r,h,INDEF,,,The x reference pixel
+yref,r,h,INDEF,,,The y reference pixel
+xmag,r,h,INDEF,,,The x axis scale in arcsec / pixel
+ymag,r,h,INDEF,,,The y axis scale in arcsec / pixel
+xrotation,r,h,INDEF,,,The x rotation angle in degrees
+yrotation,r,h,INDEF,,,The y axis rotation angle in degrees
+lngref,s,h,"INDEF",,,Reference point ra / longitude coordinate
+latref,s,h,"INDEF",,,Reference point dec / latitude coordinate
+lngrefunits,s,h,"",,,Reference point ra / longitude units
+latrefunits,s,h,"",,,Reference point dec / latitude units
+refsystem,s,h,"j2000",,,Reference point coordinate system
+projection,s,h,"tan",,,Sky projection geometry
+
+# Centeaing parameters.
+center,b,h,yes,,,Center the pixel coordinates ?
+sbox,i,h,21,11,,Search box width in pixels
+cbox,i,h,9,5,,Centering box width in pixels
+datamin,r,h,INDEF,,,Minimum good data value
+datamax,r,h,INDEF,,,Maximum good data value
+background,r,h,INDEF,,,Background reference value
+maxiter,i,h,5,2,,Maximum number of iterations
+tolerance,i,h,0,0,,Tolerance for convergence in pixels
+
+# Output parameters.
+xformat,s,h,"",,,Output format for the x coordinate
+yformat,s,h,"",,,Output format for the y coordinate
+
+# Task mode parameters.
+verbose,b,h,yes,,,Print messages about progress of task ?
+
+mode,s,h,'ql'
+
diff --git a/pkg/images/imcoords/ccget.par b/pkg/images/imcoords/ccget.par
new file mode 100644
index 00000000..50f00a55
--- /dev/null
+++ b/pkg/images/imcoords/ccget.par
@@ -0,0 +1,36 @@
+# Parameters for the CCGET task
+
+# Input and output files and images
+input,f,a,,,,The input catalog file(s)
+output,f,a,,,,The output catalog file(s)
+
+# The user field parameters.
+lngcenter,s,a,"00:00:00.0",,,Ra / Longitude of field center
+latcenter,s,a,"00:00:00",,,Dec / Latitude of field center
+lngwidth,r,a,1.0,0.0,360.0,Ra / Longitude field width in degrees
+latwidth,r,a,1.0,0.0,180.0,Dec / Latitude field width in degrees
+fcsystem,s,h,"",,,The field center celestial coordinate system
+fclngunits,s,h,"",,,Ra / Longitude units of field center
+fclatunits,s,h,"",,,Dec / Latitude units of field center
+
+# The input catalog file parameters
+colaliases,s,h,"",,,Input catalog column aliases
+lngcolumn,s,h,"c2",,,Column containing the ra / longitude
+latcolumn,s,h,"c3",,,Column containing the dec / latitude
+catsystem,s,h,"j2000",,,Catalog celestial coordinate system
+catlngunits,s,h,"",,,Catalog ra / longitude units
+catlatunits,s,h,"",,, Catalog dec / latitude units
+
+# The output catalog file parameters
+outsystem,s,h,"",,,Output celestial coordinate system
+olngunits,s,h,"",,,Output ra / longitude units
+olatunits,s,h,"",,, Ouput dec / latitude units
+olngformat,s,h,"",,,Output ra / longitude format
+olatformat,s,h,"",,, Ouput dec / latitude format
+exprs,s,h,"c[*]",,,The list of output column expressions
+formats,s,h,"",,,The optional output formats string
+
+# Output and graphics mode parameters
+verbose,b,h,yes,,,Print messages about progress of task ?
+
+mode,s,h,'ql'
diff --git a/pkg/images/imcoords/ccmap.par b/pkg/images/imcoords/ccmap.par
new file mode 100644
index 00000000..bba6a4c2
--- /dev/null
+++ b/pkg/images/imcoords/ccmap.par
@@ -0,0 +1,54 @@
+# Parameters for the CCMAP task
+
+# Input and output files and images
+input,f,a,,,,The input coordinate files
+database,f,a,,,,The output database file
+solutions,s,h,"",,,The database plate solution names
+images,f,h,"",,,The input images
+results,f,h,"",,,The optional results summary files
+
+# The input coordinate file format
+xcolumn,i,h,1,,,Column containing the x coordinate
+ycolumn,i,h,2,,,Column containing the y coordinate
+lngcolumn,i,h,3,,,Column containing the ra / longitude
+latcolumn,i,h,4,,,Column containing the dec / latitude
+xmin,r,h,INDEF,,,Minimum logical x pixel value
+xmax,r,h,INDEF,,,Maximum logical x pixel value
+ymin,r,h,INDEF,,,Minimum logical y pixel value
+ymax,r,h,INDEF,,,Maximum logical y pixel value
+lngunits,s,h,"",,,Input ra / longitude units
+latunits,s,h,"",,,Input dec / latitude units
+insystem,s,h,"j2000",,,Input celestial coordinate system
+
+# The celestial coordinate system reference point parameters
+refpoint,s,h,"coords","|coords|user|tweak|",,Source of the reference point definition
+xref,s,h,"INDEF",,,Reference point in x
+yref,s,h,"INDEF",,,Reference point in y
+lngref,s,h,"INDEF",,,Reference point ra / longitude telescope coordinate
+latref,s,h,"INDEF",,,Reference point dec / latitude telescope coordinate
+refsystem,s,h,"INDEF",,,Reference point telescope coordinate system
+lngrefunits,s,h,"",,,Reference point ra / longitude units
+latrefunits,s,h,"",,,Reference point dec / latitude units
+
+# Coordinate map fitting parameters
+projection,s,h,"tan",,,Sky projection geometry
+fitgeometry,s,h,"general",|shift|xyscale|rotate|rscale|rxyscale|general|,,Fitting geometry
+function,s,h,"polynomial",|chebyshev|legendre|polynomial|,,Surface type
+xxorder,i,h,2,2,,Order of xi fit in x
+xyorder,i,h,2,2,,Order of xi fit in y
+xxterms,s,h,"half","|none|half|full|",,Xi fit cross terms type
+yxorder,i,h,2,2,,Order of eta fit in x
+yyorder,i,h,2,2,,Order of eta fit in y
+yxterms,s,h,"half","|none|half|full|",,Eta fit cross terms type
+maxiter,i,h,0,,,The maximum number of rejection iterations
+reject,r,h,3.0,,,Rejection limit in sigma units
+
+# Output and graphics mode parameters
+update,b,h,no,,,Update the image world coordinate system ?
+pixsystem,s,h,"logical",|logical|physical|",,Input pixel coordinate system
+verbose,b,h,yes,,,Print messages about progress of task ?
+interactive,b,h,yes,,,Fit the transformation interactively ?
+graphics,s,h,"stdgraph",,,Default graphics device
+cursor,*gcur,h,,,,Graphics cursor
+
+mode,s,h,'ql'
diff --git a/pkg/images/imcoords/ccsetwcs.par b/pkg/images/imcoords/ccsetwcs.par
new file mode 100644
index 00000000..45afbf7a
--- /dev/null
+++ b/pkg/images/imcoords/ccsetwcs.par
@@ -0,0 +1,28 @@
+# Parameters for the COOWCS task
+
+# Input and output files and images
+images,f,a,,,,The input images
+database,f,a,,,,The input database file
+solutions,f,a,"",,,The input plate solutions
+
+# The celestial coordinate system parameters
+xref,r,h,INDEF,,,The x reference pixel
+yref,r,h,INDEF,,,The y reference pixel
+xmag,r,h,INDEF,,,The x axis scale in arcsec / pixel
+ymag,r,h,INDEF,,,The y axis scale in arcsec / pixel
+xrotation,r,h,INDEF,,,The x axis rotation angle in degrees
+yrotation,r,h,INDEF,,,The y axis rotation angle in degrees
+lngref,r,h,INDEF,,,The ra / longitude reference coordinate in lngunits
+latref,r,h,INDEF,,,The dec / latitude reference coordinate in latunits
+lngunits,s,h,"",,,The ra / longitude reference coordinate units
+latunits,s,h,"",,,The dec / latitude reference coordinate units
+transpose,b,h,no,,,Transpose the computed image wcs ?
+projection,s,h,"tan",,,The sky projection geometry
+coosystem,s,h,"j2000",,,The celestial coordinate system
+
+# Output and graphics mode parameters
+update,b,h,yes,,,Update the image world coordinate system ?
+pixsystem,s,h,"logical","|logical|physical|",,The input pixel coordinate system
+verbose,b,h,yes,,,Print messages about actions taken by the task ?
+
+mode,s,h,'ql'
diff --git a/pkg/images/imcoords/ccstd.par b/pkg/images/imcoords/ccstd.par
new file mode 100644
index 00000000..13dc92b3
--- /dev/null
+++ b/pkg/images/imcoords/ccstd.par
@@ -0,0 +1,31 @@
+# Parameter set for the CCSTD Task
+
+input,s,a,,,,The input coordinate files
+output,s,a,,,,The output coordinate files
+database,s,a,,,,The input database file
+solutions,s,a,,,,The plate solutions
+geometry,s,h,"linear","|linear|geometric|",,"The solution type (linear,geometric)"
+forward,b,h,yes,,,Transform to standard coordinates ?
+polar,b,h,no,,,Work in polar standard coordinates ?
+xref,r,h,INDEF,,,The X reference coordinate
+yref,r,h,INDEF,,,The Y reference coordinate
+xmag,r,h,INDEF,,,The X axis scale in arcsec per X reference coordinate
+ymag,r,h,INDEF,,,The Y axis scale in arcsec per Y reference coordinate
+xrotation,r,h,INDEF,,,The X axis rotation angle in degrees
+yrotation,r,h,INDEF,,,The Y axis rotation angle in degrees
+lngref,r,h,INDEF,,,The ra / longitude reference coordinate in lngunits
+latref,r,h,INDEF,,,The dec / latitude reference coordinate in latunits
+lngunits,s,h,"",,,The ra / longitude coordinate units
+latunits,s,h,"",,,The dec / latitude coordinate units
+projection,s,h,"tan","",,The sky projection geometry
+xcolumn,i,h,1,1,100,Input column containing the x / standard coordinate
+ycolumn,i,h,2,1,100,Input column containing the y / standard coordinate
+lngcolumn,i,h,3,1,100,Input column containing the longitude / standard coordinate
+latcolumn,i,h,4,1,100,Input column containing the latitude / standard coordinate
+lngformat,s,h,"",,,Output format of the standard / longitude coordinate
+latformat,s,h,"",,,Output format of the standard / latitude coordinate
+xformat,s,h,"",,,Output format of the standard / x coordinate
+yformat,s,h,"",,,Output format of the standard / y coordinate
+min_sigdigits,i,h,7,,,Minimum precision of the output coordinates
+mode,s,h,'ql'
+
diff --git a/pkg/images/imcoords/cctran.par b/pkg/images/imcoords/cctran.par
new file mode 100644
index 00000000..a9c51d48
--- /dev/null
+++ b/pkg/images/imcoords/cctran.par
@@ -0,0 +1,28 @@
+# Parameter set for the CCTRAN Task
+
+input,s,a,,,,The input coordinate files
+output,s,a,,,,The output coordinate files
+database,f,a,,,,The input database file
+solutions,s,a,,,,The input plate solutions
+geometry,s,h,"geometric","|linear|geometric|",,"Transformation type (linear,geometric)"
+forward,b,h,yes,,,Transform x / y to ra / dec (yes) or vice versa (no) ?
+
+xref,r,h,INDEF,,,The X reference pixel
+yref,r,h,INDEF,,,The Y reference pixel
+xmag,r,h,INDEF,,,The X axis scale in arcsec per pixel
+ymag,r,h,INDEF,,,The Y axis scale in arcsec per pixel
+xrotation,r,h,INDEF,,,The X axis rotation angle in degrees
+yrotation,r,h,INDEF,,,The Y axis rotation angle in degrees
+lngref,r,h,INDEF,,,The ra / longitude reference coordinate in lngunits
+latref,r,h,INDEF,,,The dec / latitude reference coordinate in latunits
+lngunits,s,h,"",,,The input / output ra / longitude reference coordinate units
+latunits,s,h,"",,,The input / output dec / latitude reference coordinate units
+projection,s,h,"tan",,,The sky projection geometry
+
+xcolumn,i,h,1,1,100,Input column containing the x / ra / longitude coordinate
+ycolumn,i,h,2,1,100,Input column containing the y / dec / latitude coordinate
+lngformat,s,h,"",,,Output format of the ra / longitude / x coordinate
+latformat,s,h,"",,,Output format of the dec / latitude / y coordinate
+min_sigdigits,i,h,7,,,Minimum precision of the output coordinates
+
+mode,s,h,'ql'
diff --git a/pkg/images/imcoords/ccxymatch.par b/pkg/images/imcoords/ccxymatch.par
new file mode 100644
index 00000000..a5fe93ee
--- /dev/null
+++ b/pkg/images/imcoords/ccxymatch.par
@@ -0,0 +1,41 @@
+# Parameter file for CCXYMATCH
+
+input,f,a,,,,The input pixel coordinate lists
+reference,f,a,,,,The input celestial coordinate lists
+output,f,a,,,,The output matched coordinate lists
+tolerance,r,a,1,,,The matching tolerance in arcseconds
+ptolerance,r,a,3,,,The matching tolerance in pixels
+
+refpoints,f,h,"",,,The optional list of reference points
+xin,r,h,INDEF,,,The X coordinate of the reference point
+yin,r,h,INDEF,,,The Y coordinate of the reference point
+xmag,r,h,INDEF,,,The X axis scale in arcseconds / pixel
+ymag,r,h,INDEF,,,The Y axis scale in arcseconds / pixel
+xrotation,r,h,INDEF,,,The X axis rotation in degrees
+yrotation,r,h,INDEF,,,The Y axis rotation in degrees
+projection,s,h,"tan",,,The sky projection geometry
+lngref,r,h,INDEF,,,The ra / longitude of the reference point
+latref,r,h,INDEF,,,The dec / latitude of the reference point
+
+lngcolumn,i,h,1,1,,The reference list ra / longitude coordinate column
+latcolumn,i,h,2,1,,The reference list dec / latitude coordinate column
+xcolumn,i,h,1,1,,The pixel list x coordinate column
+ycolumn,i,h,2,1,,The pixel list y coordinate column
+lngunits,s,h,"hours","|degrees|radians|hours|",,The ra / longitude units
+latunits,s,h,"degrees","|degrees|radians|",,The dec / latitude units
+
+separation,r,h,3.0,,,The minimum object separation in arcseconds
+pseparation,r,h,9.0,,,The minimum object separation in pixels
+matching,s,h,"triangles","|tolerance|triangles|",,The matching algorithm
+nmatch,i,h,30,,,The maximum number of points for triangles algorithm
+ratio,r,h,10.0,5.0,10.0,The maximum ratio of longest to shortest side of triangle
+nreject,i,h,10,,,The maximum number of rejection iterations
+
+lngformat,s,h,"",,,The format of the output ra / longitude coordinate
+latformat,s,h,"",,,The format of the output dec / latitude coordinate
+xformat,s,h,"%13.3f",,,The format of the output x coordinate
+yformat,s,h,"%13.3f",,,The format of the output y coordinate
+
+verbose,b,h,yes,,,Verbose mode ?
+
+mode,s,h,ql,,,
diff --git a/pkg/images/imcoords/doc/ccfind.hlp b/pkg/images/imcoords/doc/ccfind.hlp
new file mode 100644
index 00000000..33eceb7c
--- /dev/null
+++ b/pkg/images/imcoords/doc/ccfind.hlp
@@ -0,0 +1,596 @@
+.help ccfind Jun99 images.imcoords
+.ih
+NAME
+ccfind -- locate objects in an image given a celestial coordinate list and
+the image wcs
+.ih
+USAGE
+ccfind input output image
+.ih
+PARAMETERS
+.ls input
+The list of input celestial coordinate files. Coordinates may be entered
+by hand by setting input to "STDIN". A STDIN coordinate list is terminated
+by typing <EOF> (usually <ctrl/d> or <ctrl/z>).
+.le
+.ls output
+The list of output matched coordinate files. The computed pixel values
+are appended to the input coordinate file line and written to output. The number
+of output files must equal the number of input files. Results may be
+printed on the terminal by setting output to "STDOUT".
+.le
+.ls image
+The list of input images associated with the input coordinate files. The number
+of input images must equal the number of input coordinate files.
+.le
+.ls lngcolumn = 1, latcolumn = 2
+The input coordinate file columns containing the celestial ra / longitude and
+dec / latitude coordinates respectively.
+.le
+.ls lngunits = "", latunits = ""
+The units of the input ra / longitude and dec / latitude coordinates. The
+options are "hours", "degreees", and "radians" for ra / longitude and
+"degrees" and "radians" for dec / latitude. If lngunits and latunits are
+undefined they default to the preferred units for the coordinates
+system specified by \fIinsystem\fR, e.g. "hours" and "degrees" for
+equatorial systems and "degrees" and "degrees" for ecliptic, galactic, and
+supergalactic systems.
+.le
+.ls insystem = "j2000"
+The input celestial coordinate system. The \fIinsystem\fR parameter
+sets the preferred units for the input celestial coordinates, and
+tells CCFIND how to transform the input celestial coordinates
+the input image celestial coordinate system. The systems of most
+interest to users are "icrs", "j2000", and "b1950". The full set
+of options are the following:
+
+.ls equinox [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system if equinox is a
+Julian epoch, e.g. J2000.0 or 2000.0, or the equatorial mean place
+pre-IAU 1976 system (FK4) if equinox is a Besselian epoch, e.g. B1950.0
+or 1950.0. Julian equinoxes are prefixed by a J or j, Besselian equinoxes
+by a B or b. Equinoxes without the J / j or B / b prefix are treated as
+Besselian epochs if they are < 1984.0, Julian epochs if they are >= 1984.0.
+Epoch is the epoch of the observation and may be a Julian
+epoch, a Besselian epoch, or a Julian date. Julian epochs
+are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to the epoch type of
+equinox if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls icrs [equinox] [epoch]
+The International Celestial Reference System (ICRS) where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk5 [equinox] [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system where equinox is a
+Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0. Epoch
+is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls noefk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system but without the E-terms
+where equinox is a Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day. If undefined epoch defaults to equinox.
+.le
+.ls apparent epoch
+The equatorial geocentric apparent place post-IAU 1976 system where
+epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date.
+.le
+.ls ecliptic epoch
+The ecliptic coordinate system where epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch values < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day.
+.le
+.ls galactic [epoch]
+The IAU 1958 galactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+.ls supergalactic [epoch]
+The deVaucouleurs supergalactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+
+In all the above cases fields in [] are optional with the defaults as
+described. The epoch field for the icrs, fk5, galactic, and supergalactic
+coordinate systems is only used if the input coordinates are in the
+equatorial fk4, noefk4, fk5, or icrs systems and proper motions are supplied.
+Since CCFIND does not currently support proper motions these fields are
+not required.
+.le
+.ls usewcs = no
+Use image header information to compute the input image celestial coordinate
+system ? If usewcs is "yes", the image coordinate system is read from the
+image header. If usewcs is "no", the input image celestial coordinates
+system is defined by \fIxref\fR, \fIyref\fR, \fIxmag\fR, \fIymag\fR,
+\fIxrotation\fR, \fIyrotation\fR, \fIlngref\fR, \fIlatref\fR,
+\fIlngrefunits\fR, \fIlatrefunits\fR, \fIrefsystem\fR, and \fIprojection\fR
+parameters respectively.
+.le
+.ls xref = INDEF, yref = INDEF
+The x and y pixel coordinates of the reference point.
+xref and yref default to the center of the image in pixel coordinates.
+.le
+.ls xmag = INDEF, ymag = INDEF
+The x and y scale factors in arcseconds per pixel. xmag and ymag default
+to 1.0 and 1.0 arcseconds per pixel.
+.le
+.ls xrotation = INDEF, yrotation = INDEF
+The x and y rotation angles in degrees. xrotation and yrotation are
+interpreted as the rotation of the ra / longitude and dec / latitude
+coordinates with respect to the x and y axes, and default 0.0 and 0.0 degrees
+respectively. To set east to the up, down, left, and right directions,
+set xrotation to 90, 270, 180, and 0 respectively. To set north to the
+up, down, left, and right directions, set yrotation to 0, 180, 90, and 270
+degrees respectively. Any global rotation must be added to both the
+xrotation and yrotation values.
+.le
+.ls lngref = "INDEF", latref = "INDEF"
+The ra / longitude and dec / latitude of the reference point. Lngref and latref
+may be numbers, e.g 13:20:42.3 and -33:41:26, or keywords for the
+appropriate parameters in the image header, e.g. RA and DEC for NOAO
+image data. If lngref and latref are undefined they default to 0.0 and 0.0
+respectively.
+.le
+.ls lngrefunits = "", latrefunits = ""
+The units of the reference point celestial coordinates. The options
+are "hours", "degrees", and "radians" for the ra / longitude coordinates,
+and "degrees" and "radians" for the dec /latitude coordinates.
+If lngrefunits and latrefunits are undefined they default to the preferred
+units of the reference system.
+.le
+.ls refsystem = "INDEF"
+The celestial coordinate system of the reference point. Refsystem may
+be any one of the options listed under the \fIinsystem\fR parameter, e.g.
+"b1950", or an image header keyword containing the epoch of the observation
+in years, e.g. EPOCH for NOAO data. If refsystem is undefined
+the celestial coordinate system of the reference point defaults to the
+celestial coordinate system of the input coordinates \fIinsystem\fR.
+.le
+.ls projection = "tan"
+The sky projection geometry. The most commonly used projections in
+astronomy are "tan", "arc", "sin", and "lin". Other supported projections
+are "ait", "car", "csc", "gls", "mer", "mol", "par", "pco", "qsc", "stg",
+"tsc", and "zea".
+.le
+.ls center = yes
+Center the object pixel coordinates using an x and y marginal centroiding
+algorithm ?
+.le
+.ls sbox = 21
+The search box width in pixels. Sbox defines the region of the input image
+searched and used to compute the initial x and y marginal centroids. Users
+worried about contamination can set sbox = cbox, so that the first
+centering iteration will be the same as the others.
+.le
+.ls cbox = 9
+The centering box width in pixels. Cbox defines the region of the input
+image used to compute the final x and y marginal centroids.
+.le
+.ls datamin = INDEF, datamax = INDEF
+The minimum and maximum good data values. Values outside this range
+are exclude from the x and y marginal centroid computation.
+.le
+.ls background = INDEF
+The background value used by the centroiding algorithm. If background is
+INDEF, a value equal to the mean value of the good data pixels for
+each object is used.
+.le
+.ls maxiter = 5
+The maximum number of centroiding iterations to perform. The centroiding
+algorithm will halt when this limit is reached or when the desired tolerance
+is reached.
+.le
+.ls tolerance = 0
+The convergence tolerance of the centroiding algorithm. Tolerance is
+defined as the maximum permitted integer shift of the centering box in
+pixels from one iteration to the next.
+.le
+.ls verbose
+Print messages about actions taken by the task?
+.le
+
+.ih
+DESCRIPTION
+
+CCFIND locates the objects in the input celestial coordinate lists \fIinput\fR
+in the input images \fIimage\fR using the image world coordinate system,
+and writes the located objects to the output matched coordinates files
+\fIoutput\fR. CCFIND computes the pixel coordinates of each object by,
+1) transforming the input celestial coordinates to image celestial coordinate
+system, 2) using the image celestial coordinate system to compute the
+initial pixel coordinates, and 3) computing the final pixel coordinates
+using a centroiding algorithm. The image celestial coordinate system may
+be read from the image header or supplied by the user. The CCFIND output
+files are suitable for input to the plate solution computation task CCMAP.
+
+The input ra / longitude and dec / latitude coordinates are read from
+columns \fIlngcolumn\fR and \fIlatcolumn\fR in the input coordinate
+file respectively.
+
+The input celestial coordinate system is set by the \fIinsystem\fR parameter,
+and must be one of the following: equatorial, ecliptic, galactic, or
+supergalactic. The equatorial coordinate systems must be one of: 1) FK4,
+the mean place pre-IAU 1976 system, 2) FK4-NO-E, the same as FK4 but without
+the E-terms, 3) FK5, the mean place post-IAU 1976 system, 4) ICRS the
+International Celestial Reference System, 5) GAPPT, the geocentric apparent
+place in the post-IAU 1976 system.
+
+The \fIlngunits\fR and \fIlatunits\fR parameters set the units of the input
+celestial coordinates. If undefined, lngunits and latunits assume sensible
+defaults for the input celestial coordinate system set by the \fIinsystem\fR
+parameter, e.g. "hours" and "degrees" for equatorial coordinates and "degrees"
+and "degrees" for galactic coordinates.
+
+If the \fIusewcs\fR parameter is "yes", the image celestial coordinate
+system is read from the image header keywords CRPIX, CRVAL, CD or CDELT/CROTA,
+RADECSYS, EQUINOX or EPOCH, and MJD-OBS or DATE-OBS, where the mathematical
+part of this transformation is shown below.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = CD1_1
+ c = CD1_2
+ e = CD2_1
+ f = CD2_2
+ a = - b * CRPIX1 - c * CRPIX2
+ d = - e * CRPIX1 - f * CRPIX2
+ lng = CRVAL1 + PROJ (xi, eta)
+ lat = CRVAL2 + PROJ (xi, eta)
+.fi
+
+If usewcs is "no", then the image celestial coordinate system is computed
+using the values of the \fIxref\fR, \fIyref\fR, \fIxmag\fR, \fIymag\fR,
+\fIxrotation\fR, \fIyrotation\fR, \fIlngref\fR, \fIlatref\fR,
+\fIlngrefunits\fR, \fIlatrefunits\fR, \fIrefsystem\fR, and \fIprojection\fR
+supplied by the user, where the mathematical part of this transformation is
+shown below.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = xmag * cos (xrotation)
+ c = -ymag * sin (yrotation)
+ e = xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = - b * xref - c * yref
+ d = - e * xref - f * yref
+ lng = lngref + PROJ (xi, eta)
+ lat = latref + PROJ (xi, eta)
+.fi
+
+In both the above examples, x and y are the pixel coordinates, xi and eta
+are the usual projected (standard) coordinates, lng and lat are the celestial
+coordinates, and PROJ stands for the projection function, usually
+the tangent plane projection function.
+
+Once the image celestial coordinate system is determined, CCFIND transforms
+the input celestial coordinates to the image celestial coordinate system
+using the value of the \fIinsystem\fR parameter, and either the values of
+the image header keywords RADECSYS, EQUINOX / EPOCH, and MJD-OBS / DATE-OBS
+(if \fIusewcs\fR = "yes"), or the value of the \fIrefsystem\fR parameter (if
+\fIusewcs\fR = "no"), and then transforms the image celestial coordinates
+to pixel coordinates using the inverse of the transformation functions
+shown above.
+
+If \fIcenter\fR is yes, CCFIND locates the objects in the input
+image using an xn and y marginal centroiding algorithm. Pixels
+inside a box \fIsbox\fR pixels wide centered in the initial coordinates,
+are used to locate the objects in the image. Accurate final centering
+is done using pixels inside a region \fIcbox\fR pixels wide centered on
+these initial coordinates. Sbox should be set to a value large enough
+to locate the object, but small enough to exclude other bright sources.
+Cbox should be set to a value small enough to exclude sky values and other
+bright sources, but large enough to include the wings of point sources.
+Bad data can be excluded from the centroiding algorithm by setting
+the \fIdatamin\fR and \fIdatamax\fR parameters. If \fIbackground\fR is
+undefined then the centroiding algorithm sets the background value to
+the mean of the good data values inside the centering box.
+The centroiding algorithm iterates until the maximum number of
+iterations \fImaxiter\fR limit is reached, or until the tolerance
+criteria \fItolerance\fR is achieved.
+
+Only objects whose coordinates are successfully located in the
+input image are written to the output coordinate file. The computed
+output pixel coordinates are appended to the input image line using
+the format parameters \fIxformat\fR and \fIyformat\fR parameters,
+whose default values are "%10.3f" and "%10.3f" respectively
+
+.ih
+FORMATS
+
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+cctran.hlp-(67%)-line 268-file 1 of 1
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+.ih
+EXAMPLES
+
+1. Locate the object in the list wpix.coords in the image wpix using
+the existing image header wcs. The input celestial coordinates file
+contains j2000 GSC catalog coordinates of 5 objects in the field.
+The image wcs is in b1950.
+
+.nf
+cl> imcopy dev$wpix wpix
+ ... copy the test image into the current directory
+
+cl> hedit wpix equinox 1950.0 add+
+ ... change the epoch keyword value to the correct number
+
+cl> type wpix.coords
+13:29:47.297 47:13:37.52
+13:29:37.406 47:09:09.18
+13:29:38.700 47:13:36.23
+13:29:55.424 47:10:05.15
+13:30:01.816 47:12:58.79
+
+cl> ccfind wpix.coords wpix.match wpix usewcs+
+
+Input File: wpix.coords Output File: wpix.match
+ Image: wpix Wcs:
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Refsystem: wpix.imh logical Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK4 Equinox: B1950.000
+ Epoch: B1987.25767884 MJD: 46890.00000
+Located 5 objects in image wpix
+
+cl> type wpix.match
+# Input File: wpix.coords Output File: wpix.match
+# Image: wpix Wcs:
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Refsystem: wpix.imh logical Projection: TAN Ra/Dec axes: 1/2
+# Coordinates: equatorial FK4 Equinox: B1950.000
+# Epoch: B1987.25767884 MJD: 46890.00000
+
+13:29:47.297 47:13:37.52 327.504 410.379
+13:29:37.406 47:09:09.18 465.503 62.101
+13:29:38.700 47:13:36.23 442.013 409.654
+13:29:55.424 47:10:05.15 224.351 131.200
+13:30:01.816 47:12:58.79 134.373 356.327
+
+cl> ccmap wpix.match ccmap.db xcol=3 ycol=4 lngcol=1 latcol=2 ...
+.fi
+
+2. Repeat the previous example but input the image coordinate system by hand.
+The scale is known to be ~0.77 arcseconds per pixel, north is up, east is left,
+and the center of the image is near ra = 13:27:47, dec = 47:27:14 in 1950
+coordinates.
+
+.nf
+cl> ccfind wpix.coords wpix.match wpix xmag=-0.77 ymag=.77 lngref=13:27:47 \
+latref=47:27:14 refsystem=b1950.
+
+Input File: wpix.coords Output File: wpix.match.1
+ Image: wpix Wcs:
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Refsystem: b1950 Coordinates: equatorial FK4
+ Equinox: B1950.000 Epoch: B1950.00000000 MJD: 33281.92346
+Located 5 objects in image wpix
+
+
+cl> type wpix.match
+
+# Input File: wpix.coords Output File: wpix.match
+# Image: wpix Wcs:
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Refsystem: b1950 Coordinates: equatorial FK4
+# Equinox: B1950.000 Epoch: B1950.00000000 MJD: 33281.92346
+
+13:29:47.297 47:13:37.52 327.504 410.379
+13:29:37.406 47:09:09.18 465.503 62.101
+13:29:38.700 47:13:36.23 442.013 409.654
+13:29:55.424 47:10:05.15 224.351 131.200
+13:30:01.816 47:12:58.79 134.373 356.327
+.fi
+
+3. Repeat the previous example but read the ra, dec, and epoch from the
+image header keywords RA, DEC, and EPOCH. It turns out the telescope
+RA and DEC recorded in the image header are not very accurate and that
+EPOCH is 0.0 instead of 1987.26 so we will fix up the header before
+trying out the example.
+
+.nf
+cl> hedit wpix EPOCH 1987.26
+cl> hedit wpix RA '13:29:21'
+cl> hedit wpix DEC '47:15:42'
+
+cl> ccfind wpix.coords wpix.match wpix xmag=-0.77 ymag=.77 lngref=RA \
+latref=DEC refsystem=EPOCH
+
+Input File: wpix.coords Output File: wpix.match
+ Image: wpix Wcs:
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Refsystem: 1987.26 Coordinates: equatorial FK5
+ Equinox: J1987.260 Epoch: J1987.26000000 MJD: 46891.21500
+Located 5 objects in image wpix
+
+# Input File: wpix.coords Output File: wpix.match
+# Image: wpix Wcs:
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Refsystem: 1987.26 Coordinates: equatorial FK5
+# Equinox: J1987.260 Epoch: J1987.26000000 MJD: 46891.21500
+
+13:29:47.297 47:13:37.52 327.504 410.379
+13:29:37.406 47:09:09.18 465.503 62.101
+13:29:38.700 47:13:36.23 442.013 409.654
+13:29:55.424 47:10:05.15 224.351 131.200
+13:30:01.816 47:12:58.79 134.373 356.327
+.fi
+
+4. Use ccfind to predict the pixel coordinate in the last example by
+turning off the object centering, and mark the predicted coordinates
+on the image display with red dots.
+
+.nf
+cl> ccfind wpix.coords wpix.match wpix xmag=-0.77 ymag=.77 lngref=RA \
+latref=DEC refsystem=EPOCH center-
+
+Input File: wpix.coords Output File: wpix.match
+ Image: wpix Wcs:
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Refsystem: 1987.26 Coordinates: equatorial FK5
+ Equinox: J1987.260 Epoch: J1987.26000000 MJD: 46891.21500
+Located 5 objects in image wpix
+
+cl> type wpix.match
+
+# Input File: wpix.coords Output File: wpix.match
+# Image: wpix Wcs:
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Refsystem: 1987.26 Coordinates: equatorial FK5
+# Equinox: J1987.260 Epoch: J1987.26000000 MJD: 46891.21500
+
+13:29:47.297 47:13:37.52 333.954 401.502
+13:29:37.406 47:09:09.18 465.338 53.175
+13:29:38.700 47:13:36.23 447.687 399.967
+13:29:55.424 47:10:05.15 226.600 125.612
+13:30:01.816 47:12:58.79 141.892 351.084
+
+cl> display wpix 1
+
+cl> fields wpix.match 3,4 | tvmark 1 STDIN col=204
+
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+starfind, ccxymatch, ccmap, ccsetwcs, cctran
+.endhelp
diff --git a/pkg/images/imcoords/doc/ccget.hlp b/pkg/images/imcoords/doc/ccget.hlp
new file mode 100644
index 00000000..fef9afba
--- /dev/null
+++ b/pkg/images/imcoords/doc/ccget.hlp
@@ -0,0 +1,463 @@
+.help ccget Oct00 images.imcoords
+.ih
+NAME
+ccget -- extract objects in a user specified field from a text file catalog
+.ih
+USAGE
+ccget input output lngcenter latcenter lngwidth latwidth
+.ih
+PARAMETERS
+.ls input
+The input text file catalog(s). The text file columns must be
+delimited by whitespace and all the input catalogs must have the same format.
+.le
+.ls output
+The output catalogs containing the extracted objects. The number of
+output catalogs must be one or equal to the number of input catalogs.
+.le
+.ls lngcenter, latcenter
+The center of the field containing the objects to be extracted. Lngcenter and
+latcenter are assumed to be in the coordinate system specified by
+\fIfcsystem\fR, e.g. ra and dec for equatorial systems, galactic longitude and
+latitude for galactic systems, etc. and in the units specified by
+\fIfclngunits\fR and \fIlatunits\fR.
+.le
+.ls lngwidth, latwidth
+The width of the user specified field in degrees.
+.le
+.ls fcsystem = ""
+The celestial coordinate system of the field center. If undefined fcsystem
+defaults to the catalog celestial coordinate system specified by
+\fIcatsystem\fR. The two systems of
+most interest to users are "j2000" and "b1950". The full set of options is:
+
+.ls equinox [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system if equinox is a
+Julian epoch, e.g. J2000.0 or 2000.0, or the equatorial mean place
+pre-IAU 1976 system (FK4) if equinox is a Besselian epoch, e.g. B1950.0
+or 1950.0. Julian equinoxes are prefixed by a J or j, Besselian equinoxes
+by a B or b. Equinoxes without the J / j or B / b prefix are treated as
+Besselian epochs if they are < 1984.0, Julian epochs if they are >= 1984.0.
+Epoch is the epoch of the observation and may be a Julian
+epoch, a Besselian epoch, or a Julian date. Julian epochs
+are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to the epoch type of
+equinox if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk5 [equinox] [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system where equinox is a
+Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0. Epoch
+is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls noefk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system but without the E-terms
+where equinox is a Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day. If undefined epoch defaults to equinox.
+.le
+.ls apparent epoch
+The equatorial geocentric apparent place post-IAU 1976 system where
+epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date.
+.le
+.ls ecliptic epoch
+The ecliptic coordinate system where epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch values < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day.
+.le
+.ls galactic [epoch]
+The IAU 1958 galactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+.ls supergalactic [epoch]
+The deVaucouleurs supergalactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+
+In all the above cases fields in [] are optional with the defaults as
+described. The epoch field for the fk5, galactic, and supergalactic
+coordinate systems is only used if the input coordinates are in the
+equatorial fk4, noefk4, or fk5 systems and proper motions are supplied.
+Since ccget does not currently support proper motions these fields are
+not required.
+.le
+
+.ls fclngunits = "", fclatunits = ""
+The units of the field center coordinates. The options are "hours", "degrees",
+and "radians" for the ra / longitude coordinate and "degrees" and "radians"
+for the dec / latitude coordinates. If fclngunits and fclatunits are undefined
+they default to the preferred units for the given system, e.g. "hours" and
+degrees" for equatorial systems and "degrees" and "degrees" for ecliptic,
+galactic, and supergalactic systems.
+.le
+.ls colaliases = ""
+The list of input catalog column aliases separated by commas. By default the
+catalog columns are "c1", "c2", "c10", etc. If colaliases is defined then
+the aliases are assigned to the columns in order. For example if colaliases
+is "id,ra,dec,v,bv" then columns c1, c2, c3, c4, c5 will be assigned
+the names id, ra, dec, v, and bv and any remaining columns in the input catalog
+file will be assigned default names beginning with c6.
+.le
+.ls lngcolumn = "c2", latcolumn = "c3"
+The input catalog columns containing the coordinates of catalog objects.
+.le
+.ls catsystem = "j2000"
+The celestial coordinate system of the input catalog(s). The two systems of
+most interest to users are "j2000" and "b1950". The full set of options is
+described in the \fIfcsystem\fR parameter section.
+.le
+.ls catlngunits = "", catlatunits = ""
+The units of the catalog coordinates. The options are "hours", "degrees",
+and "radians" for the ra / longitude coordinate and "degrees" and "radians"
+for the dec / latitude coordinates. If catlngunits and catlatunits are undefined
+they default to the preferred units for the catalog system, e.g. "hours" and
+degrees" for equatorial systems and "degrees" and "degrees" for ecliptic,
+galactic, and supergalactic systems.
+.le
+.ls outsystem = ""
+The celestial coordinate system of the output coordinates. If undefined
+outsystem defaults to the celestial coordinate system of the catalog.
+The two systems of most interest to users are "j2000" and "b1950". The
+full set of options is described under the \fIfcsystem\fR parameter
+section.
+.le
+.ls olngunits = "", olatunits = ""
+The units of the output coordinates. The options are "hours", "degrees",
+and "radians" for the ra / longitude coordinate and "degrees" and "radians"
+for the dec / latitude coordinates. If olngunits and olatunits are undefined
+they default to the preferred units for outsystem, e.g. "hours" and degrees" for
+equatorial systems and "degrees" and "degrees" for ecliptic, galactic, and
+supergalactic systems.
+.le
+.ls olngformat = "", olatformat=""
+The output ra / longitude and dec / latitude formats if the output
+celestial coordinate system is different from the catalog celestial
+coordinate system. The defaults are " %010.1h" for hours, " %9h" for degrees
+and " %9.7g" for radians.
+.le
+.ls exprs = "c[*]"
+The list of output columns and column expressions separated by commas.
+By default the entire record for the extracted object is output exactly
+as it is. The output columns can be individual columns e.g. c1 or c5
+or column ranges, e.g. c[1-10] or c[2-4]. Column expressions are
+expressions of the catalog columns, e.g c4 + c5. Columns and column
+expression are output in the order in which they appear in exprs.
+.le
+.ls formats = ""
+An optional list of column formats separated by commas. Column formats must
+be placeholders, e.g. the letter f for existing columns which are not
+reformatted (with the possible exception of the coordinate columns).
+Column expression formats may be any regular formatting expression.
+For example if \fIexprs\fR is "c[1-3],c4+c5,c5+c7", then formats might be
+"f,%7.3f,%7.3f".
+.le
+.ls verbose = yes
+Print messages on the standard output about actions taken by the task.
+.le
+
+.ih
+DESCRIPTION
+
+Ccget extracts objects in a user specified field from the input catalogs
+\fIinput\fR and writes the extracted records to the output
+catalogs \fIoutput\fR.
+
+The user field is specified by the parameters \fIlngcenter\fR, \fIlatcenter\fR,
+\fIlngwidth\fR, and \fIlatwidth\fR, where the field center is entered in
+the celestial coordinate system specified by \fIfcsystem\fR and the
+units are specified by \fIfclngunits\fR and \fIfclatunits\fR. If fcsystem
+is undefined it defaults to the value of the catalog coordinate system
+\fIcatsystem\fR.
+
+The input catalogs must be text files containing 2 or more columns separated
+by whitespace. By default these columns are assigned names of the form
+c1, c2, ..., cn. Legal columns names must have the form described
+in the following column names section. Users may assign their own names
+to the columns by setting
+the \fIcolaliases\fR parameter. The input catalog columns \fIlngcolumn\fR and
+\fIlatcolumn\fR must contain the ra / longitude and dec / latitude coordinates
+of the catalog objects respectively. The parameters \fIcatsystem\fR,
+\fIcatlngunits\fR, and \fIcatlatunits\fR specify the coordinate system
+of the input catalog and its coordinate units respectively.
+
+At task startup the user field center is transformed from the coordinate
+system defined by \fIfcsystem\fR to the catalog coordinate system
+\fIcatsystem\fR and the ra / longitude and dec / latitude limits of the
+user field are computed. As each input catalog record is read, the catalog
+coordinates are decoded and tested against these limits. If the
+object is inside the user field then the column and column
+expressions specified by \fIexprs\fR are extracted from the input catalogs
+and written to the output catalogs.
+
+If the output celestial coordinate system \fIoutsystem\fR is
+different from \fIcatsystem\fR, then the catalog coordinates are transformed
+and to the output coordinates system, and written to the output catalog
+in the units specified
+by \fIolngunits\fR and \fIolatunits\fR, with the formats specified by
+\fIolngformat\fR and \fIolatformat\fR. Existing columns are written to
+the output catalog in the same
+format they have in the input catalog. Column expressions are written
+using the formats specified by \fIformats\fR or the builtin defaults
+of %5b, %10d, %10g, or %s for boolean, integer, floating point, or
+string columns respectively.
+
+.ih
+COLUMN NAMES
+
+By default column names are of the form c1, c2, ..., cN. However users can
+also define their own column names, which must have the following syntax
+
+.nf
+ {a-zA-Z}[{a-zA-Z0-9._$}]*
+.fi
+
+where [] indicates optional, {} indicates a class, - indicates an ascii
+range of characters, and * indicates zero or more occurrences. In words
+a column name must begin with an alphabetic character and be followed
+by any combination of alphabetic, digit, or '.', '_', and '$' characters.
+The ccget task imposes a 19 character limit on the columns names so it is
+best to keep them short.
+
+.ih
+COLUMN EXPRESSIONS
+
+Expressions must consist of operands and operators. The operands may be
+column names, numeric constants, functions, and quoted string constants.
+Values given as sexagesimal strings are automatically converted to
+decimal numbers. The operators are arithmetic, logical, and string.
+
+The following operators are supported:
+
+
+.nf
+ + - * / arithmetic operators
+ ** exponentiation
+ // string concatenation
+ ! - boolean not, unary negation
+ < <= > >= order comparison (works for strings)
+ == != && || equals, not equals, and, or
+ ?= string equals pattern
+ ? : conditional expression
+.fi
+
+The following intrinsic functions are supported:
+
+
+.nf
+ abs atan2 deg log min real sqrt
+ acos bool double log10 mod short str
+ asin cos exp long nint sin tan
+ atan cosh int max rad sinh tanh
+.fi
+
+
+.ih
+COLUMN FORMATS
+
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+.ih
+SOME BUILTIN CATALOG FORMATS
+
+The nlandolt.dat catalog in noao$photcal/catalogs/ has the following format.
+
+.nf
+# Column Quantity
+
+ 1 id
+ 2 ra
+ 3 dec
+ 4 v
+ 5 b-v
+ 6 u-b
+ 7 v-r
+ 8 r-i
+ 9 v-i
+ 10 n
+ 11 m
+ 12 err(v)
+ 13 err(b-v)
+ 14 err(u-b)
+ 15 err(v-r)
+ 16 err(r-i)
+ 17 err(v-i)
+.fi
+
+where the coordinates are in j2000, the errors are all mean errors of the mean,
+and n and m are the number of observations and number of independent nights
+of observations respectively.
+
+.ih
+REFERENCES
+
+The catalog references are
+
+.nf
+nlandolt.dat - Landolt, A.U. 1992, A.J. 104, 340
+.fi
+
+.ih
+EXAMPLES
+
+Example 1. Extract all Landolt standard stars within a 1 degree field
+surrounding the position ra = 3:55:00 dec = 0:00:00 (J2000).
+
+.nf
+cl> ccget nlandolt.dat output 03:55:00.0 0:00:00 1.0 1.0
+.fi
+
+Example 2. Repeat example 1 but output the coordinates in the b1950
+celestial coordinate system.
+
+.nf
+cl> ccget nlandolt.dat output 03:55:00.0 0:00:00 1.0 1.0 \
+outsystem=b1950
+.fi
+
+Example 3. Repeat example 1 but extract only the id, ra, dec, v,
+and b-v fields from the Landolt catalog. Note that since these
+columns are the first five in the catalog they can be specified
+as a range.
+
+.nf
+cl> ccget nlandolt.dat output 03:55:00.0 0:00:00 1.0 1.0 \
+exprs="c[1-5]"
+.fi
+
+Example 4. Repeat example 1 but extract the id, ra, dec, b and
+b-r colors. Note that b and b-r are not columns in the input catalog
+but may be computed from them. Note also that formats should be
+specified to give the desired spacing, although defaults will be
+supplied.
+
+.nf
+cl> ccget nlandolt.dat output 03:55:00.0 0:00:00 1.0 1.0 \
+exprs="c[1-3],c4+c5,c5+c7" formats="%7.3f,%7.3f
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+.endhelp
diff --git a/pkg/images/imcoords/doc/ccmap.hlp b/pkg/images/imcoords/doc/ccmap.hlp
new file mode 100644
index 00000000..e19d30fa
--- /dev/null
+++ b/pkg/images/imcoords/doc/ccmap.hlp
@@ -0,0 +1,1028 @@
+.help ccmap Jan01 images.imcoords
+.ih
+NAME
+ccmap -- compute plate solutions using matched pixel and celestial coordinate
+lists
+.ih
+USAGE
+ccmap input database
+.ih
+PARAMETERS
+.ls input
+The input text files containing the pixel and celestial coordinates of
+points in the input images. The coordinates are listed one per line with x, y,
+ra / longitude, and dec / latitude in the columns specified by the
+\fIxcolumn\fR, \fIycolumn\fR, \fIlngcolumn\fR, and \fIlatcolumn\fR parameters
+respectively. Whether all files are combined to produce one solution or
+each file produces a separate solution depends on whether there is a
+matching list of output \fIsolutions\fR names or \fIresults\fR files.
+.le
+.ls database
+The text database file where the computed plate solutions are stored.
+.le
+.ls solutions = ""
+An optional list of plate solution names. If there are multiple input
+coordinate files and no name or a single name is specified then the
+input coordinates are combined to produce a single solution. Otherwise
+the list must match the number of input coordinate files. If no names are
+supplied then the database records are assigned the names of the input
+images \fIimages\fR, or the names of the coordinate files \fIinput\fR.
+In the case of multiple coordinate files the first image or input is used.
+.le
+.ls images = ""
+The images associated with the input coordinate files. The number of images
+must be zero or equal to the number of input coordinate files. If an input
+image exists and the \fIupdate\fR parameter is enabled, the image wcs will
+be created from the linear component of the computed plate solution
+and written to the image header.
+.le
+.ls results = ""
+Optional output files containing a summary of the results including a
+description of the plate geometry and a listing of the input coordinates,
+the fitted coordinates, and the fit residuals. The number of
+results files must be zero, one or equal to the number of input files. If
+results is "STDOUT" the results summary is printed on the standard output.
+If there are multiple input coordinate files and zero or one output is
+specified then the input coordinates are combined to produce a single solution.
+.le
+.ls xcolumn = 1, ycolumn = 2, lngcolumn = 3, latcolumn = 4
+The input coordinate file columns containing the x, y, ra / longitude and
+dec / latitude values.
+.le
+.ls xmin = INDEF, xmax = INDEF, ymin = INDEF, ymax = INDEF
+The range of x and y pixel coordinates over which the computed coordinate
+transformation is valid. These limits should be left at INDEF or set to
+the values of the column and row limits of the input images, e.g xmin = 1.0,
+xmax = 512, ymin= 1.0, ymax = 512 for a 512 x 512 image. If xmin, xmax, ymin,
+or ymax are undefined, they are set to the minimum and maximum x and y
+pixels values in \fIinput\fR.
+.le
+.ls lngunits = "", latunits = ""
+The units of the input ra / longitude and dec / latitude coordinates. The
+options are "hours", "degrees", and "radians" for ra / longitude, and
+"degrees" and "radians" for dec / latitude. If the lngunits and latunits
+are undefined they default to the preferred units for the coordinate system
+specified by \fIinsystem\fR, e.g. "hours" and "degrees" for equatorial
+systems, and "degrees" and "degrees" for ecliptic, galactic, and
+supergalactic systems.
+.le
+.ls insystem = "j2000"
+The input celestial coordinate system. The \fIinsystem\fR parameter
+sets the preferred units for the input celestial coordinates,
+tells CCMAP how to transform the celestial coordinates of the reference
+point from the reference point coordinate system to the input coordinate
+system, and sets the correct values of the image header keywords CTYPE,
+RADECSYS, EQUINOX, and MJD-WCS if the image header wcs is updated. The
+systems of most interest to users are "icrs", "j2000", and "b1950" which
+stand for the ICRS J2000.0, FK5 J2000.0 and FK4 B1950.0 celestial coordinate
+systems respectively. The full set of options are the following:
+
+.ls equinox [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system if equinox is a
+Julian epoch, e.g. J2000.0 or 2000.0, or the equatorial mean place
+pre-IAU 1976 system (FK4) if equinox is a Besselian epoch, e.g. B1950.0
+or 1950.0. Julian equinoxes are prefixed by a J or j, Besselian equinoxes
+by a B or b. Equinoxes without the J / j or B / b prefix are treated as
+Besselian epochs if they are < 1984.0, Julian epochs if they are >= 1984.0.
+Epoch is the epoch of the observation and may be a Julian
+epoch, a Besselian epoch, or a Julian date. Julian epochs
+are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to the epoch type of
+equinox if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls icrs [equinox] [epoch]
+The International Celestial Reference System where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk5 [equinox] [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system where equinox is a
+Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0. Epoch
+is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls noefk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system but without the E-terms
+where equinox is a Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day. If undefined epoch defaults to equinox.
+.le
+.ls apparent epoch
+The equatorial geocentric apparent place post-IAU 1976 system where
+epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date.
+.le
+.ls ecliptic epoch
+The ecliptic coordinate system where epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch values < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day.
+.le
+.ls galactic [epoch]
+The IAU 1958 galactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+.ls supergalactic [epoch]
+The deVaucouleurs supergalactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+
+In all the above cases fields in [] are optional with the defaults as
+described. The epoch field for the icrs, fk5, galactic, and supergalactic
+coordinate systems is only used if the input coordinates are in the
+equatorial fk4, noefk4, fk5, or icrs systems and proper motions are supplied.
+Since CCMAP does not currently support proper motions these fields are
+not required.
+.le
+
+.ls refpoint = "coords"
+The definition of the sky projection reference point in celestial coordinates,
+e.g. the tangent point in the case of the usual tangent plane projection.
+The options are:
+.ls coords
+The celestial coordinates of the reference point are set to the mean of the
+input celestial coordinates, e.g. the mean of ra / longitude and dec /
+latitude coordinates. If the true tangent point is reasonably close to
+the center of the input coordinate distribution and the input is not
+too large, this approximation is reasonably accurate.
+.le
+.ls user
+The values of the keywords \fIlngref\fR, \fIlatref\fR, \fIrefsystem\fR,
+\fIlngrefunits\fR, and \fIlatrefunits\fR are used to determine the celestial
+coordinates of the reference point.
+.le
+.le
+.ls xref = "INDEF", yref = "INDEF"
+The reference pixel may be specified as a value or image header keyword.
+In the latter case a reference image must be specified. By specifying
+the reference pixel the solution will be constrained to putting the
+reference coordinate at that point.
+.le
+.ls lngref = "INDEF", latref = "INDEF"
+The ra / longitude and dec / latitude of the reference point(s). Lngref
+and latref may be numbers, e.g 13:20:42.3 and -33:41:26 or keywords for the
+appropriate parameters in the image header, e.g. RA/DEC or CRVAL1/CRVAL2.
+Each parameter may be a list to apply different reference points to
+each input coordinate list. If lngref and latref are undefined then
+the position of the reference point defaults to the mean of the input
+coordinates.
+.le
+.ls refsystem = "INDEF"
+The celestial coordinate system of the reference point. Refsystem may
+be any one of the options listed under the \fIinsystem\fR parameter, e.g.
+"b1950", or an image header keyword containing the epoch of the observation
+in years, e.g. EPOCH for NOAO data. In the latter case the coordinate system is
+assumed to be equatorial FK4 at equinox EPOCH. If refsystem is undefined
+the celestial coordinate system of the reference point defaults to the
+celestial coordinate system of the input coordinates \fIinsystem\fR.
+.le
+.ls lngrefunits = "", latrefunits = ""
+The units of the reference point celestial coordinates. The options
+are "hours", "degrees", and "radians" for the ra / longitude coordinates,
+and "degrees" and "radians" for the dec /latitude coordinates.
+If lngunits and latunits are undefined they default to the units of the
+input coordinate system.
+.le
+.ls projection = "tan"
+The sky projection geometry. The most commonly used projections in astronomy
+are "tan", "arc", "sin", and "lin". Other supported standard projections
+are "ait", "car","csc", "gls", "mer", "mol", "par", "pco", "qsc", "stg",
+"tsc", and "zea". A new experimental function "tnx", a combination of the
+tangent plate projection and polynomials, is also available.
+.le
+.ls fitgeometry = "general"
+The plate solution geometry to be used. The options are the following, where
+xi and eta refer to the usual standard coordinates used in astrometry.
+.ls shift
+Xi and eta shifts only are fit.
+.le
+.ls xyscale
+Xi and eta shifts and x and y magnification factors in " / pixel are fit.
+Axis flips are allowed for.
+.le
+.ls rotate
+Xi and eta shifts and a rotation angle are fit. Axis flips are allowed for.
+.le
+.ls rscale
+Xi and eta shifts, a magnification factor in " / pixel assumed to be the same
+in x and y, and a rotation angle are fit. Axis flips are allowed for.
+.le
+.ls rxyscale
+Xi and eta shifts, x and y magnifications factors in " / pixel, and a rotation
+angle are fit. Axis flips are allowed for.
+.le
+.ls general
+A polynomial of arbitrary order in x and y is fit. A linear term and a
+distortion term are computed separately. The linear term includes a xi and eta
+shift, an x and y scale factor in " / pixel, a rotation and a skew. Axis
+flips are also allowed for in the linear portion of the fit. The distortion
+term consists of a polynomial fit to the residuals of the linear term. By
+default the distortion term is set to zero.
+.le
+
+For all the fitting geometries except "general" no distortion term is fit,
+i.e. the x and y polynomial orders are assumed to be 2 and the cross term
+switches are assumed to be set to "none", regardless of the values of the
+\fIxxorder\fR, \fIxyorder\fR, \fIxxterms\fR, \fIyxorder\fR, \fIyyorder\fR
+and \fIyxterms\fR parameters set by the user.
+.le
+.ls function = "polynomial"
+The type of analytic coordinate surface to be fit. The options are the
+following.
+.ls legendre
+Legendre polynomials in x and y.
+.le
+.ls chebyshev
+Chebyshev polynomials in x and y.
+.le
+.ls polynomial
+Power series polynomials in x and y.
+.le
+.le
+.ls xxorder = 2, xyorder = 2, yxorder = 2, yyorder = 2
+The order of the polynomials in x and y for the xi and eta fits respectively.
+The default order and cross term settings define the linear term in x
+and y, where the 6 coefficients can be interpreted in terms of an xi and eta
+shift, an x and y scaling in " / pixel, and rotations of the x and y axes.
+The "shift", "xyscale", "rotation", "rscale", and "rxyscale", fitting geometries
+assume that the polynomial order parameters are 2 regardless of the values
+set by the user. If any of the order parameters are higher than 2 and
+\fIfitgeometry\fR is "general", then a distortion surface is fit to the
+residuals from the linear portion of the fit.
+.le
+.ls xxterms = "half", yxterms = "half"
+The options are:
+.ls none
+The individual polynomial terms contain powers of x or powers of y but not
+powers of both.
+.le
+.ls half
+The individual polynomial terms contain powers of x and powers of y, whose
+maximum combined power is MAX (xxorder - 1, xyorder - 1) for the xi fit and
+MAX (yxorder - 1, yyorder - 1) for the eta fit. This is the recommended
+option for higher order plate solutions.
+.le
+.ls full
+The individual polynomial terms contain powers of x and powers of y, whose
+maximum combined power is MAX (xxorder - 1 + xyorder - 1) for the xi fit and
+MAX (yxorder - 1 + yyorder - 1) for the eta fit.
+.le
+
+The "shift", "xyscale", "rotation",
+"rscale", and "rxyscale" fitting geometries, assume that the
+cross term switches are set to "none" regardless of the values set by the user.
+If either of the cross-terms parameters is set to "half" or "full" and
+\fIfitgeometry\fR is "general" then a distortion surface is fit to the
+residuals from the linear portion of the fit.
+.le
+.ls maxiter = 0
+The maximum number of rejection iterations. The default is no rejection.
+.le
+.ls reject = INDEF
+The rejection limit in units of sigma.
+.le
+.ls update = no
+Update the world coordinate system in the input image headers ?
+The required numerical quantities represented by the keywords CRPIX,
+CRVAL, and CD are computed from the linear portion of the plate solution,
+The values of the keywords CTYPE, RADECSYS, EQUINOX, and MJD-WCS
+are set by the \fIprojection\fR and \fIinsystem\fR parameters. As there
+is currently no standard mechanism for storing the higher order plate solution
+terms if any in the image header wcs, these terms are currently ignored
+unless the projection function is the experimental function "tnx". The "tnx"
+function is not FITS compatible and can only be understood by IRAF. Any existing
+image wcs represented by the above keywords is overwritten during the update.
+.le
+.ls pixsystem = "logical"
+The input pixel coordinate system. The options are:
+.ls logical
+The logical pixel coordinate system is the coordinate system of the image
+pixels on disk. Since most users measure the pixel coordinates of objects
+in this system, "logical" is the system of choice for most applications.
+.le
+.ls physical
+The physical coordinate system is the pixel coordinate system of the
+parent image if any. This option may be useful for users working on images
+that are pieces of a larger mosaic.
+.le
+
+The choice of pixsystem has no affect on the fitting process, but does
+determine how the image header wcs is updated.
+.le
+.ls verbose = yes
+Print detailed messages about the progress of the task on the standard output ?
+.le
+.ls interactive = yes
+Compute the plate solution interactively ?
+In interactive mode the user may interact with the fitting process, e.g.
+change the order of the fit, reject points, display the data and refit, etc.
+.le
+.ls graphics = "stdgraph"
+The graphics device.
+.le
+.ls cursor = ""
+The graphics cursor.
+.le
+.ih
+DESCRIPTION
+
+CCMAP computes the plate solution for an image or set of images using lists
+of matched pixel and celestial coordinates. The celestial coordinates
+are usually equatorial coordinates, but may also be ecliptic, galactic,
+or supergalactic coordinates. The input coordinate files \fIinput\fR must
+be text file tables whose columns are delimited by whitespace. The pixel
+and celestial coordinates are listed in input, one per line with x, y,
+ra / longitude, and dec / latitude in columns \fIxcolumn\fR, \fIycolumn\fR,
+\fIlngcolumn\fR, and \fIlatcolumn\fR respectively.
+
+The \fIxmin\fR, \fIxmax\fR, \fIymin\fR and \fIymax\fR parameters define
+the region of validity of the fit in the pixel coordinate system. They should
+normally either be left set to INDEF, or set to the size of input images
+\fIimages\fR if any, e.g. xmin= 1.0, xmax= 512.0, ymin = 1.0, ymax = 512.0
+for a 512 square image. If set these parameters are also used to reject out
+of range pixel data before the actual fitting is done.
+
+The \fIlngunits\fR and \fIlatunits\fR parameters set the units of the input
+celestial coordinates. If undefined lngunits and latunits assume sensible
+defaults for the input celestial coordinate system set by the \fIinsystem\fR
+parameter, e.g. "hours" and "degrees" for equatorial coordinates and "degrees"
+and "degrees" for galactic coordinates. The input celestial coordinate system
+must be one of the following: equatorial, ecliptic, galactic, or supergalactic.
+The equatorial coordinate systems must be one of: 1) FK4, the mean place
+pre-IAU 1976 system, 2) FK4-NO-E, the same as FK4 but without the E-terms,
+3) FK5, the mean place post-IAU 1976 system, 4) GAPPT, the geocentric apparent
+place in the post-IAU 1976 system.
+
+The plate solution computed by CCMAP has the following form, where x and y
+are the pixel coordinates of points in the input image and xi and eta are the
+corresponding standard coordinates in units of " / pixel.
+
+.nf
+ xi = f (x, y)
+ eta = g (x, y)
+.fi
+
+The standard coordinates xi and eta are computed from the input celestial
+coordinates using the sky projection geometry \fIprojection\fR and
+the celestial coordinates of the projection reference point set by
+the user. The default projection is the tangent plane or gnomonic
+projection commonly used in optical astronomy. The projections most commonly
+used in astronomy are "sin" (the orthographic projection, used in radio
+aperture synthesis), "arc" (the zenithal equidistant projection, widely
+used as an approximation for Schmidt telescopes), and "lin" (linear).
+Other supported projections are "ait", "car", "csc", "gls", "mer", "mol",
+"par", "pco", "qsc", "stg", "tsc", and "zea". The experimental projection
+function "tnx" combines the "tan" projection with a polynomial fit
+to the residuals can be used to represent more complicated distortion
+functions.
+
+There are two modes in which this task works with multiple input
+coordinate lists. In one case each input list and possible associated
+image is treated independently and produce separate solutions. To
+select this option requires specifying a matching list of solution
+names or output results files. Note that this can also be simply done
+by running the task multiple times with a single input list each time.
+
+In the second mode data from multiple input lists are combined to
+produce a single solution. This is useful when multiple exposures are
+taken to define a higher quality astrometric solution. This mode is
+selected when there are multiple input lists, and possibly associated
+images, and no solution name or a single solution name is specified.
+
+When combining input data each set of coordinates may have different
+reference points which can be specified either as a list or by
+reference to image header keywords. The different reference points
+are used to convert each set of coordinates to the same coordinate
+frame. Typically this occurs when a set of exposures, each with the
+same coordinate reference pixel, has slightly different pointing as
+defined by the coordinate reference value. These different points
+result from a dither and can be useful to more completely sample the
+image pixel space. In other words, astrometric reference stars can be
+moved around the images to produce many more fitting points than occur
+with a single exposure. The key point to this process is that the
+shifts are mapped by the reference points of the pointing and the
+standard coordinates are independent of the pointing.
+
+A particular feature primarily intending for combining multiple
+exposures, but applies to single exposures as well, is an adjustment to
+the specified tangent point value based on the image WCS. When images,
+reference pixels, and reference coordinates are all defined and the
+images contain a celestial WCS the following computation is performed.
+The reference information replaces the WCS tangent point values, though
+typically the initial reference information is specified as the tangent
+point, and the updated WCS is used to evaluate celestial coordinates
+from the input pixel coordinates. The average difference between the WCS
+evaluated coordinates and the input celestial coordinates is computed.
+This difference is applied to the reference point prior to the standard
+coordinate plate solution calculation. In other words, the reference
+point is tweaked in the initial image WCS to make it agree on average with
+the input reference coordinates. If one updates the WCS of the images by
+the plate solution and the repeats the plate solution, particularly when
+using multiple exposures, an iterative convergence to a self-consistent
+WCS of both the tangent point and plate solution can be obtained.
+
+Several polynomial cross terms options are available. Options "none",
+"half", and "full" are illustrated below for a quadratic polynomial in
+x and y.
+
+.nf
+xxterms = "none", xyterms = "none"
+xxorder = 3, xyorder = 3, yxorder = 3, yyorder = 3
+
+ xi = a11 + a21 * x + a12 * y +
+ a31 * x ** 2 + a13 * y ** 2
+ eta = a11' + a21' * x + a12' * y +
+ a31' * x ** 2 + a13' * y ** 2
+
+xxterms = "half", xyterms = "half"
+xxorder = 3, xyorder = 3, yxorder = 3, yyorder = 3
+
+ xi = a11 + a21 * x + a12 * y +
+ a31 * x ** 2 + a22 * x * y + a13 * y ** 2
+ eta = a11' + a21' * x + a12' * y +
+ a31' * x ** 2 + a22' * x * y + a13' * y ** 2
+
+xxterms = "full", xyterms = "full"
+xxorder = 3, xyorder = 3, yxorder = 3, yyorder = 3
+
+ xi = a11 + a21 * x + a31 * x ** 2 +
+ a12 * y + a22 * x * y + a32 * x ** 2 * y +
+ a13 * y ** 2 + a23 * x * y ** 2 + a33 * x ** 2 * y ** 2
+ eta = a11' + a21' * x + a31' * x ** 2 +
+ a12' * y + a22' * x * y + a32' * x ** 2 * y +
+ a13' * y ** 2 + a23' * x * y ** 2 + a33' * x ** 2 * y ** 2
+.fi
+
+If \fIrefpoint\fR is "coords", then the sky projection reference point is set
+to the mean of the input celestial coordinates. For images where the true
+reference point is close to the center of the input coordinate distribution,
+this definition is adequate for many purposes. If \fIrefpoint\fR is "user",
+the user may either set the celestial coordinates of the reference
+point explicitly, e.g. \fIlngref\fR = 13:41:02.3 and \fIlatref\fR = -33:42:20,
+or point these parameters to the appropriate keywords in the input image
+header, e.g. \fIlngref\fR = RA, \fIlatref\fR = DEC for NOAO image data.
+If undefined the celestial coordinate system of the reference point
+\fIrefsystem\fR defaults to the celestial coordinate system of the input
+coordinates, otherwise it be any of the supported celestial coordinate
+systems described above. The user may also set \fIrefsystem\fR to the
+image header keyword containing the epoch of the celestial reference point
+coordinates in years, e.g. EPOCH for NOAO data. In this case the
+reference point coordinates are assumed to be equatorial FK4 coordinates at the
+epoch specified by EPOCH. The units of the reference point celestial
+coordinates are specified by the \fIlngrefunits\fR and \fIlatrefunits\fR
+parameters. Lngrefunits and latrefunits default to the values of the input
+coordinate units if undefined by either the user or the \fIrefsystem\fR
+parameter. ONCE DETERMINED THE REFERENCE POINT CANNOT BE RESET DURING
+THE FITTING PROCESS.
+
+The \fIxref\fR and \fIyref\fR parameters may be used to constrain the
+solution to putting the reference coordinate at the reference pixel.
+Effectively what this does is fix the zero-th order coefficient in the
+linear part of the solution. If a reference pixel is not specified the
+solution will produce a point determined from the zero-th order
+constant coefficient. This may not be what is expected based on
+the specified reference celestial coordinate.
+
+The fitting functions f and g are specified by the \fIfunction\fR parameter
+and may be power series polynomials, Legendre polynomials, or Chebyshev
+polynomials of order \fIxxorder\fR and \fIxyorder\fR in x and \fIyxorder\fR
+and \fIyyorder\fR in y. Cross-terms are optional and are turned on and
+off by setting the \fIxxterms\fR and \fIxyterms\fR parameters. If the
+\fBfitgeometry\fR parameter is anything other than "general", the order
+parameters assume the value 2 and the cross-terms switches assume the value
+"none", regardless of the values set by the user. All computation are done in
+double precision. Automatic pixel rejection may be enabled by setting
+\fImaxiter\fR > 0 and \fIreject\fR to a positive value, usually something
+in the range 2.5-5.0.
+
+CCMAP may be run interactively by setting \fIinteractive\fR to "yes" and
+inputting commands by the use of simple keystrokes. In interactive mode the
+user has the option of changing the fitting parameters and displaying the
+data and fit graphically until a satisfactory fit has been achieved. The
+keystroke commands are listed below.
+
+.nf
+
+? Print options
+f Fit data and graph fit with the current graph type (g,x,r,y,s)
+g Graph the data and the current fit
+x,r Graph the xi residuals versus x and y respectively
+y,s Graph the eta residuals versus x and y respectively
+d,u Delete or undelete the data point nearest the cursor
+o Overplot the next graph
+c Toggle the line of constant x and y plotting option
+t Plot a line of constant x and y through nearest data point
+l Print xishift, etashift, xscale, yscale, xrotate, yrotate
+q Exit the interactive fitting code
+.fi
+
+The parameters listed below can be changed interactively with simple colon
+commands. Typing the parameter name along will list the current value.
+
+.nf
+:show List parameters
+:projection Sky projection
+:refpoint Sky projection reference point
+:fit [value] Fit type (shift,xyscale,rotate,rscale,rxyscale,general)
+:function [value] Fitting function (chebyshev,legendre,polynomial)
+:xxorder [value] Xi fitting function order in x
+:xyorder [value] Xi fitting function order in y
+:yxorder [value] Eta fitting function order in x
+:yyorder [value] Eta fitting function order in y
+:xxterms [n/h/f] The xi fit cross terms type
+:yxterms [n/h/f] The eta fit cross terms type
+:maxiter [value] Maximum number of rejection iterations
+:reject [value] K-sigma rejection threshold
+.fi
+
+The final fit is stored in the text database file \fIdatabase\fR file in a
+format suitable for use by the CCSETWCS and CCTRAN tasks. Each fit is
+stored in a record whose name is the name of the input image \fIimage\fR
+if one is supplied, or the name of the input coordinate file \fIinput\fR.
+
+If the \fIupdate\fR switch is "yes" and an input image is specified,
+a new image wcs is derived from the linear component of the computed plate
+solution and written to the image header. The numerical components of
+the new image wcs are written to the standards FITS keywords, CRPIX, CRVAL,
+and CD, with the actual values depending on the input pixel coordinate
+system \fIpixsystem\fR.
+The FITS keywords which define the image celestial coordinate
+system CTYPE, RADECSYS, EQUINOX, and MJD-WCS are set by the \fIinsystem\fR and
+\fIprojection\fR parameters.
+
+The first four characters of the values of the ra / longitude and dec / latitude
+axis CTYPE keywords specify the celestial coordinate system. They are set to
+RA-- / DEC- for equatorial coordinate systems, ELON / ELAT for the ecliptic
+coordinate system, GLON / GLAT for the galactic coordinate system, and
+SLON / SLAT for the supergalactic coordinate system.
+
+The second four characters of the values of the ra / longitude and dec /
+latitude axis CTYPE keywords specify the sky projection geometry. IRAF
+currently supports the TAN, SIN, ARC, AIT, CAR, CSC, GLS, MER, MOL, PAR, PCO,
+QSC, STG, TSC, and ZEA standard projections, in which case the second 4
+characters of CTYPE are set to -TAN, -ARC, -SIN, etc. IRAF and CCMAP also
+support the experiment TAN plus polynomials function driver.
+
+If the input celestial coordinate system is equatorial, the value of the
+RADECSYS keyword specifies the fundamental equatorial system, EQUINOX
+specifies the epoch of the mean place, and MJD-WCS specifies the epoch
+for which the mean place is correct. The permitted values of
+RADECSYS are FK4, FK4-NO-E, FK5, ICRS, and GAPPT. EQUINOX is entered in years
+and interpreted as a Besselian epoch for the FK4 system, a Julian epoch
+for the FK5 system. The epoch of the wcs MJD-WCS is entered as
+a modified Julian date. Only those keywords necessary to defined the
+new wcs are written. Any existing keywords which are not required to
+define the wcs or are redundant are removed, with the exception of
+DATE-OBS and EPOCH, which are left unchanged for obvious (DATE_OBS) and
+historical (use of EPOCH keyword at NOAO) reasons.
+
+If \fIverbose\fR is "yes", various pieces of useful information are
+printed to the terminal as the task proceeds. If \fIresults\fR is set to a
+file name then the original pixel and celestial coordinates, the fitted
+celestial coordinates, and the residuals of the fit in arcseconds are written
+to that file.
+
+The transformation computed by the "general" fitting geometry is arbitrary
+and does not correspond to a physically meaningful model. However the computed
+coefficients for the linear term can be given a simple geometrical
+interpretation for all the fitting geometries as shown below.
+
+.nf
+ fitting geometry = general (linear term)
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+
+ fitting geometry = shift
+ xi = a + x
+ eta = d + y
+
+ fitting geometry = xyscale
+ xi = a + b * x
+ eta = d + f * y
+
+ fitting geometry = rotate
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b * f - c * e = +/-1
+ b = f, c = -e or b = -f, c = e
+
+ fitting geometry = rscale
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b * f - c * e = +/- const
+ b = f, c = -e or b = -f, c = e
+
+ fitting geometry = rxyscale
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b * f - c * e = +/- const
+.fi
+
+The coefficients can be interpreted as follows. X0, y0, xi0, eta0
+are the origins in the reference and input frames respectively. By definition
+xi0 and eta0 are 0.0 and 0.0 respectively. Rotation and skew are the rotation
+of the x and y axes and their deviation from perpendicularity respectively.
+Xmag and ymag are the scaling factors in x and y in " / pixel and are assumed
+to be positive by definition.
+
+.nf
+ general (linear term)
+ xrotation = rotation - skew / 2
+ yrotation = rotation + skew / 2
+ b = xmag * cos (xrotation)
+ c = ymag * sin (yrotation)
+ e = -xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * x0 - c * y0 = xshift
+ d = eta0 - e * x0 - f * y0 = yshift
+
+ shift
+ xrotation = 0.0, yrotation = 0.0
+ xmag = ymag = 1.0
+ b = 1.0
+ c = 0.0
+ e = 0.0
+ f = 1.0
+ a = xi0 - x0 = xshift
+ d = eta0 - y0 = yshift
+
+ xyscale
+ xrotation 0.0 / 180.0 yrotation = 0.0
+ b = + /- xmag
+ c = 0.0
+ e = 0.0
+ f = ymag
+ a = xi0 - b * x0 = xshift
+ d = eta0 - f * y0 = yshift
+
+ rscale
+ xrotation = rotation + 0 / 180, yrotation = rotation
+ mag = xmag = ymag
+ const = mag * mag
+ b = mag * cos (xrotation)
+ c = mag * sin (yrotation)
+ e = -mag * sin (xrotation)
+ f = mag * cos (yrotation)
+ a = xi0 - b * x0 - c * y0 = xshift
+ d = eta0 - e * x0 - f * y0 = yshift
+
+ rxyscale
+ xrotation = rotation + 0 / 180, yrotation = rotation
+ const = xmag * ymag
+ b = xmag * cos (xrotation)
+ c = ymag * sin (yrotation)
+ e = -xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * x0 - c * y0 = xshift
+ d = eta0 - e * x0 - f * y0 = yshift
+.fi
+
+.ih
+REFERENCES
+
+
+Additional information on the IRAF world coordinate systems can be found in
+the help pages for the WCSEDIT and WCRESET tasks.
+Detailed documentation for the IRAF world coordinate system interface MWCS
+can be found in the file "iraf$sys/mwcs/MWCS.hlp". This file can be
+formatted and printed with the command "help iraf$sys/mwcs/MWCS.hlp fi+ |
+lprint".
+
+Details of the FITS header world coordinate system interface can
+be found in the draft paper "World Coordinate Systems Representations Within the
+FITS Format" by Hanisch and Wells, available from the iraf anonymous ftp
+archive and the draft paper which supersedes it "Representations of Celestial
+Coordinates in FITS" by Greisen and Calabretta available from the NRAO
+anonymous ftp archives.
+
+The spherical astronomy routines employed here are derived from the Starlink
+SLALIB library provided courtesy of Patrick Wallace. These routines
+are very well documented internally with extensive references provided
+where appropriate. Interested users are encouraged to examine the routines
+for this information. Type "help slalib" to get a listing of the SLALIB
+routines, "help slalib opt=sys" to get a concise summary of the library,
+and "help <routine>" to get a description of each routine's calling sequence,
+required input and output, etc. An overview of the library can be found in the
+paper "SLALIB - A Library of Subprograms", Starlink User Note 67.7
+by P.T. Wallace, available from the Starlink archives.
+
+
+
+.ih
+EXAMPLES
+
+1. Compute the plate scale for the test image dev$pix given the following
+coordinate list. Set the tangent point to the mean of the input celestial
+coordinates. Compute the plate scale interactively.
+
+.nf
+cl> type coords
+
+13:29:47.297 47:13:37.52 327.50 410.38
+13:29:37.406 47:09:09.18 465.50 62.10
+13:29:38.700 47:13:36.23 442.01 409.65
+13:29:55.424 47:10:05.15 224.35 131.20
+13:30:01.816 47:12:58.79 134.37 356.33
+
+cl> imcopy dev$pix pix
+
+cl> hedit pix epoch 1987.26
+
+cl> ccmap coords coords.db image=pix xcol=3 ycol=4 lngcol=1 latcol=2
+
+ ... a plot of the mapping function appears
+ ... type ? to see the list of commands
+ ... type x to see the xi fit residuals versus x
+ ... type r to see the xi fit residuals versus y
+ ... type y to see the eta fit residuals versus x
+ ... type s to see the eta fit residuals versus y
+ ... type g to return to the default plot
+ ... type l to see the computed x and y scales in " / pixel
+ ... type q to quit and save fit
+.fi
+
+2. Repeat example 2 but compute the fit non-interactively and list the
+fitted values of the ra and dec and their residuals on the standard
+output.
+
+.nf
+cl> ccmap coords coords.db image=pix results=STDOUT xcol=3 ycol=4 \
+lngcol=1 latcol=2 inter-
+
+# Coords File: coords Image: pix
+# Database: coords.db Record: pix
+# Refsystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Coordinate mapping status
+# XI fit ok. ETA fit ok.
+# Ra/Dec or Long/Lat fit rms: 0.229 0.241 (arcsec arcsec)
+# Coordinate mapping parameters
+# Sky projection geometry: tan
+# Reference point: 13:29:48.129 47:11:53.37 (hours degrees)
+# Reference point: 318.735 273.900 (pixels pixels)
+# X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+# X and Y axis rotation: 179.110 358.958 (degrees degrees)
+# Wcs mapping status
+# Ra/Dec or Long/Lat wcs rms: 0.229 0.241 (arcsec arcsec)
+#
+# Input Coordinate Listing
+# X Y Ra Dec Ra(fit) Dec(fit) Dra Ddec
+#
+327.5 410.4 13:29:47.30 47:13:37.5 13:29:47.28 47:13:37.9 0.128 -0.370
+465.5 62.1 13:29:37.41 47:09:09.2 13:29:37.42 47:09:09.2 -0.191 -0.062
+442.0 409.6 13:29:38.70 47:13:36.2 13:29:38.70 47:13:35.9 0.040 0.282
+224.3 131.2 13:29:55.42 47:10:05.2 13:29:55.40 47:10:05.1 0.289 0.059
+134.4 356.3 13:30:01.82 47:12:58.8 13:30:01.84 47:12:58.7 -0.267 0.091
+.fi
+
+3. Repeat the previous example but in this case input the position of the
+tangent point in fk4 1950.0 coordinates.
+
+.nf
+cl> ccmap coords coords.db image=pix results=STDOUT xcol=3 ycol=4 lngcol=1 \
+latcol=2 refpoint=user lngref=13:27:46.9 latref=47:27:16 refsystem=b1950.0 \
+inter-
+
+# Coords File: coords Image: pix
+# Database: coords.db Record: pix
+# Refsystem: b1950.0 Coordinates: equatorial FK4
+# Equinox: B1950.000 Epoch: B1950.00000000 MJD: 33281.92346
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Coordinate mapping status
+# XI fit ok. ETA fit ok.
+# Ra/Dec or Long/Lat fit rms: 0.229 0.241 (arcsec arcsec)
+# Coordinate mapping parameters
+# Sky projection geometry: tan
+# Reference point: 13:29:53.273 47:11:48.36 (hours degrees)
+# Reference point: 250.256 266.309 (pixels pixels)
+# X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+# X and Y axis rotation: 179.126 358.974 (degrees degrees)
+# Wcs mapping status
+# Ra/Dec or Long/Lat wcs rms: 0.229 0.241 (arcsec arcsec)
+#
+# Input Coordinate Listing
+# X Y Ra Dec Ra(fit) Dec(fit) Dra Ddec
+
+327.5 410.4 13:29:47.30 47:13:37.5 13:29:47.28 47:13:37.9 0.128 -0.370
+465.5 62.1 13:29:37.41 47:09:09.2 13:29:37.42 47:09:09.2 -0.191 -0.062
+442.0 409.6 13:29:38.70 47:13:36.2 13:29:38.70 47:13:35.9 0.040 0.282
+224.3 131.2 13:29:55.42 47:10:05.2 13:29:55.40 47:10:05.1 0.289 0.059
+134.4 356.3 13:30:01.82 47:12:58.8 13:30:01.84 47:12:58.7 -0.267 0.091
+.fi
+
+Note the computed image scales are identical in examples 2 and 3 but that
+the assumed position of the tangent point is different (the second estimate
+is more accurate) producing different values for the pixel and celestial
+coordinates of the reference point and small differences in the computed
+rotation angles.
+
+4. Repeat the previous example but in this case extract the position of the
+tangent point in from the image header keywords RA, DEC, and EPOCH.
+
+.nf
+cl> imheader pix l+
+
+...
+DATE-OBS= '05/04/87' / DATE DD/MM/YY
+RA = '13:29:24.00' / RIGHT ASCENSION
+DEC = '47:15:34.00' / DECLINATION
+EPOCH = 1987.26 / EPOCH OF RA AND DEC
+...
+
+cl> ccmap coords coords.db image=pix results=STDOUT xcol=3 ycol=4 \
+lngcol=1 latcol=2 refpoint=user lngref=RA latref=DEC refsystem=EPOCH \
+inter-
+
+# Coords File: coords Image: pix
+# Database: coords.db Record: pix
+# Refsystem: fk4 b1987.26 Coordinates: equatorial FK4
+# Equinox: B1987.260 Epoch: B1987.26000000 MJD: 46890.84779
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Coordinate mapping status
+# XI fit ok. ETA fit ok.
+# Ra/Dec or Long/Lat fit rms: 0.229 0.241 (arcsec arcsec)
+# Coordinate mapping parameters
+# Sky projection geometry: tan
+# Reference point: 13:29:56.232 47:11:38.19 (hours degrees)
+# Reference point: 211.035 252.447 (pixels pixels)
+# X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+# X and Y axis rotation: 179.135 358.983 (degrees degrees)
+# Wcs mapping status
+# Ra/Dec or Long/Lat wcs rms: 0.229 0.241 (arcsec arcsec)
+#
+# Input Coordinate Listing
+# X Y Ra Dec Ra(fit) Dec(fit) Dra Ddec
+
+327.5 410.4 13:29:47.30 47:13:37.5 13:29:47.28 47:13:37.9 0.128 -0.370
+465.5 62.1 13:29:37.41 47:09:09.2 13:29:37.42 47:09:09.2 -0.191 -0.062
+442.0 409.6 13:29:38.70 47:13:36.2 13:29:38.70 47:13:35.9 0.040 0.282
+224.3 131.2 13:29:55.42 47:10:05.2 13:29:55.40 47:10:05.1 0.289 0.059
+134.4 356.3 13:30:01.82 47:12:58.8 13:30:01.84 47:12:58.7 -0.267 0.091
+
+.fi
+
+Note that the position of the tangent point is slightly different again but
+that this does not have much affect on the fitted coordinates for this image.
+
+5. Repeat the third example but this time store the computed world coordinate
+system in the image header and check the header update with the imheader and
+skyctran tasks.
+
+.nf
+cl> imheader pix l+
+...
+DATE-OBS= '05/04/87' / DATE DD/MM/YY
+RA = '13:29:24.00' / RIGHT ASCENSION
+DEC = '47:15:34.00' / DECLINATION
+EPOCH = 1987.26 / EPOCH OF RA AND DEC
+...
+
+cl> ccmap coords coords.db image=pix results=STDOUT xcol=3 ycol=4 \
+lngcol=1 latcol=2 refpoint=user lngref=13:27:46.9 latref=47:27:16 \
+refsystem=b1950.0 inter- update+
+
+# Coords File: coords Image: pix
+# Database: coords.db Record: pix
+# Refsystem: b1950.0 Coordinates: equatorial FK4
+# Equinox: B1950.000 Epoch: B1950.00000000 MJD: 33281.92346
+# Insystem: j2000 Coordinates: equatorial FK5
+# Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+# Coordinate mapping status
+# Coordinate mapping status
+# XI fit ok. ETA fit ok.
+# Ra/Dec or Long/Lat fit rms: 0.229 0.241 (arcsec arcsec)
+# Coordinate mapping parameters
+# Sky projection geometry: tan
+# Reference point: 13:29:53.273 47:11:48.36 (hours degrees)
+# Reference point: 250.256 266.309 (pixels pixels)
+# X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+# X and Y axis rotation: 179.126 358.974 (degrees degrees)
+# Wcs mapping status
+# Ra/Dec or Long/Lat wcs rms: 0.229 0.241 (arcsec arcsec)
+# Updating image header wcs
+#
+#
+# Input Coordinate Listing
+# X Y Ra Dec Ra(fit) Dec(fit) Dra Ddec
+
+327.5 410.4 13:29:47.30 47:13:37.5 13:29:47.28 47:13:37.9 0.128 -0.370
+465.5 62.1 13:29:37.41 47:09:09.2 13:29:37.42 47:09:09.2 -0.191 -0.062
+442.0 409.6 13:29:38.70 47:13:36.2 13:29:38.70 47:13:35.9 0.040 0.282
+224.3 131.2 13:29:55.42 47:10:05.2 13:29:55.40 47:10:05.1 0.289 0.059
+134.4 356.3 13:30:01.82 47:12:58.8 13:30:01.84 47:12:58.7 -0.267 0.091
+
+cl> imheader pix l+
+...
+DATE-OBS= '05/04/87' / DATE DD/MM/YY
+RA = '13:29:24.00' / RIGHT ASCENSION
+DEC = '47:15:34.00' / DECLINATION
+EPOCH = 1987.26 / EPOCH OF RA AND DEC
+...
+RADECSYS= 'FK5 '
+EQUINOX = 2000.
+MJD-WCS = 51544.5
+WCSDIM = 2
+CTYPE1 = 'RA---TAN'
+CTYPE2 = 'DEC--TAN'
+CRVAL1 = 202.471969550729
+CRVAL2 = 47.1967667056819
+CRPIX1 = 250.255619786203
+CRPIX2 = 266.308757328719
+CD1_1 = -2.1224568721716E-4
+CD1_2 = -3.8136850875221E-6
+CD2_1 = -3.2384199624421E-6
+CD2_2 = 2.12935798198448E-4
+LTM1_1 = 1.
+LTM2_2 = 1.
+WAT0_001= 'system=image'
+WAT1_001= 'wtype=tan axtype=ra'
+WAT2_001= 'wtype=tan axtype=dec'
+...
+
+cl> skyctran coords STDOUT "pix log" "pix world" lngcol=3 latcol=4 trans+
+
+# Insystem: pix logical Projection: TAN Ra/Dec axes: 1/2
+# Coordinates: equatorial FK5 Equinox: J2000.000
+# Epoch: J2000.00000000 MJD: 51544.50000
+# Outsystem: pix world Projection: TAN Ra/Dec axes: 1/2
+# Coordinates: equatorial FK5 Equinox: J2000.000
+# Epoch: J2000.00000000 MJD: 51544.50000
+
+# Input file: incoords Output file: STDOUT
+
+13:29:47.297 47:13:37.52 13:29:47.284 47:13:37.89
+13:29:37.406 47:09:09.18 13:29:37.425 47:09:09.24
+13:29:38.700 47:13:36.23 13:29:38.696 47:13:35.95
+13:29:55.424 47:10:05.15 13:29:55.396 47:10:05.09
+13:30:01.816 47:12:58.79 13:30:01.842 47:12:58.70
+
+.fi
+
+Note that two versions of the rms values are printed, one for the fit
+and one for the wcs fit. For the default fitting parameters these
+two estimates should be identical. If a non-linear high order plate
+solution is requested however, the image wcs will have lower precision
+than the than the full plate solution, because only the linear component
+of the plate solution is preserved in the wcs.
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+cctran,ccsetwcs,skyctran,imctran,finder.tfinder,finder.tastrom
+.endhelp
diff --git a/pkg/images/imcoords/doc/ccsetwcs.hlp b/pkg/images/imcoords/doc/ccsetwcs.hlp
new file mode 100644
index 00000000..b5700cbc
--- /dev/null
+++ b/pkg/images/imcoords/doc/ccsetwcs.hlp
@@ -0,0 +1,562 @@
+.help ccsetwcs Jun99 images.imcoords
+.ih
+NAME
+ccsetwcs -- create an image wcs from a plate solution
+.ih
+USAGE
+ccsetwcs image database solutions
+.ih
+PARAMETERS
+.ls images
+The input images for which the wcs is to be created.
+.le
+.ls database
+The text database file written by the ccmap task containing the
+plate solutions. If database is undefined ccsetwcs computes
+the image wcs using the xref, yref, xmag, ymag, xrotation, yrotation,
+lngref, latref, lngrefunits, latrefunits, and projection parameters.
+.le
+.ls solutions
+The list of plate solutions. The number of plate solutions must be one
+or equal to the number of input images. Solutions is either a user name
+supplied to the ccmap task, or the
+name of the ccmap task input image for which the plate solution is valid,
+or the name of the coordinate file that the ccmap task used to compute the
+plate solution. The quantities stored in transform always supersede the
+values of the xref, yref, xmag, ymag, xrotation, yrotation, lngref, latref,
+lnrefunits, latrefunits, and projection parameters.
+.le
+.ls xref = INDEF, yref = INDEF
+The x and y pixel coordinates of the sky projection reference point.
+If database is undefined then xref and yref default to the center of the
+image in pixel coordinates, otherwise these parameters are ignored.
+.le
+.ls xmag = INDEF, ymag = INDEF
+The x and y scale factors in arcseconds per pixel. If database is undefined
+xmag and ymag default to 1.0 and 1.0 arcsec / pixel, otherwise these parameters
+are ignored.
+.le
+.ls xrotation = INDEF, yrotation = INDEF
+The x and y rotation angles in degrees measured counter-clockwise with
+respect to the x and y axes. Xrotation and yrotation are interpreted as the
+rotation of the coordinates with respect to the x and y axes and default 0.0
+and 0.0 degrees. For example xrotation and yrotation values of 30.0 and 30.0
+will rotate a point 30 degrees counter-clockwise with respect to the x and y
+axes. To flip the x axis coordinates in this case either set the angles to
+210.0 and 30.0 degrees or leave the angles set to 30.0 and 30.0 and set the
+xmag parameter to a negative value. To set east to the up, down, left, and
+right directions, set xrotation to 90, 270, 180, and 0 respectively. To set
+north to the up, down, left, and right directions, set yrotation to 0, 180,
+90, and 270 degrees respectively. Any global rotation must be added to both the
+xrotation and yrotation values.
+.le
+.ls lngref = INDEF, latref = INDEF
+The celestial coordinates of the sky projection reference point, e.g.
+the ra and dec of the reference point for equatorial systems. If database is
+undefined lngref and latref default to 0.0 and 0.0, otherwise these parameters
+are ignored.
+.le
+.ls lngunits = "", latunits = ""
+The units of the lngref and latref parameters.
+The options are "hours", "degrees", "radians" for the ra / longitude
+coordinates, and "degrees" and "radians" for the dec / latitude coordinates.
+If database is undefined then lngunits and latunits default to the preferred
+units for the celestial coordinate system defined by the \fIcoosystem\fR
+parameter, otherwise these parameters are ignored.
+.le
+.ls transpose = no
+Transpose the newly created image wcs ?
+.le
+.ls projection = "tan"
+The sky projection geometry. The most commonly used projections in
+astronomy are "tan", "arc", "sin", and "lin". Other supported projections
+are "ait", "car", "csc", "gls", "mer", "mol", "par", "pco", "qsc", "stg",
+"tsc", and "zea".
+.le
+.ls coosystem = "j2000"
+The celestial coordinate system. The systems of most interest to users
+are "icrs", "j2000" and "b1950" which stand for the ICRS J2000.0, FK5 J2000.0,
+and FK4 B1950.0 celestial coordinate systems respectively. The full set of
+options are listed below. The celestial coordinate system sets the preferred
+units for the lngref and latref parameters and the correct values of the image
+wcs header keywords CTYPE, RADECSYS, EQUINOX, and MJD-WCS if the image header
+wcs is updated. If database is undefined the coosystem parameter is used,
+otherwise this parameter is ignored.
+
+.ls equinox [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system if equinox is a
+Julian epoch, e.g. J2000.0 or 2000.0, or the equatorial mean place
+pre-IAU 1976 system (FK4) if equinox is a Besselian epoch, e.g. B1950.0
+or 1950.0. Julian equinoxes are prefixed by a J or j, Besselian equinoxes
+by a B or b. Equinoxes without the J / j or B / b prefix are treated as
+Besselian epochs if they are < 1984.0, Julian epochs if they are >= 1984.0.
+Epoch is the epoch of the observation and may be a Julian
+epoch, a Besselian epoch, or a Julian date. Julian epochs
+are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to the epoch type of
+equinox if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls icrs [equinox] [epoch]
+The International Celestial Reference System where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk5 [equinox] [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system where equinox is a
+Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0. Epoch
+is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls noefk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system but without the E-terms
+where equinox is a Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day. If undefined epoch defaults to equinox.
+.le
+.ls apparent epoch
+The equatorial geocentric apparent place post-IAU 1976 system where
+epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date.
+.le
+.ls ecliptic epoch
+The ecliptic coordinate system where epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch values < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day.
+.le
+.ls galactic [epoch]
+The IAU 1958 galactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+.ls supergalactic [epoch]
+The deVaucouleurs supergalactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+
+In all the above cases fields in [] are optional with the defaults as
+described. The epoch field for icrs, fk5, galactic, and supergalactic
+coordinate systems is required only if the input coordinates are in the
+equatorial fk4, noefk4, fk5, or icrs systems and proper motions are defined.
+.le
+.ls update = yes
+Update the world coordinate system in the input image headers ?
+The numerical quantities represented by the keywords CRPIX,
+CRVAL, and CD are computed from the linear portion of the plate solution.
+The values of the keywords CTYPE, RADECSYS, EQUINOX, and MJD-WCS
+are set by the \fIprojection\fR and \fIcoosystem\fR parameters if database
+is undefined, otherwise projection and coosystem are read from the plate
+solution. As there is currently no standard mechanism for storing the higher
+order plate solution terms if any in the image header wcs, these terms are
+ignored. Any existing image wcs represented by the above keywords is
+overwritten during the update.
+.le
+.ls pixsystem = "logical"
+The pixel coordinate system. The options are:
+.ls logical
+The logical pixel coordinate system is the coordinate system of the image
+pixels on disk. Since most users measure the pixel coordinates of objects
+in this system, "logical" is the system of choice for most applications.
+.le
+.ls physical
+The physical coordinate system is the pixel coordinate system of the
+parent image. This option is useful for users working on images that are
+pieces of a larger mosaic.
+.le
+
+The pixsystem parameter is only used if no database solution is specified.
+Otherwise pixsystem is read from the database file.
+.le
+.ls verbose = yes
+Print detailed messages about the progress of the task on the standard output ?
+.le
+
+.ih
+DESCRIPTION
+
+CCSETWCS creates an image world coordinate system from the plate solution
+computed by the CCMAP task or supplied by the user, and writes it to the
+headers of the input images \fIimages\fR if the \fIupdate\fR parameter is yes.
+
+The plate solution can either be read from record \fIsolutions\fR in the
+database file \fIdatabase\fR written by CCMAP, or specified by the user
+via the \fIxref\fR, \fIyref\fR, \fIxmag\fR, \fIymag\fR, \fIxrotation\fR,
+\fIyrotation\fR, \fIlngref\fR, \fIlatref\fR, \fIlngunits\fR, \fIlatunits\fR,
+\fItranspose\fR, \fIprojection\fR, \fIcoosystem\fR and \fIpixsystem\fR
+parameters.
+
+The plate solution computed by CCMAP has the following form where x and y
+are the image pixel coordinates and xi and eta are the corresponding standard
+coordinates in arcseconds per pixel. The standard coordinates are computed
+by applying the appropriate sky projection to the celestial coordinates.
+
+
+.nf
+ xi = f (x, y)
+ eta = g (x, y)
+.fi
+
+The functions f and g are either power series, Legendre, or Chebyshev
+polynomials whose order and region of validity were set by the user when
+CCMAP was run. The computed plate solution is somewhat arbitrary and does
+not correspond to any physically meaningful model. However the linear
+component of the plate solution can be given the simple geometrical
+interpretation shown below.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = xmag * cos (xrotation)
+ c = ymag * sin (yrotation)
+ e = -xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * xref - c * yref = xshift
+ d = eta0 - e * xref - f * yref = yshift
+ xi0 = 0.0
+ eta0 = 0.0
+.fi
+
+xref, yref, xi0, and eta0 are the origins of the pixel and standard
+coordinate systems respectively. xmag and ymag are the x and y scale factors
+in " / pixel and xrotation and yrotation are the rotation angles measured
+counter-clockwise of the x and y axes.
+
+If the CCMAP database is undefined then CCSETWCS computes a linear plate
+solution using the parameters \fIxref\fR, \fIyref\fR, \fIxmag\fR,
+\fIymag\fR, \fIxrotation\fR, \fIyrotation\fR, \fIlngref\fR, \fIlatref\fR,
+\fIlngunits\fR, \fIlatunits\fR, \fItranspose\fR, and
+\fIprojection\fR as shown below. Note that in this case
+xrotation and yrotation are interpreted as the rotation of the coordinates
+themselves not the coordinate axes.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = xmag * cos (xrotation)
+ c = -ymag * sin (yrotation)
+ e = xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * xref - c * yref = xshift
+ d = eta0 - e * xref - f * yref = yshift
+ xi0 = 0.0
+ eta0 = 0.0
+.fi
+
+The \fItranspose\fR parameter can be used to transpose the newly created
+image wcs.
+
+If the \fIupdate\fR switch is "yes" and an input image is specified,
+a new image wcs is derived from the linear component of the computed plate
+solution and written to the image header. The numerical components of
+the new image wcs are written to the standards FITS keywords, CRPIX, CRVAL,
+and CD, with the actual values depending on the pixel coordinate system
+\fIpixsystem\fR read from the database or set by the user. The FITS keywords
+which define the image celestial coordinate system CTYPE, RADECSYS, EQUINOX,
+and MJD-WCS are set by the \fIcoosystem\fR and \fIprojection\fR parameters.
+
+The first four characters of the values of the ra / longitude and dec / latitude
+axis CTYPE keywords specify the celestial coordinate system. They are set to
+RA-- / DEC- for equatorial coordinate systems, ELON / ELAT for the ecliptic
+coordinate system, GLON / GLAT for the galactic coordinate system, and
+SLON / SLAT for the supergalactic coordinate system.
+
+The second four characters of the values of the ra / longitude and dec /
+latitude axis CTYPE keywords specify the sky projection geometry.
+The second four characters of the values of the ra / longitude and dec /
+latitude axis CTYPE keywords specify the sky projection geometry. IRAF
+currently supports the TAN, SIN, ARC, AIT, CAR, CSC, GLS, MER, MOL, PAR, PCO,
+QSC, STG, TSC, and ZEA standard projections, in which case the second 4
+characters of CTYPE are set to -TAN, -ARC, -SIN, etc.
+
+If the input celestial coordinate system is equatorial, the value of the
+RADECSYS keyword specifies the fundamental equatorial system, EQUINOX
+specifies the epoch of the mean place, and MJD-WCS specifies the epoch
+for which the mean place is correct. The permitted values of
+RADECSYS are FK4, FK4-NO-E, FK5, ICRS, and GAPPT. EQUINOX is entered in years
+and interpreted as a Besselian epoch for the FK4 system, a Julian epoch
+for the FK5 and ICRS system. The epoch of the wcs MJD-WCS is entered as
+a modified Julian date. Only those keywords necessary to defined the
+new wcs are written. Any existing keywords which are not required to
+define the wcs or are redundant are removed, with the exception of
+DATE-OBS and EPOCH, which are left unchanged for obvious (DATE-OBS) and
+historical (use of EPOCH keyword at NOAO) reasons.
+
+If \fIverbose\fR is "yes", various pieces of useful information are
+printed to the terminal as the task proceeds.
+
+.ih
+REFERENCES
+
+Additional information on the IRAF world coordinate systems can be found in
+the help pages for the WCSEDIT and WCRESET tasks.
+Detailed documentation for the IRAF world coordinate system interface MWCS
+can be found in the file "iraf$sys/mwcs/MWCS.hlp". This file can be
+formatted and printed with the command "help iraf$sys/mwcs/MWCS.hlp fi+ |
+lprint".
+
+Details of the FITS header world coordinate system interface can
+be found in the draft paper "World Coordinate Systems Representations Within the
+FITS Format" by Hanisch and Wells, available from the iraf anonymous ftp
+archive and the draft paper which supersedes it "Representations of Celestial
+Coordinates in FITS" by Greisen and Calabretta available from the NRAO
+anonymous ftp archives.
+
+The spherical astronomy routines employed here are derived from the Starlink
+SLALIB library provided courtesy of Patrick Wallace. These routines
+are very well documented internally with extensive references provided
+where appropriate. Interested users are encouraged to examine the routines
+for this information. Type "help slalib" to get a listing of the SLALIB
+routines, "help slalib opt=sys" to get a concise summary of the library,
+and "help <routine>" to get a description of each routine's calling sequence,
+required input and output, etc. An overview of the library can be found in the
+paper "SLALIB - A Library of Subprograms", Starlink User Note 67.7
+by P.T. Wallace, available from the Starlink archives.
+
+
+
+.ih
+EXAMPLES
+
+1. Compute the plate solution for an image with the ccmap task and then
+use the ccsetwcs task to create the image wcs. Check the results with the
+imheader and skyctran tasks.
+
+.nf
+cl> type coords
+13:29:47.297 47:13:37.52 327.50 410.38
+13:29:37.406 47:09:09.18 465.50 62.10
+13:29:38.700 47:13:36.23 442.01 409.65
+13:29:55.424 47:10:05.15 224.35 131.20
+13:30:01.816 47:12:58.79 134.37 356.33
+
+
+cl> ccmap coords coords.db image=pix xcol=3 ycol=4 lngcol=1 latcol=2 \
+inter-
+Coords File: coords Image: pix
+ Database: coords.db Record: pix
+Refsystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Coordinate mapping status
+ Ra/Dec or Long/Lat fit rms: 0.229 0.241 (arcsec arcsec)
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:48.129 47:11:53.37 (hours degrees)
+ Reference point: 318.735 273.900 (pixels pixels)
+ X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+ X and Y axis rotation: 179.110 358.958 (degrees degrees)
+Wcs mapping status
+ Ra/Dec or Long/Lat wcs rms: 0.229 0.241 (arcsec arcsec)
+
+cl> type coords.db
+# Mon 15:10:37 13-May-96
+begin coords
+ xrefmean 318.7460000000001
+ yrefmean 273.9320000000001
+ lngmean 13.49670238888889
+ latmean 47.19815944444444
+ coosystem j2000
+ projection tan
+ lngref 13.49670238888889
+ latref 47.19815944444444
+ lngunits hours
+ latunits degrees
+ xpixref 318.7352667484295
+ ypixref 273.9002619912411
+ geometry general
+ function polynomial
+ xishift 247.3577084680361
+ etashift -206.1795977453246
+ xmag 0.7641733802338992
+ ymag 0.7666917500560622
+ xrotation 179.1101291109185
+ yrotation 358.9582148846163
+ wcsxirms 0.2288984454992771
+ wcsetarms 0.2411034140453112
+ xirms 0.2288984454992771
+ etarms 0.2411034140453112
+ surface1 11
+ 3. 3.
+ 2. 2.
+ 2. 2.
+ 0. 0.
+ 134.3700000000001 134.3700000000001
+ 465.5000000000002 465.5000000000002
+ 62.1 62.1
+ 410.3800000000001 410.3800000000001
+ 247.3577084680361 -206.1795977453246
+ -0.7640812161068504 -0.011868034832272
+ -0.01393966623835092 0.7665650170136847
+ surface2 0
+
+
+
+cl> imheader pix l+
+...
+DATE-OBS= '05/04/87' / DATE DD/MM/YY
+RA = '13:29:24.00' / RIGHT ASCENSION
+DEC = '47:15:34.00' / DECLINATION
+EPOCH = 1987.26 / EPOCH OF RA AND DEC
+...
+
+
+cl> ccsetwcs pix coords.db pix
+Image: pix Database: coords.db Record: pix
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:48.129 47:11:53.37 (hours degrees)
+ Ra/Dec logical image axes: 1 2
+ Reference point: 318.735 273.900 (pixels pixels)
+ X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+ X and Y coordinate rotation: 179.110 358.958 (degrees degrees)
+Updating image header wcs
+
+cl> imheader pix l+
+...
+DATE-OBS= '05/04/87' / DATE DD/MM/YY
+RA = '13:29:24.00' / RIGHT ASCENSION
+DEC = '47:15:34.00' / DECLINATION
+EPOCH = 1987.26 / EPOCH OF RA AND DEC
+...
+RADECSYS= 'FK5 '
+EQUINOX = 2000.
+MJD-WCS = 51544.5
+WCSDIM = 2
+CTYPE1 = 'RA---TAN'
+CTYPE2 = 'DEC--TAN'
+CRVAL1 = 202.450535833334
+CRVAL2 = 47.1981594444445
+CRPIX1 = 318.735266748429
+CRPIX2 = 273.900261991241
+CD1_1 = -2.1224478225190E-4
+CD1_2 = -3.8721295106530E-6
+CD2_1 = -3.2966763422978E-6
+CD2_2 = 2.12934726948246E-4
+LTM1_1 = 1.
+LTM2_2 = 1.
+WAT0_001= 'system=image'
+WAT1_001= 'wtype=tan axtype=ra'
+WAT2_001= 'wtype=tan axtype=dec'
+
+cl> skyctran coords STDOUT "pix log" "pix world" lngcol=3 latcol=4 trans+
+
+# Insystem: pix logical Projection: TAN Ra/Dec axes: 1/2
+# Coordinates: equatorial FK5 Equinox: J2000.000
+# Epoch: J2000.00000000 MJD: 51544.50000
+# Outsystem: pix world Projection: TAN Ra/Dec axes: 1/2
+# Coordinates: equatorial FK5 Equinox: J2000.000
+# Epoch: J2000.00000000 MJD: 51544.50000
+
+# Input file: incoords Output file: STDOUT
+
+13:29:47.297 47:13:37.52 13:29:47.284 47:13:37.89
+13:29:37.406 47:09:09.18 13:29:37.425 47:09:09.24
+13:29:38.700 47:13:36.23 13:29:38.696 47:13:35.95
+13:29:55.424 47:10:05.15 13:29:55.396 47:10:05.09
+13:30:01.816 47:12:58.79 13:30:01.842 47:12:58.70
+.fi
+
+The skyctran task is used to test that the input image wcs is indeed correct.
+Columns 1 and 2 contain the original ra and dec values and columns 3 and 4
+contain the transformed values. The second imheader listing shows what the
+image wcs looks like.
+
+
+2. Repeat the previous example but enter the plate solution parameters by
+hand.
+
+.nf
+cl> ccsetwcs pix "" xref=318.735 yref=273.900 lngref=13:29:48.129 \
+latref=47:11:53.37 xmag=.764 ymag=.767 xrot=180.890 yrot=1.042
+Image: pix
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:48.129 47:11:53.37 (hours degrees)
+ Ra/Dec logical image axes: 1 2
+ Reference point: 318.735 273.900 (pixels pixels)
+ X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+ X and Y coordinate rotation: 180.890 1.042 (degrees degrees)
+Updating image header wcs
+
+
+cl> skyctran coords STDOUT "pix log" "pix world" lngcol=3 latcol=4 trans+
+
+# Insystem: pix logical Projection: TAN Ra/Dec axes: 1/2
+# Coordinates: equatorial FK5 Equinox: J2000.000
+# Epoch: J2000.00000000 MJD: 51544.50000
+# Outsystem: pix world Projection: TAN Ra/Dec axes: 1/2
+# Coordinates: equatorial FK5 Equinox: J2000.000
+# Epoch: J2000.00000000 MJD: 51544.50000
+
+# Input file: incoords Output file: STDOUT
+
+13:29:47.297 47:13:37.52 13:29:47.285 47:13:37.93
+13:29:37.406 47:09:09.18 13:29:37.428 47:09:09.17
+13:29:38.700 47:13:36.23 13:29:38.698 47:13:35.99
+13:29:55.424 47:10:05.15 13:29:55.395 47:10:05.04
+13:30:01.816 47:12:58.79 13:30:01.839 47:12:58.72
+.fi
+
+Note that there are minor differences between the results of examples 1
+and 2 due to precision differences in the input. Note also the difference
+in the way the xrotation and yrotation angles are defined between examples
+1 and 2. In example 2 the rotations are defined as coordinate rotations,
+whereas in example one they are described as axis rotations.
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+ccmap, cctran, skyctran, imctran
+.endhelp
diff --git a/pkg/images/imcoords/doc/ccstd.hlp b/pkg/images/imcoords/doc/ccstd.hlp
new file mode 100644
index 00000000..b24def49
--- /dev/null
+++ b/pkg/images/imcoords/doc/ccstd.hlp
@@ -0,0 +1,480 @@
+.help ccstd Oct00 images.imcoords
+.ih
+NAME
+ccstd -- transform pixel and celestial coordinates to standard coordinates
+and vice versa
+.ih
+USAGE
+ccstd input output database solutions
+.ih
+PARAMETERS
+.ls input
+The input coordinate files. Coordinates may be entered by hand by setting input
+to "STDIN".
+.le
+.ls output
+The output coordinate files. The number of output files must be one or equal
+to the number of input files. Results may be printed on the terminal by
+setting output to "STDOUT".
+.le
+.ls database
+The text database file written by the ccmap task which contains the
+desired plate solutions. If database is undefined ccstd computes the
+standard coordinates or pixel and celestial coordinates using the current
+values of the xref, yref, xmag ymag, xrotation, yrotation, lngref, latref,
+and projection parameters.
+.le
+.ls solutions
+The database record containing the desired plate solution.
+The number of records must be one or equal to the number of input coordinate
+files. Solutions is either the user name supplied to ccmap, the name of the
+image input to ccmap for which the plate solution is valid, or the name of the
+coordinate file that the ccmap task used to compute the plate solution.
+The quantities stored in solutions always supersede the values of the
+parameters xref, yref, xmag, ymag, xrotation, yrotation, lngref, latref,
+and projection.
+.le
+.ls geometry = "geometric"
+The type of geometric transformation. The geometry parameter is
+only requested if database is defined. The options are:
+.ls linear
+Transform the pixel coordinates to standard coordinates or vice versa
+using the linear part of the plate solution.
+only.
+.le
+.ls geometric
+Transform the pixel coordinates to standard coordinates or vice versa
+using the full plate solution.
+.le
+.le
+.ls forward = yes
+Transform from pixel and celestial coordinates to standard coordinates ? If
+forward is "no" then the plate solution is inverted and standard coordinates
+are transformed to pixel and celestial coordinates.
+.le
+.ls polar = no
+Convert to and from polar standard coordinates instead of Cartesian standard
+coordinates?
+.le
+.ls xref = INDEF, yref = INDEF
+The pixel coordinates of the reference point. If database is undefined
+then xref and yref default to 0.0 and 0.0, otherwise these parameters are
+ignored.
+.le
+.ls xmag = INDEF, ymag = INDEF
+The x and y scale factors in arcseconds per pixel. If database is undefined
+xmag and ymag default to 1.0 and 1.0 arcseconds per pixel, otherwise these
+parameters are ignored.
+.le
+.ls xrotation = INDEF, yrotation = INDEF
+The x and y rotation angles in degrees measured counter-clockwise with
+respect to the x and y axes. If database is undefined then xrotation and
+yrotation are interpreted as the rotation of the coordinates with respect
+to the x and y axes and default to 0.0 and 0.0 degrees. For example xrotation
+and yrotation values of 30.0 and 30.0 degrees will rotate a point 30 degrees
+counter-clockwise with respect to the x and y axes. To flip the x axis
+coordinates in this case either set the angles to 210.0 and 30.0 degrees
+or leave the angles at 30.0 and 30.0 and set the xmag parameter to a negative
+value. If database is defined these parameters are ignored. The ccmap task
+computes the x and y rotation angles of the x and y axes, not the rotation
+angle of the coordinates. An celestial coordinate system rotated 30 degrees
+counter-clockwise with respect to the pixel coordinate system will produce
+xrotation and yrotation values o 330.0 and 330.0 or equivalently -30.0 and
+-30.0 degrees in the database file not 30.0 and 30.0.
+.le
+.ls lngref = INDEF, latref = INDEF
+The celestial coordinates of the reference point, e.g. the ra and dec
+of the reference point for equatorial systems, galactic longitude and
+latitude of the reference for galactic systems. If database is undefined
+lngref and latref default to 0.0 and 0.0, otherwise these parameters are
+ignored.
+.le
+.ls lngunits = "", latunits = ""
+The units of the input or output ra / longitude and dec / latitude coordinates.
+The options are "hours", "degrees", "radians" for ra / longitude coordinates,
+and "degrees" and "radians" for dec / latitude systems. If lngunits and
+latunits are undefined they default to the values in the database records.
+If database is undefined then lngunits and latunits default to "hours" and
+"degrees" respectively.
+.le
+.ls projection = "tan"
+The sky projection geometry. The options are "tan", "sin", "arc" and
+"lin". If database is undefined then the value of the projection parameter
+is used, otherwise this parameter is ignored.
+.le
+.ls xcolumn = 1, ycolumn = 2
+The columns in the input coordinate file containing the x and y coordinates
+if the \fIforward\fR parameter is "yes", or the corresponding standard
+coordinates xi and eta if the forward parameter is "no".
+.le
+.ls lngcolumn = 3, latcolumn = 4
+The columns in the input coordinate file containing the celestial coordinates
+if the \fIforward\fR parameter is "yes", or the corresponding standard
+coordinates xi and eta if the forward parameter is "no".
+.le
+.ls lngformat = "", latformat = ""
+The default output format of the transformed coordinates in lngcolumn and
+latcolumn. If forward = yes then the default output format is "%10.3f".
+Otherwise the defaults are "%12.2h" for output coordinates in hours, "%11.1h"
+for output coordinates in degrees, and "%13.7g" for output coordinates in
+radians.
+.le
+.ls xformat = "", yformat = ""
+The default output format of the transformed coordinates in xcolumn and
+ycolumn. The default is "%10.3f".
+.le
+.ls min_sigdigits = 7
+The minimum precision of the output coordinates.
+.le
+
+.ih
+DESCRIPTION
+
+CCSTD transforms the list of input coordinates in the
+text file \fIinput\fR and writes the transformed
+coordinates to the text file \fIoutput\fR. The input coordinates
+are read from and the output coordinates written to, the columns
+\fIxcolumn\fR, \fIycolumn\fR, \fIlngcolumn\fR, and \fIlatcolumn\fR
+in the input and output
+files. The format of the output coordinates can be specified using the
+\fIxformat\fR, \fIyformat\fR, \fIlngformat\fR and \fIlatformat\fR parameters.
+If the output formats are unspecified the coordinates are written out with
+reasonable default formats, e.g. "%10.3f" for standard coordinates,
+"%12.2h" and "11.1h" for celestial coordinates in hours or degrees,
+and "%13.7g" for celestial coordinates in radians. All the remaining
+fields in the
+input file are copied to the output file without modification. Blank lines
+and comment lines are also passed to the output file unaltered.
+
+The plate solution can either be read from record \fIsolutions\fR
+in the database file \fIdatabase\fR written by CCMAP, or specified
+by the user via the \fIxref\fR, \fIyref\fR, \fIxmag\fR, \fIymag\fR,
+\fIxrotation\fR, \fIyrotation\fR, \fIlngref\fR, \fIlatref\fR,
+and \fIprojection\fR parameters. \fIlngunits\fR and \fIlatunits\fR
+define the units of the input celestial coordinates. If
+undefined they default to the values in the database or to
+the quantities "hours" and "degrees" respectively. The standard coordinates
+are always written and read in units of arcseconds.
+
+If the \fIforward\fR
+parameter is "yes", the input coordinates are assumed to be pixel coordinates
+and celestial coordinates. The pixel coordinates are transformed to standard
+coordinates using the plate solution, and celestial coordinates are
+transformed to standard coordinates using the position of the reference
+point \fIlngref\fR, \fIlatref\fR, and the projection specified by
+\fIprojection\fR. If \fIforward\fR is "no", then
+the input coordinates are assumed to be standard coordinates and
+those in \fIxcolumn\fR and \fIycolumn\fR are transformed to pixel
+coordinates by inverting the plate solution, and those in \fIlngcolumn\fR
+and \fIlatcolumn\fR are transformed to celestial coordinates using the
+position of the reference point and the specified projection.
+
+The plate solution computed by CCMAP has the following form where x and y
+are the pixel coordinates and xi and eta are the corresponding fitted standard
+coordinates in arcseconds per pixel. The observed standard coordinates are
+computed by applying the appropriate sky projection to the celestial
+coordinates.
+
+
+.nf
+ xi = f (x, y)
+ eta = g (x, y)
+.fi
+
+The functions f and g are either power series, Legendre, or Chebyshev
+polynomials whose order and region of validity were set by the user when
+CCMAP was run. The plate solution is arbitrary and does not correspond to
+any physically meaningful model. However the first order terms can be given
+the simple geometrical interpretation shown below.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = xmag * cos (xrotation)
+ c = ymag * sin (yrotation)
+ e = -xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * xref - c * yref = xshift
+ d = eta0 - e * xref - f * yref = yshift
+ xi0 = 0.0
+ eta0 = 0.0
+.fi
+
+xref, yref, xi0, and eta0 are the origins of the reference and output
+coordinate systems respectively. xi0 and eta0 are both 0.0 by default.
+xmag and ymag are the x and y scales in " / pixel, and xrotation and yrotation
+are the x and y axes rotation angles measured counter-clockwise from original
+x and y axes.
+
+If the CCMAP database is undefined then CCSTD computes a linear plate
+solution using the parameters \fIxref\fR, \fIyref\fR, \fIxmag\fR,
+\fIymag\fR, \fIxrotation\fR, \fIyrotation\fR, \fIlngref\fR, \fIlatref\fR,
+\fIlngunits\fR, \fIlatunits\fR and \fIprojection\fR as shown below. Note
+that in this case xrotation and yrotation are interpreted as the rotation
+of the coordinates not the rotation of the coordinate axes.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = xmag * cos (xrotation)
+ c = -ymag * sin (yrotation)
+ e = xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * xref - c * yref = xshift
+ d = eta0 - e * xref - f * yref = yshift
+ xi0 = 0.0
+ eta0 = 0.0
+.fi
+
+Linear plate solutions are evaluated in the forward and reverse sense
+using the appropriate IRAF mwcs system routines. Higher order plate
+solutions are evaluated in the forward sense using straight-forward
+evaluation of the polynomial terms, in the reverse sense by applying
+Newton's method to the plate solution.
+
+
+.ih
+FORMATS
+
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+.ih
+EXAMPLES
+
+.nf
+1. Compute the standard coordinates in arcseconds per pixel given a list of
+pixel and equatorial coordinates and the position of the reference point in
+pixel and equatorial coordinates.
+
+cl> type coords
+13:29:47.297 47:13:37.52 327.50 410.38
+13:29:37.406 47:09:09.18 465.50 62.10
+13:29:38.700 47:13:36.23 442.01 409.65
+13:29:55.424 47:10:05.15 224.35 131.20
+13:30:01.816 47:12:58.79 134.37 356.33
+
+cl> ccstd coords STDOUT "" xref=256.5 yref=256.5 lngref=13:29:48.1 \
+latref = 47:11:53.4 xcol=3 ycol=4 lngcol=1 latcol=2
+ -8.180 104.120 71.000 153.880
+-109.087 -164.189 209.000 -194.400
+ -95.753 102.854 185.510 153.150
+ 74.688 -108.235 -32.150 -125.300
+ 139.745 65.441 -122.130 99.830
+
+2. Repeat the previous example but output the results in polar coordinates.
+The first and third columns contain the radius coordinate in arcseconds,
+the second and fourth columns contain the position angle in degrees measured
+counter-clockwise with respect to the standard coordinates.
+
+cl> ccstd coords STDOUT "" xref=256.5 yref=256.5 lngref=13:29:48.1 \
+latref = 47:11:53.4 xcol=3 ycol=4 lngcol=1 latcol=2 polar+
+104.441 94.492 169.470 65.231
+197.124 236.400 285.434 317.073
+140.526 132.952 240.560 39.542
+131.504 304.608 129.359 255.609
+154.309 25.093 157.740 140.737
+
+
+3. Compute the plate solution and use it to evaluate the Cartesian and
+polar standard coordinates for the input coordinate list used in example 1.
+
+cl> ccmap coords coords.db xcol=3 ycol=4 lngcol=1 latcol=2 inter-
+Coords File: coords Image:
+ Database: coords.db Record: coords
+Refsystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Coordinate mapping status
+ Ra/Dec or Long/Lat fit rms: 0.229 0.241 (arcsec arcsec)
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:48.129 47:11:53.37 (hours degrees)
+ Reference point: 318.735 273.900 (pixels pixels)
+ X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+ X and Y axis rotation: 179.110 358.958 (degrees degrees)
+
+
+cl> type coords.db
+# Mon 10:29:13 24-Nov-97
+begin coords
+ xrefmean 318.7460000000001
+ yrefmean 273.9320000000001
+ lngmean 13.49670238888889
+ latmean 47.19815944444444
+ coosystem j2000
+ projection tan
+ lngref 13.49670238888889
+ latref 47.19815944444444
+ lngunits hours
+ latunits degrees
+ xpixref 318.7352667484295
+ ypixref 273.9002619912411
+ geometry general
+ function polynomial
+ xishift 247.3577084680361
+ etashift -206.1795977453246
+ xmag 0.7641733802338992
+ ymag 0.7666917500560622
+ xrotation 179.1101291109185
+ yrotation 358.9582148846163
+ wcsxirms 0.2288984454992771
+ wcsetarms 0.2411034140453112
+ xirms 0.2288984454992771
+ etarms 0.2411034140453112
+ surface1 11
+ 3. 3.
+ 2. 2.
+ 2. 2.
+ 0. 0.
+ 134.3700000000001 134.3700000000001
+ 465.5000000000002 465.5000000000002
+ 62.1 62.1
+ 410.3800000000001 410.3800000000001
+ 247.3577084680361 -206.1795977453246
+ -0.7640812161068504 -0.011868034832272
+ -0.01393966623835092 0.7665650170136847
+ surface2 0
+
+
+cl> ccstd coords STDOUT coords.db coords xcol=3 ycol=4 lngcol=1 latcol=2
+ -8.471 104.146 -8.599 104.517
+-109.378 -164.163 -109.188 -164.100
+ -96.044 102.880 -96.084 102.598
+ 74.397 -108.210 74.107 -108.269
+ 139.454 65.467 139.721 65.376
+
+cl> ccstd coords STDOUT coords.db coords xcol=3 ycol=4 lngcol=1 latcol=2 \
+polar+
+104.490 94.650 104.870 94.704
+197.264 236.325 197.106 236.361
+140.744 133.032 140.565 133.122
+131.317 304.509 131.202 304.391
+154.056 25.148 154.259 25.075
+
+4. Use the previous plate solution to transform the pixel and equatorial
+coordinates to standard coordinates but enter the plate solution by hand.
+
+cl> ccstd coords STDOUT "" xref=318.735 yref=273.900 lngref=13:29:48.129 \
+latref=47:11:53.37 xmag=.764 ymag=.767 xrot=180.890 yrot=1.042 xcol=3 \
+ycol=4 lngcol=1 latcol=2
+ -8.475 104.150 -8.599 104.559
+-109.382 -164.159 -109.161 -164.165
+ -96.048 102.884 -96.064 102.640
+ 74.393 -108.206 74.092 -108.313
+ 139.450 65.471 139.688 65.401
+
+cl> ccstd coords STDOUT "" xref=318.735 yref=273.900 lngref=13:29:48.129 \
+latref=47:11:53.37 xmag=.764 ymag=.767 xrot=180.890 yrot=1.042 xcol=3 \
+ycol=4 lngcol=1 latcol=2 polar+
+104.494 94.652 104.912 94.702
+197.263 236.324 197.145 236.378
+140.750 133.032 140.582 133.105
+131.311 304.509 131.230 304.374
+154.054 25.150 154.240 25.089
+
+Note that there are minor differences between the results of examples 3 and
+4 due to precision differences in the input, and that the angles input
+to ccstd in example 4 are the coordinate rotation angles not the axes
+rotation angles as printed by ccmap. The difference is exactly 180 degrees
+in both cases.
+
+5. Use the plate solution computed in example 3 to convert a list
+of standard coordinates into the equivalent pixel and celestial coordinates.
+
+cl> type stdcoords
+ -8.471 104.146 -8.599 104.517
+-109.378 -164.163 -109.188 -164.100
+ -96.044 102.880 -96.084 102.598
+ 74.397 -108.210 74.107 -108.269
+ 139.454 65.467 139.721 65.376
+
+cl> ccstd stdcoords STDOUT coords.db coords xcol=3 ycol=4 lngcol=1 latcol=2 \
+forward-
+
+13:29:47.30 47:13:37.5 327.499 410.381
+13:29:37.41 47:09:09.2 465.500 62.101
+13:29:38.70 47:13:36.2 442.010 409.650
+13:29:55.42 47:10:05.1 224.350 131.200
+13:30:01.82 47:12:58.8 134.370 356.330
+.fi
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+ccmap, ccsetwcs, cctran, finder.tastrom, skyctran
+.endhelp
diff --git a/pkg/images/imcoords/doc/cctran.hlp b/pkg/images/imcoords/doc/cctran.hlp
new file mode 100644
index 00000000..202598f6
--- /dev/null
+++ b/pkg/images/imcoords/doc/cctran.hlp
@@ -0,0 +1,412 @@
+.help cctran Dec96 images.imcoords
+.ih
+NAME
+cctran -- transform from pixel to celestial coordinates and vice versa
+using the computed plate solution
+.ih
+USAGE
+cctran input output database solutions
+.ih
+PARAMETERS
+.ls input
+The coordinate files to be transformed.
+.le
+.ls output
+The output coordinate files. The number of output files must
+be one or equal to the number of input files.
+.le
+.ls database
+The text database file written by the ccmap task containing the
+desired plate solution. If database is undefined cctran computes
+a linear plate solution using the current values of the xref, yref, xmag
+ymag, xrotation, yrotation, lngref, latref, and projection parameters.
+.le
+.ls solutions
+The database record containing the desired plate solution.
+The number of records must be one or equal to the number of input coordinate
+files. Solutions is either a user name supplied to ccmap, the name of the
+ccmap task
+input image for which the plate solution is valid, or the name of the
+coordinate file that the ccmap task used to compute the plate solution.
+The quantities stored in
+solutions always supersede the values of xref, yref, xmag, ymag,
+xrotation, yrotation, lngref, latref, and projection.
+.le
+.ls geometry = "geometric"
+The type of geometric transformation. The geometry parameter is
+only requested if database is defined. The options are:
+.ls linear
+Transform the coordinates using only the linear part of the plate solution.
+.le
+.ls geometric
+Transform the coordinates using the full plate solution.
+.le
+.le
+.ls forward = yes
+Transform from pixel to celestial coordinates ? If forward is "no" then
+the plate solution is inverted and celestial coordinates are transformed
+to pixel coordinates.
+.le
+.ls xref = INDEF, yref = INDEF
+The x and y pixel coordinates of the reference point. If database is undefined
+then xref and yref default to 0.0 and 0.0, otherwise these parameters are
+ignored.
+.le
+.ls xmag = INDEF, ymag = INDEF
+The x and y scale factors in arcseconds per pixel. If database is undefined
+xmag and ymag default to 1.0 and 1.0 arcseconds per pixel, otherwise these
+parameters are ignored.
+.le
+.ls xrotation = INDEF, yrotation = INDEF
+The x and y rotation angles in degrees measured counter-clockwise with
+respect to the x and y axes. Xrotation and yrotation are interpreted as the
+rotation of the coordinates with respect to the x and y axes and default to
+0.0 and 0.0 degrees. For example xrotation and yrotation values of 30.0 and
+30.0 degrees will rotate a point 30 degrees counter-clockwise with respect to
+the x and y axes. To flip the x axis coordinates in this case either set the
+angles to 210.0 and 30.0 degrees or leave the angles at 30.0 and 30.0 and set
+the xmag parameter to a negative value. To set east to the up, down, left, and
+right directions, set xrotation to 90, 270, 180, and 0 respectively. To set
+north to the up, down, left, and right directions, set yrotation to 0, 180,
+90, and 270 degrees respectively. Any global rotation must be added to both the
+xrotation and yrotation values.
+.le
+.ls lngref = INDEF, latref = INDEF
+The celestial coordinates of the reference point, e.g. the ra and dec
+of the reference point for equatorial systems, galactic longitude and
+latitude for galactic systems. If database is undefined
+lngref and latred default to 0.0 and 0.0, otherwise these parameters are
+ignored.
+.le
+.ls lngunits = "", latunits = ""
+The units of the input or output ra / longitude and dec / latitude coordinates.
+The options are "hours", "degrees", "radians" for ra / longitude coordinates,
+and "degrees" and "radians" for dec / latitude systems. If lngunits and
+latunits are undefined they default to the values in the database records.
+If database is undefined then lngunits and latunits default to "hours" and
+"degrees" respectively.
+.le
+.ls projection = "tan"
+The sky projection geometry. The most commonly used projections in
+astronomy are "tan", "arc", "sin", and "lin". Other supported projections
+are "ait", "car", "csc", "gls", "mer", "mol", "par", "pco", "qsc", "stg",
+"tsc", and "zea".
+.le
+.ls xcolumn = 1, ycolumn = 2
+The columns in the input coordinate file containing the x and y coordinates
+if the \fIforward\fR parameter is "yes", the celestial ra / longitude and
+dec / latitude if the forward parameter is "no".
+.le
+.ls lngformat = "", latformat = ""
+The format of the output coordinates. The defaults are "%10.3f" for
+output coordinates in pixels, "%12.2h" for coordinates in hours,
+"%11.1h" for coordinates in degrees,
+and "%13.7g" for coordinates in radians.
+.le
+.ls min_sigdigits = 7
+The minimum precision of the output coordinates.
+.le
+
+.ih
+DESCRIPTION
+
+CCTRAN applies the plate solution to a list of pixel or celestial
+coordinates in the text file \fIinput\fR and writes the transformed
+coordinates to the text file \fIoutput\fR. The input coordinates
+are read from and the output coordinates written to, the columns
+\fIxcolumn\fR and \fIycolumn\fR in the input and output
+files. The format of the output coordinates can be specified using the
+\fIlngformat\fR and \fIlatformat\fR parameters. If the output formats
+are unspecified the coordinates are written out with reasonable
+default precisions, e.g. "%10.3f" for pixel coordinates, "%12.2h" and "11.1h"
+for coordinates in hours or degrees,
+and "%13.7g" for coordinates in radians. All the remaining fields in the
+input file are copied to the output file without modification. Blank lines
+and comment lines are also passed to the output file unaltered.
+
+The plate solution is either read from record \fIsolutions\fR
+in the database file \fIdatabase\fR written by CCMAP, or specified
+by the user via the \fIxref\fR, \fIyref\fR, \fIxmag\fR, \fIymag\fR,
+\fIxrotation\fR, \fIyrotation\fR, \fIlngref\fR, \fIlatref\fR,
+and \fIprojection\fR parameters. If \fILngunits\fR and \fIlatunits\fR
+are undefined they default to the values in the database or to
+the quantities "hours" and "degrees" respectively.
+If the \fIforward\fR
+parameter is "yes", the input coordinates are assumed to be pixel coordinates
+and are transformed to celestial coordinates. If \fIforward\fR is "no", then
+the input coordinates are assumed to be celestial coordinates and are
+transformed to pixel coordinates.
+
+The transformation computed by CCMAP has the following form where x and y
+are the pixel coordinates and xi and eta are the corresponding standard
+coordinates in arcseconds per pixel. The standard coordinates are computed
+by applying the appropriate sky projection to the celestial coordinates.
+
+
+.nf
+ xi = f (x, y)
+ eta = g (x, y)
+.fi
+
+The functions f and g are either power series, Legendre, or Chebyshev
+polynomials whose order and region of validity were set by the user when
+CCMAP was run. The plate solution is arbitrary and does not correspond to
+any physically meaningful model. However the first order terms can be given
+the simple geometrical interpretation shown below.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = xmag * cos (xrotation)
+ c = ymag * sin (yrotation)
+ e = -xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * xref - c * yref = xshift
+ d = eta0 - e * xref - f * yref = yshift
+ xi0 = 0.0
+ eta0 = 0.0
+.fi
+
+xref, yref, xi0, and eta0 are the origins of the reference and output
+coordinate systems respectively. xi0 and eta0 are both 0.0 by default.
+xmag and ymag are the x and y scales in " / pixel, and xrotation and yrotation
+are the x and y axes rotation angles measured counter-clockwise from original
+x and y axes.
+
+If the CCMAP database is undefined then CCTRAN computes a linear plate
+solution using the parameters \fIxref\fR, \fIyref\fR, \fIxmag\fR,
+\fIymag\fR, \fIxrotation\fR, \fIyrotation\fR, \fIlngref\fR, \fIlatref\fR,
+\fIlngunits\fR, \fIlatunits\fR and \fIprojection\fR as shown below. Note
+that in this case xrotation and yrotation are interpreted as the rotation
+of the coordinates not the rotation of the coordinate axes.
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+ b = xmag * cos (xrotation)
+ c = -ymag * sin (yrotation)
+ e = xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = xi0 - b * xref - c * yref = xshift
+ d = eta0 - e * xref - f * yref = yshift
+ xi0 = 0.0
+ eta0 = 0.0
+.fi
+
+Linear plate solutions are evaluated in the forward and reverse sense
+using the appropriate IRAF mwcs system routines. Higher order plate
+solutions are evaluated in the forward sense using straight-forward
+evaluation of the polynomial terms, in the reverse sense by applying
+Newton's method to the plate solution.
+
+
+.ih
+FORMATS
+
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+.ih
+EXAMPLES
+
+1. Compute the plate solution and evaluate the forward transformation for
+the following input coordinate list.
+
+.nf
+cl> type coords
+13:29:47.297 47:13:37.52 327.50 410.38
+13:29:37.406 47:09:09.18 465.50 62.10
+13:29:38.700 47:13:36.23 442.01 409.65
+13:29:55.424 47:10:05.15 224.35 131.20
+13:30:01.816 47:12:58.79 134.37 356.33
+
+
+cl> ccmap coords coords.db xcol=3 ycol=4 lngcol=1 latcol=2 inter-
+Coords File: coords Image:
+ Database: coords.db Record: coords
+Refsystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+Coordinate mapping status
+ Ra/Dec or Long/Lat fit rms: 0.229 0.241 (arcsec arcsec)
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:48.129 47:11:53.37 (hours degrees)
+ Reference point: 318.735 273.900 (pixels pixels)
+ X and Y scale: 0.764 0.767 (arcsec/pixel arcsec/pixel)
+ X and Y axis rotation: 179.110 358.958 (degrees degrees)
+
+
+cl> type coords.db
+# Mon 15:10:37 13-May-96
+begin coords
+ xrefmean 318.7460000000001
+ yrefmean 273.9320000000001
+ lngmean 13.49670238888889
+ latmean 47.19815944444444
+ coosystem j2000
+ projection tan
+ lngref 13.49670238888889
+ latref 47.19815944444444
+ lngunits hours
+ latunits degrees
+ xpixref 318.7352667484295
+ ypixref 273.9002619912411
+ geometry general
+ function polynomial
+ xishift 247.3577084680361
+ etashift -206.1795977453246
+ xmag 0.7641733802338992
+ ymag 0.7666917500560622
+ xrotation 179.1101291109185
+ yrotation 358.9582148846163
+ wcsxirms 0.2288984454992771
+ wcsetarms 0.2411034140453112
+ xirms 0.2288984454992771
+ etarms 0.2411034140453112
+ surface1 11
+ 3. 3.
+ 2. 2.
+ 2. 2.
+ 0. 0.
+ 134.3700000000001 134.3700000000001
+ 465.5000000000002 465.5000000000002
+ 62.1 62.1
+ 410.3800000000001 410.3800000000001
+ 247.3577084680361 -206.1795977453246
+ -0.7640812161068504 -0.011868034832272
+ -0.01393966623835092 0.7665650170136847
+ surface2 0
+
+
+
+cl> cctran coords STDOUT coords.db coords xcol=3 ycol=4 lngformat=%0.3h \
+latformat=%0.2h
+13:29:47.297 47:13:37.52 13:29:47.284 47:13:37.89
+13:29:37.406 47:09:09.18 13:29:37.425 47:09:09.24
+13:29:38.700 47:13:36.23 13:29:38.696 47:13:35.95
+13:29:55.424 47:10:05.15 13:29:55.396 47:10:05.09
+13:30:01.816 47:12:58.79 13:30:01.842 47:12:58.70
+
+cl> cctran coords STDOUT coords.db coords xcol=1 ycol=2 forward-
+327.341 409.894 327.50 410.38
+465.751 62.023 465.50 62.10
+441.951 410.017 442.01 409.65
+223.970 131.272 224.35 131.20
+134.717 356.454 134.37 356.33
+.fi
+
+Note that for the forward transformation the original ras and decs are in
+columns 1 and 2 and the computed ras and decs are in columns 3 and 4, but
+for the reverse transformation the original x and y values are in columns
+3 and 4 and the computed values are in columns 1 and 2.
+
+
+2. Use the previous plate solution to transform x and y values to
+ra and dec values and vice versa but enter the plate solution by hand.
+
+.nf
+cl> cctran coords STDOUT "" xcol=3 ycol=4 lngformat=%0.3h latformat=%0.2h \
+xref=318.735 yref=273.900 lngref=13:29:48.129 latref=47:11:53.37 \
+xmag=.764 ymag=.767 xrot=180.890 yrot=1.042
+13:29:47.297 47:13:37.52 13:29:47.285 47:13:37.93
+13:29:37.406 47:09:09.18 13:29:37.428 47:09:09.17
+13:29:38.700 47:13:36.23 13:29:38.698 47:13:35.99
+13:29:55.424 47:10:05.15 13:29:55.395 47:10:05.04
+13:30:01.816 47:12:58.79 13:30:01.839 47:12:58.72
+
+cl> cctran coords STDOUT "" xcol=1 ycol=2 xref=318.735 yref=273.900 \
+lngref=13:29:48.129 latref=47:11:53.37 xmag=.764 ymag=.767 \
+xrot=180.890 yrot=1.042 forward-
+327.347 409.845 327.50 410.38
+465.790 62.113 465.50 62.10
+441.983 409.968 442.01 409.65
+223.954 131.334 224.35 131.20
+134.680 356.426 134.37 356.33
+
+.fi
+
+Note that there are minor differences between examples 1 and 2 due to
+precision differences in the input, and that the angles input to cctran
+in example 2 are the coordinate rotation angles not the axes rotation angles
+as printed by ccmap. The different is exactly 180 degrees in both cases.
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+ccmap, ccsetwcs, finder.tastrom, skyctran
+.endhelp
diff --git a/pkg/images/imcoords/doc/ccxymatch.hlp b/pkg/images/imcoords/doc/ccxymatch.hlp
new file mode 100644
index 00000000..6987a437
--- /dev/null
+++ b/pkg/images/imcoords/doc/ccxymatch.hlp
@@ -0,0 +1,781 @@
+.help ccxymatch Oct96 images.imcoords
+.ih
+NAME
+ccxymatch -- Match celestial and pixel coordinate lists using various methods
+.ih
+USAGE
+ccxymatch input reference output tolerance [ptolerance]
+.ih
+PARAMETERS
+.ls input
+The list of input pixel coordinate files.
+.le
+.ls reference
+The list of input celestial coordinate files. The number of celestial coordinate
+files must be one or equal to the number of pixel coordinate files.
+.le
+.ls output
+The output matched coordinate files containing: 1) the celestial coordinates
+of the matched objects in columns 1 and 2, 2) the pixel coordinates of the
+matched objects in columns 3 and 4, and 3) the line numbers of the matched
+objects in the celestial coordinate and pixel lists in columns 5 and 6.
+.le
+.ls tolerance
+The matching tolerance in arcseconds.
+.le
+.ls ptolerance
+The matching tolerance in pixels. The ptolerance parameter is required
+by the "triangles" matching algorithm but not by the "tolerance" matching
+algorithm.
+.le
+.ls refpoints = ""
+A file of tie points used to compute the linear transformation
+from the pixel coordinate system to the celestial coordinate system. Refpoints
+is a text file containing the celestial coordinates of 1-3 tie points
+in the first line, followed by the pixel coordinates of the same 1-3 tie points
+in succeeding lines. The celestial coordinates are assumed to be
+in the units specified by \fIlngunits\fR and \fIlatunits\fR.
+If refpoints is undefined then the parameters \fIxin\fR, \fIyin\fR,
+\fIxmag\fR, \fIymag\fR, \fIxrotation\fR, \fIyrotation\fR, \fIprojection\fR,
+\fIlngref\fR, and \fIlatref\fR are used to compute the linear transformation.
+.le
+.ls xin = INDEF, yin = INDEF
+The x and y origin of the pixel coordinate system. Xin and yin default to
+0.0 and 0.0 respectively.
+.le
+.ls xmag = INDEF, ymag = INDEF
+The x and y scale factors in arcseconds per pixel. Xmag and
+ymag default to 1.0 and 1.0 respectively.
+.le
+.ls xrotation = INDEF, yrotation = INDEF
+The x and y rotation angles measured in degrees counter-clockwise. Xrotation
+and yrotation default to 0.0 and 0.0 degrees respectively. To set east to the
+up, down, left, and right directions, set xrotation to 90, 270, 180, and 0
+respectively. To set north to the up, down, left, and right directions, set
+yrotation to 0, 180, 90, and 270 degrees respectively. Any global rotation
+must be added to both the xrotation and yrotation values.
+.le
+.ls projection = "tan"
+The sky projection geometry. The most commonly used projections in
+astronomy are "tan", "arc", "sin", and "lin". Other supported projections
+are "ait", "car", "csc", "gls", "mer", "mol", "par", "pco", "qsc", "stg",
+"tsc", and "zea".
+.le
+.ls lngref = INDEF, latref = INDEF
+The origin of the celestial coordinate system. Lngref and latref define the
+reference point of the sky projection \fIprojection\fR, and default to the
+mean of the ra / longitude and dec / latitude coordinates respectively. Lngref
+and latref are assumed to be in units of \fIlngunits\fR and \fIlatunits\fR.
+.le
+.ls lngcolumn = 1, latcolumn = 2
+The columns in the celestial coordinate list containing the ra / longitude
+and dec / latitude coordinate values.
+.le
+.ls xcolumn = 1, ycolumn = 2
+The columns in the pixel coordinate list containing the x and y coordinate
+values.
+.le
+.ls lngunits = "hours", latunits = "degrees"
+The units of the celestial coordinates. The options are "hours", "degrees",
+and "radians" for lngunits, and "degrees" and "radians" for latunits.
+.le
+.ls separation = 3.0
+The minimum separation in arcseconds for objects in the celestial coordinate
+lists. Objects closer together than separation arcseconds
+are removed from the celestial coordinate lists prior to matching.
+.le
+.ls pseparation = 9.0
+The minimum separation in pixels for objects in the pixel coordinate
+lists. Objects closer together than pseparation pixels
+are removed from the pixel coordinate lists prior to matching.
+.le
+.ls matching = "triangles"
+The matching algorithm. The choices are:
+.ls tolerance
+A linear transformation is applied to the pixel coordinates,
+the appropriate projection is applied to the celestial coordinates,
+the transformed pixel and celestial coordinates are sorted,
+points which are too close together are removed, and the pixel coordinates
+which most closely match the celestial coordinates to within the
+user specified tolerance are determined. The tolerance algorithm requires
+an initial estimate for the linear transformation. This estimate can be
+derived by supplying the coordinates of tie points via the
+\fIrefpoints\fR file, or by setting the linear transformation parameters
+\fIxin\fR, \fIyin\fR, \fIxmag\fR, \fIymag\fR, \fIxrotation\fR,
+\fIyrotation\fR, \fIprojection\fR, \fIlngref\fR, and \fIlatref\fR. Assuming that
+a good initial estimate for the required linear transformation is supplied,
+the tolerance algorithm functions well in the presence of shifts, axis
+flips, x and y scale changes, rotations, and axis skew between the two
+coordinate systems. The algorithm is sensitive to higher order distortion terms
+in the coordinate transformation.
+.le
+.ls triangles
+A linear transformation is applied to the pixel coordinates,
+the appropriate projection is applied to the celestial coordinates,
+the transformed pixel and celestial coordinates are sorted, points
+which are too close together are removed, and the pixel coordinates
+are matched to the celestial coordinates using a triangle pattern
+matching algorithm and user specified tolerance parameters.
+The triangles pattern matching algorithm does not require prior knowledge
+of the linear transformation, although it will use a transformation if one
+is supplied. The algorithm functions well in the presence of
+shifts, axis flips, magnification, and rotation between the two coordinate
+systems, as long as both lists have a reasonable number of objects
+in common and the errors in the computed coordinates are small.
+However as the algorithm depends on comparisons of similar triangles, it
+is sensitive to differences in the x and y coordinate scales,
+skew between the x and y axes, and higher order distortion terms
+in the coordinate transformation.
+.le
+.le
+.ls nmatch = 30
+The maximum number of celestial and pixel coordinates used
+by the "triangles" pattern matching algorithm. If either list contains
+more coordinates than nmatch, the lists are subsampled. Nmatch should be
+kept small as the computation and memory requirements of the "triangles"
+algorithm depend on a high power of the lengths of the respective lists.
+.le
+.ls ratio = 10.0
+The maximum ratio of the longest to shortest side of the
+triangles generated by the "triangles" pattern matching algorithm.
+Triangles with computed longest to shortest side ratios > ratio
+are rejected from the pattern matching algorithm. Ratio should never
+be set higher than 10.0 but may be set as low as 5.0.
+.le
+.ls nreject = 10
+The maximum number of rejection iterations for the "triangles" pattern
+matching algorithm.
+.le
+.ls lngformat = "", latformat = ""
+The format of the output celestial coordinates. The default formats are
+"%13.3h", "%13.3h", and "%13.7g" for units of "hours", "degrees", and
+"radians" respectively.
+.le
+.ls xformat = "%13.3f", yformat = "%13.3f"
+The format of the output pixel coordinates.
+By default the coordinates are output right justified in a field of
+13 characters with 3 places following the decimal point.
+.le
+.ls verbose = yes
+Print messages about the progress of the task ?
+.le
+
+.ih
+DESCRIPTION
+
+CCXYMATCH matches ra / dec or longitude / latitude coordinates in the
+celestial coordinate list \fIreference\fR to their corresponding x and y
+coordinates in the pixel coordinate list \fIinput\fR using user specified
+tolerances in arcseconds \fItolerance\fR and pixels \fIptolerance\fR, and
+writes the matched coordinates to the output file \fIoutput\fR. The output
+file is suitable for input to the plate solution computation task CCMAP.
+
+CCXYMATCH matches the coordinate lists by: 1) projecting the celestial
+coordinates onto a plane using the sky projection geometry \fIprojection\fR
+and the reference point \fIlngref\fR and \fIlatref\fR,
+2) computing an initial guess for the linear transformation required to
+match the pixel coordinate system to the projected celestial coordinate system,
+3) applying the computed transformation to the pixel coordinates, 4) sorting
+the projected celestial and pixel coordinates lists, 5) removing points with a
+minimum separation specified by the parameters \fIseparation\fR and
+\fIpseparation\fR from both lists, 6) matching the two lists using either
+the "triangles" or "tolerance" matching algorithms, and 7) writing the matched
+list to the output file.
+
+An initial estimate for the linear transformation is computed in one of
+two ways. If \fIrefpoints\fR is defined, the celestial and pixel coordinates
+of up to three tie points are read from succeeding lines in the refpoints file,
+and used to compute the linear transformation. The coordinates of the tie
+points can be typed in by hand if \fIrefpoints\fR is "STDIN". The formats of
+two sample refpoints files are shown below.
+
+.nf
+# First sample refpoints file (1 reference file and N input files)
+
+ra1 dec1 [ra2 dec2 [ra3 dec3]] # tie points for reference coordinate file
+ x1 y1 [ x2 y2 [ x3 y3]] # tie points for input coordinate file 1
+ x1 y1 [ x2 y2 [ x3 y3]] # tie points for input coordinate file 2
+.. .. [ .. .. [ .. ..]
+ x1 y1 [ x2 y2 [ x3 y3]] # tie points for input coordinate file N
+
+
+# Second sample refpoints file (N reference files and N input files)
+
+ra1 dec1 [ra2 dec2 [ra3 dec3]] # tie points for reference coordinate file 1
+ x1 y1 [ x2 y2 [ x3 y3]] # tie points for input coordinate file 1
+ra1 dec1 [ra2 dec2 [ra3 dec3]] # tie points for reference coordinate file 2
+ x1 y1 [ x2 y2 [ x3 y3]] # tie points for input coordinate file 2
+ .. .. [ .. .. [ .. ..]]
+ra1 dec1 [ra2 dec2 [ra3 dec3]] # tie points for reference coordinate file N
+ x1 y1 [ x2 y2 [ x3 y3]] # tie points for input coordinate file N
+
+.fi
+
+If the refpoints file is undefined the parameters \fIxin\fR, \fIxin\fR,
+\fIxmag\fR, \fIymag\fR, \fIxrotation\fR, \fIxrotation\fR are used
+to compute a linear transformation from the pixel coordinates to the
+standard coordinates xi and eta as shown below. Orientation and skew
+are the orientation of the x and y axes and their deviation from
+perpendicularity respectively.
+
+
+.nf
+ xi = a + b * x + c * y
+ eta = d + e * x + f * y
+
+ xrotation = orientation - skew / 2
+ yrotation = orientation + skew / 2
+ b = xmag * cos (xrotation)
+ c = -ymag * sin (yrotation)
+ e = xmag * sin (xrotation)
+ f = ymag * cos (yrotation)
+ a = 0.0 - b * xin - c * yin = xshift
+ d = 0.0 - e * xin - f * yin = yshift
+.fi
+
+Both methods of computing the initial linear transformation compute the
+standard coordinates xi and eta by projecting the celestial coordinates
+onto a plane using the sky projection geometry \fIprojection\fR and the
+reference point \fIlngref\fR and \fIlatref\fR. The celestial coordinates
+are assumed to be in units of \fIlngunits\fR and \fIlatunits\fR and the
+standard coordinates are in arcseconds. The linear transformation and its
+geometric interpretation are shown below.
+
+The celestial and pixel coordinates are read from columns \fIlngcolumn\fR and
+\fIlatcolumn\fR in the celestial coordinate list, and \fIxcolumn\fR, and
+\fIycolumn\fR in the pixel coordinate list respectively. The pixel
+coordinates are transformed using the linear transformation described above,
+the celestial coordinate in units of \fIlngunits\fR and \fIlatunits\fR
+are projected to standard coordinates in arcseconds, and stars closer together
+than \fIseparation\fR arcseconds and \fIpseparation\fR pixels are removed
+from the celestial and pixel coordinate lists respectively.
+
+The coordinate lists are matched using the matching algorithm specified by
+\fImatching\fR. If matching is "tolerance", CCXYMATCH searches the transformed
+sorted pixel coordinate list for the coordinates that are within the matching
+tolerance \fItolerance\fR and closest to the current standard coordinates.
+The major advantage of the "tolerance" algorithm is that it can handle x and y
+scale differences and axis skew in the coordinate transformation. The major
+disadvantage of the "tolerance" algorithm is that the user must supply
+tie point information in all but the simplest case of small x and y
+shifts between the pixel and celestial coordinate systems.
+
+If matching is "triangles", CCXYMATCH constructs a list of triangles
+using up to \fInmatch\fR celestial coordinates and transformed pixel
+coordinates and performs a pattern matching operation on the resulting
+triangle lists. If the number of coordinates in both lists is less than
+\fInmatch\fR the entire list is matched using the "triangles" algorithm
+directly, otherwise the "triangles" algorithm is used to estimate a new
+linear transformation, the input coordinate list is transformed using
+the new transformation, and the entire list is matched using the "tolerance"
+algorithm. The major advantage of the "triangles" algorithm is that it
+requires no tie point information from the user. The major disadvantages of the
+algorithm are that, it is sensitive to x and y scale differences and axis
+skew between the celestial and pixel coordinate systems, and can be
+computationally expensive.
+
+The matched celestial and pixel coordinates are written to columns 1, 2, 3,
+and 4 of the output file, in the formats specified by the \fIlngformat\fR,
+\fIlatformat\fR, \fIxformat\fR and \fIyformat\fR parameters. The original
+line numbers in the celestial and pixels coordinate files are written to
+columns 5 and 6.
+
+If \fIverbose\fR is yes, detailed messages about actions taken by the
+task are written to the terminal as the task executes.
+
+.ih
+ALGORITHMS
+
+The "triangles" algorithm uses a sophisticated pattern matching
+technique which requires no tie point information from the user.
+It is expensive computationally and is therefore restricted to a maximum
+of \fInmatch\fR objects from the celestial and pixel coordinate lists.
+
+The "triangles" algorithm first generates a list
+of all the possible triangles that can be formed from the points in each list.
+For a list of nmatch points this number is the combinatorial factor
+nmatch! / [(nmatch-3)! * 3!] or nmatch * (nmatch-1) * (nmatch-2) / 6.
+The length of the perimeter, ratio of longest to shortest side, cosine
+of the angle between the longest and shortest side, the tolerances in
+the latter two quantities and the direction of the arrangement of the vertices
+of each triangle are computed and stored in a table.
+Triangles with vertices closer together than \fItolerance\fR and
+\fIptolerance\fR, or
+with a ratio of the longest to shortest side greater than \fIratio\fR
+are discarded. The remaining triangles are sorted in order of increasing
+ratio. A sort merge algorithm is used to match the triangles using the
+ratio and cosine information, the tolerances in these quantities, and
+the maximum tolerances for both lists. The ratios of the
+perimeters of the matched triangles are compared to the most common ratio
+for the entire list, and triangles which deviate too widely from this number
+are discarded. The number of triangles remaining are divided into
+the number which match in the clockwise sense and the number which match
+int the counter-clockwise sense. Those in the minority category
+are eliminated.
+The rejection step can be repeated up to \fInreject\fR times or until
+no more rejections occur, whichever comes first.
+The last step in the algorithm is a voting procedure in which each remaining
+matched triangle casts three votes, one for each matched pair of vertices.
+Points which have fewer than half the maximum number of
+votes are discarded. The final set of matches are written to the output file.
+
+The "triangles" algorithm functions well when the celestial and
+pixel coordinate lists have a sufficient number of objects (50%,
+in some cases as low as 25%) of their objects in common, any distortions
+including x and y scale differences and skew between the two systems are small,
+and the random errors in the coordinates are small. Increasing the value of
+the \fItolerance\fR parameter will increase the ability to deal with
+distortions but will also produce more false matches which after some point
+will swamp the true matches.
+
+.ih
+FORMATS
+
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+.ih
+REFERENCES
+
+A detailed description of the "triangles" pattern matching algorithm used here
+can be found in the article "A Pattern-Matching Algorithm for Two-
+Dimensional Coordinate Lists" by E.J. Groth, A.J. 91, 1244 (1986).
+
+.ih
+EXAMPLES
+
+1. Compute the plate solution for a 1528 by 2288 B band image of M51 by
+matching a list of reference stars extracted from the Guide Star Catalog
+with the regions task against a list of bright stars detected with the daofind
+task. The approximate image center is RA = 13:29:52.8 and DEC = +47:11:41
+(J2000) and the image scale is 0.43 arcseconds / pixel.
+
+.nf
+... Get the guide stars (see stsdas.analysis.gasp package).
+cl> regions 13:29:52.8 47:11:41 0.27 m51b.gsc.tab
+
+... Convert the binary table to a text file (see package tables.ttools).
+cl> tprint m51b.gsc.tab > m51b.gsc
+
+... Examine the guide star list.
+cl> type m51b.gsc
+
+# Table m51b.gsc.tab Tue 10:39:55 22-Oct-96
+
+# row RA_HRS RA_DEG DEC_DEG MAG
+# hours degrees degrees magnitudes
+
+ 1 13:29:13.33 202:18:19.9 47:14:16.3 12.3
+ 2 13:29:05.51 202:16:22.6 47:10:44.7 14.8
+ 3 13:29:48.60 202:27:09.0 47:07:42.5 15.0
+ 4 13:29:47.30 202:26:49.4 47:13:37.5 10.9
+ 5 13:29:31.65 202:22:54.7 47:18:54.7 15.0
+ 6 13:29:06.16 202:16:32.4 47:04:53.1 14.9
+ 7 13:29:37.40 202:24:21.1 47:09:09.2 15.1
+ 8 13:29:38.70 202:24:40.5 47:13:36.2 15.0
+ 9 13:29:55.42 202:28:51.3 47:10:05.2 15.4
+ 10 13:29:06.91 202:16:43.7 47:04:07.9 12.4
+ 11 13:29:29.73 202:22:25.9 47:12:04.1 15.1
+ 12 13:30:07.96 202:31:59.4 47:05:18.3 14.7
+ 13 13:30:01.82 202:30:27.2 47:12:58.8 11.8
+ 14 13:30:36.75 202:39:11.2 47:04:05.9 14.9
+ 15 13:30:34.04 202:38:30.6 47:16:44.8 13.2
+ 16 13:30:14.95 202:33:44.3 47:10:27.6 13.4
+
+... Locate bright stars in the image (see noao.digiphot.daophot package).
+... Suitable values for fwhmpsf, sigma, ... and threshold can be determined
+... using the imstatistics and imexamine tasks. Some experimentation may be
+... necessary to determine optimal values.
+cl> daofind m51b "default" fwhmpsf=4.0 sigma=5.0 threshold=20.0
+
+... Examine the star list.
+cl> type m51b.coo.1
+
+ ...
+#N XCENTER YCENTER MAG SHARPNESS SROUND GROUND ID
+ ...
+ 401.034 147.262 -2.315 0.473 -0.075 -0.170 1
+ 261.137 453.696 -1.180 0.481 -0.373 -0.135 2
+ 860.002 480.061 -1.397 0.373 -0.218 -0.178 3
+ 69.342 675.895 -0.955 0.368 -0.294 -0.133 4
+ 1127.791 680.033 -1.166 0.449 -0.515 -0.326 5
+ 972.435 691.544 -1.722 0.449 -0.327 -0.060 6
+ 1348.891 715.084 -1.069 0.389 -0.242 -0.145 7
+ 946.114 797.067 -0.543 0.406 -0.198 -0.069 8
+ 698.455 811.407 -1.620 0.437 -0.038 -0.028 9
+ 964.566 853.201 -0.317 0.382 0.031 -0.086 10
+ 236.088 864.817 -3.515 0.429 -0.164 -0.035 11
+ 919.703 909.835 -3.775 0.447 0.051 0.007 12
+ 406.592 985.807 -0.715 0.424 -0.307 -0.068 13
+ 920.790 986.083 -0.600 0.364 -0.047 0.021 14
+ 761.403 1037.795 -1.944 0.383 -0.023 0.120 15
+ 692.012 1050.603 -0.508 0.339 -0.365 -0.164 16
+ 1023.330 1060.144 -1.897 0.381 -0.246 -0.288 17
+ 681.864 1066.937 -0.059 0.467 -0.175 0.135 18
+ 1307.802 1085.564 -1.173 0.435 0.032 -0.207 19
+ 716.494 1094.800 -0.389 0.421 -0.412 -0.032 20
+ 715.935 1106.616 -3.747 0.649 0.271 0.245 21
+ 1093.813 1300.189 -1.557 0.377 -0.309 -0.078 22
+ 596.406 1353.798 -0.461 0.383 0.029 -0.103 23
+ 1212.117 1362.636 -0.362 0.369 -0.180 0.043 24
+ 251.355 1488.048 -0.909 0.357 -0.390 0.077 25
+ 600.659 1630.261 -1.392 0.423 0.013 -0.312 26
+ 329.448 2179.233 -0.824 0.442 -0.463 0.325 27
+
+... Match the two lists using the "triangles" algorithm and tolerances of
+... 1.0 arcseconds and 3.0 pixels respectively.
+cl> ccxymatch m51b.coo.1 m51b.gsc m51b.mat.1 1.0 3.0 lngcolumn=2 latcolumn=4
+
+... Examine the matched file.
+cl> type m51b.mat.1
+
+# Input: m51b.coo.1 Reference: m51b.gsc Number of tie points: 0
+# Initial linear transformation
+# xref[tie] = 0. + 1. * x[tie] + 0. * y[tie]
+# yref[tie] = 0. + 0. * x[tie] + 1. * y[tie]
+# dx: 0.00 dy: 0.00 xmag: 1.000 ymag: 1.000 xrot: 0.0 yrot: 0.0
+#
+# Column definitions
+# Column 1: Reference Ra / Longitude coordinate
+# Column 2: Reference Dec / Latitude coordinate
+# Column 3: Input X coordinate
+# Column 4: Input Y coordinate
+# Column 5: Reference line number
+# Column 6: Input line number
+
+ 13:29:48.600 47:07:42.50 860.002 480.061 8 44
+ 13:29:38.700 47:13:36.20 1093.813 1300.189 13 63
+ 13:29:55.420 47:10:05.20 698.455 811.407 14 50
+ 13:29:29.730 47:12:04.10 1307.802 1085.564 16 60
+ 13:30:07.960 47:05:18.30 401.034 147.262 17 42
+ 13:30:14.950 47:10:27.60 236.088 864.817 21 52
+
+... Compute the plate solution.
+cl> ccmap m51b.mat.1 ccmap.db results=STDOUT xcolumn=3 ycolumn=4 lngcolumn=1 \
+latcolumn=2 refpoint=user lngref=13:29:52.8 latref=47:11:41 interactive=no
+
+Coords File: m51b.mat.1 Image:
+ Database: ccmap.db Record: m51b.mat.1
+Refsystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.000 MJD: 51544.50000
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.000 MJD: 51544.50000
+Coordinate mapping status
+ XI fit ok. ETA fit ok.
+ Ra/Dec or Long/Lat fit rms: 0.206 0.103 (arcsec arcsec)
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:52.800 47:11:41.00 (hours degrees)
+ Reference point: 760.656 1033.450 (pixels pixels)
+ X and Y scale: 0.430 0.431 (arcsec/pixel arcsec/pixel)
+ X and Y axis rotation: 180.158 359.991 (degrees degrees)
+
+ Input Coordinate Listing
+ X Y Ra Dec Ra(fit) Dec(fit) Dra Ddec
+
+ 860.0 480.1 13:29:48.60 47:07:42.5 13:29:48.62 47:07:42.5 -0.153 0.017
+1093.8 1300.2 13:29:38.70 47:13:36.2 13:29:38.73 47:13:36.4 -0.258 -0.164
+ 698.5 811.4 13:29:55.42 47:10:05.2 13:29:55.43 47:10:05.2 -0.062 0.024
+1307.8 1085.6 13:29:29.73 47:12:04.1 13:29:29.70 47:12:04.0 0.318 0.123
+ 401.0 147.3 13:30:07.96 47:05:18.3 13:30:07.96 47:05:18.4 0.028 -0.073
+ 236.1 864.8 13:30:14.95 47:10:27.6 13:30:14.94 47:10:27.5 0.127 0.073
+.fi
+
+
+
+2. Repeat example 1 but replace the daofind pixel list with one generated
+using the center task and a finder chart created with the skymap task.
+
+.nf
+... Get the guide stars. (see stsdas.analysis.gasp package)
+cl> regions 13:29:52.8 47:11:41 0.27 m51b.gsc.tab
+
+... Create the finder chart (see stsdas.analysis.gasp package)
+cl> gasp.skymap m51b.gsc.tab 13:29:52.8 47:11:41 INDEF 0.27 \
+objstyle=square racol=RA_HRS deccol=DEC_DEG magcol=MAG interactive- \
+dev=stdplot
+
+... Convert the binary table to a text file. (see tables.ttools package)
+cl> tprint m51b.gsc.tab > m51b.gsc
+
+... Mark and center the guide stars on the image display using the finder
+... chart produced by the skymap task and the center task (see the
+... digiphot.apphot package).
+cl> display m51b 1 fi+
+cl> center m51b cbox=7.0 ...
+cl> pdump m51b.ctr.1 xcenter,ycenter yes > m51b.pix
+
+... Display the pixel coordinate list.
+cl> type m51b.pix
+
+401.022 147.183
+236.044 864.882
+698.368 811.329
+860.003 480.051
+1127.754 680.020
+1307.819 1085.615
+1093.464 1289.595
+1212.001 1362.594
+1348.963 715.085
+
+... Match the two lists using the "triangles" algorithm and tolerances of
+... 1.0 arcseconds and 3.0 pixels respectively.
+cl> ccxymatch m51b.pix m51b.gsc m51b.mat.2 1.0 3.0 lngcolumn=2 latcolumn=4
+
+... Examine the matched file.
+cl> type m51b.mat.2
+
+# Input: m51b.pix Reference: m51b.gsc Number of tie points: 0
+# Initial linear transformation
+# xi[tie] = 0. + 1. * x[tie] + 0. * y[tie]
+# eta[tie] = 0. + 0. * x[tie] + 1. * y[tie]
+# dx: 0.00 dy: 0.00 xmag: 1.000 ymag: 1.000 xrot: 0.0 yrot: 0.0
+#
+# Column definitions
+# Column 1: Reference Ra / Longitude coordinate
+# Column 2: Reference Dec / Latitude coordinate
+# Column 3: Input X coordinate
+# Column 4: Input Y coordinate
+# Column 5: Reference line number
+# Column 6: Input line number
+
+ 13:29:48.600 47:07:42.50 860.003 480.051 8 4
+ 13:29:37.400 47:09:09.20 1127.754 680.020 12 5
+ 13:29:55.420 47:10:05.20 698.368 811.329 14 3
+ 13:29:29.730 47:12:04.10 1307.819 1085.615 16 6
+ 13:30:07.960 47:05:18.30 401.022 147.183 17 1
+ 13:30:14.950 47:10:27.60 236.044 864.882 21 2
+
+... Compute the plate solution.
+cl> ccmap m51b.mat.2 ccmap.db results=STDOUT xcolumn=3 ycolumn=4 lngcolumn=1 \
+latcolumn=2 refpoint=user lngref=13:29:52.8 latref=47:11:41 interactive=no
+
+Coords File: m51b.mat.2 Image:
+ Database: junk.db Record: m51b.mat.2
+Refsystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.000 MJD: 51544.50000
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.000 MJD: 51544.50000
+Coordinate mapping status
+ XI fit ok. ETA fit ok.
+ Ra/Dec or Long/Lat fit rms: 0.312 0.0664 (arcsec arcsec)
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:52.800 47:11:41.00 (hours degrees)
+ Reference point: 761.093 1033.230 (pixels pixels)
+ X and Y scale: 0.430 0.431 (arcsec/pixel arcsec/pixel)
+ X and Y axis rotation: 180.175 359.998 (degrees degrees)
+
+ Input Coordinate Listing
+ X Y Ra Dec Ra(fit) Dec(fit) Dra Ddec
+.fi
+
+
+3. Repeat example 1 but use the "tolerance" matching algorithm and apriori
+knowledge of the celestial and pixel coordinates of the nucleus of M51,
+the x and y image scales, and the orientation of the detector on the telescope
+to match the two lists.
+
+.nf
+... Match the two lists using the ccxymatch "tolerance" algorithm and
+... a matching tolerance of 2.0 arcseconds. Note the negative and positive
+... signs on the xmag and ymag parameters and lack of any rotation,
+... indicating that north is up and east is to the left.
+cl> ccxymatch m51b.coo.1 m51b.gsc m51b.mat.3 2.0 lngcolumn=2 latcolumn=4 \
+matching=tolerance xin=761.40 yin=1037.80 xmag=-0.43 ymag=0.43 xrot=0.0 \
+yrot=0.0 lngref=13:29:52.80 latref=47:11:42.9
+
+... Examine the matched file.
+cl> type m51b.mat.3
+
+# Input: m51b.coo.1 Reference: m51b.gsc Number of tie points: 0
+# Initial linear transformation
+# xref[tie] = 327.402 + -0.43 * x[tie] + 0. * y[tie]
+# yref[tie] = -446.254 + 0. * x[tie] + 0.43 * y[tie]
+# dx: 327.40 dy: -446.25 xmag: 0.430 ymag: 0.430 xrot: 180.0 yrot: 0.0
+#
+# Column definitions
+# Column 1: Reference Ra / Longitude coordinate
+# Column 2: Reference Dec / Latitude coordinate
+# Column 3: Input X coordinate
+# Column 4: Input Y coordinate
+# Column 5: Reference line number
+# Column 6: Input line number
+
+ 13:30:07.960 47:05:18.30 401.034 147.262 17 42
+ 13:29:48.600 47:07:42.50 860.002 480.061 8 44
+ 13:29:37.400 47:09:09.20 1127.791 680.033 12 46
+ 13:29:55.420 47:10:05.20 698.455 811.407 14 50
+ 13:30:14.950 47:10:27.60 236.088 864.817 21 52
+ 13:29:29.730 47:12:04.10 1307.802 1085.564 16 60
+ 13:29:38.700 47:13:36.20 1093.813 1300.189 13 63
+
+
+... Compute the plate solution.
+cl> ccmap m51b.mat.3 ccmap.db results=STDOUT xcolumn=3 ycolumn=4 lngcolumn=1 \
+latcolumn=2 refpoint=user lngref=13:29:52.8 latref=47:11:41 interactive=no
+
+Coords File: m51b.mat.3 Image:
+ Database: ccmap.db Record: m51.mat.3
+Refsystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.000 MJD: 51544.50000
+Insystem: j2000 Coordinates: equatorial FK5
+ Equinox: J2000.000 Epoch: J2000.000 MJD: 51544.50000
+Coordinate mapping status
+ XI fit ok. ETA fit ok.
+ Ra/Dec or Long/Lat fit rms: 0.342 0.121 (arcsec arcsec)
+Coordinate mapping parameters
+ Sky projection geometry: tan
+ Reference point: 13:29:52.800 47:11:41.00 (hours degrees)
+ Reference point: 760.687 1033.441 (pixels pixels)
+ X and Y scale: 0.430 0.431 (arcsec/pixel arcsec/pixel)
+ X and Y axis rotation: 180.174 359.949 (degrees degrees)
+
+ Input Coordinate Listing
+ X Y Ra Dec Ra(fit) Dec(fit) Dra Ddec
+
+ 401.0 147.3 13:30:07.96 47:05:18.3 13:30:07.97 47:05:18.4 -0.109 -0.109
+ 860.0 480.1 13:29:48.60 47:07:42.5 13:29:48.64 47:07:42.5 -0.385 -0.045
+1127.8 680.0 13:29:37.40 47:09:09.2 13:29:37.34 47:09:09.0 0.572 0.152
+ 698.5 811.4 13:29:55.42 47:10:05.2 13:29:55.43 47:10:05.2 -0.118 0.009
+ 236.1 864.8 13:30:14.95 47:10:27.6 13:30:14.92 47:10:27.5 0.290 0.116
+1307.8 1085.6 13:29:29.73 47:12:04.1 13:29:29.72 47:12:04.0 0.082 0.060
+1093.8 1300.2 13:29:38.70 47:13:36.2 13:29:38.73 47:13:36.4 -0.332 -0.184
+.fi
+
+
+
+4. Repeat example 3 but input the appropriate linear transformation via a list
+of tie points, rather than setting the transformation parameters directly.
+
+.nf
+... Display the tie points.
+cl> type refpts
+13:29:55.42 47:10:05.2 13:29:38.70 47:13:36.2 13:30:14.95 47:10:27.6
+ 698.5 811.4 1093.8 1300.2 236.1 864.8
+
+... Match the lists using the ccxymatch "tolerance" algorithm and a matching
+... tolerance of 2.0 arcseconds. Note the negative and positive signs on the
+... xmag and ymag parameters and lack of any rotation, indicating that north
+... is up and east is to the left.
+cl> ccxymatch m51b.coo.1 m51b.gsc m51b.mat.4 2.0 refpoints=refpts \
+lngcolumn=2 latcolumn=4 matching=tolerance lngref=13:29:52.80 \
+latref=47:11:42.9
+
+... Examine the matched list.
+cl> type m51b.mat.4
+
+# Input: m51b.coo.1 Reference: m51b.gsc Number of tie points: 3
+# tie point: 1 ref: 26.718 -97.698 input: 698.500 811.400
+# tie point: 2 ref: -143.629 113.354 input: 1093.800 1300.200
+# tie point: 3 ref: 225.854 -75.167 input: 236.100 864.800
+#
+# Initial linear transformation
+# xi[tie] = 327.7137 + -0.4306799 * x[tie] + -2.0406E-4 * y[tie]
+# eta[tie] = -448.0854 + 0.00103896 * x[tie] + 0.430936 * y[tie]
+# dx: 327.71 dy: -448.09 xmag: 0.431 ymag: 0.431 xrot: 179.9 yrot: 0.0
+#
+# Column definitions
+# Column 1: Reference Ra / Longitude coordinate
+# Column 2: Reference Dec / Latitude coordinate
+# Column 3: Input X coordinate
+# Column 4: Input Y coordinate
+# Column 5: Reference line number
+# Column 6: Input line number
+
+
+ 13:30:07.960 47:05:18.30 401.034 147.262 17 42
+ 13:29:48.600 47:07:42.50 860.002 480.061 8 44
+ 13:29:37.400 47:09:09.20 1127.791 680.033 12 46
+ 13:29:55.420 47:10:05.20 698.455 811.407 14 50
+ 13:30:14.950 47:10:27.60 236.088 864.817 21 52
+ 13:29:29.730 47:12:04.10 1307.802 1085.564 16 60
+ 13:29:38.700 47:13:36.20 1093.813 1300.189 13 63
+
+
+... Compute the plate solution which is identical to the solution computed
+... in example 2.
+cl> ccmap m51b.mat.4 ccmap.db results=STDOUT xcolumn=3 ycolumn=4 lngcolumn=1 \
+latcolumn=2 refpoint=user lngref=13:29:52.8 latref=47:11:41 interactive=no
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+stsdas.gasp.regions,stsdas.gasp.skymap,tables.ttools.tprint,daophot.daofind,ccmap
+.endhelp
diff --git a/pkg/images/imcoords/doc/hpctran.hlp b/pkg/images/imcoords/doc/hpctran.hlp
new file mode 100644
index 00000000..16a550c3
--- /dev/null
+++ b/pkg/images/imcoords/doc/hpctran.hlp
@@ -0,0 +1,109 @@
+.help hpctran Jul09 imcoords
+.ih
+NAME
+hpctran -- Convert between HEALPix row and spherical coordinate
+.ih
+USAGE
+hpctran lng=xxx lat=xxx
+.br
+hpctran row=xxx
+.ih
+PARAMETERS
+.ls row
+HEALPix table row (1 indexed).
+This is used as input if the direction
+is "row2ang" or is used to store the value if the direction is
+"ang2row".
+.le
+.ls lng, lat
+Spherical coordinate consisting of a longitude and latitude.
+These are used as input if the direction
+is "ang2row" or is used to store the value if the direction is
+"row2ang". The units are interpreted as selected by the \fIcunits\fR
+parameter. The type of coordinates appropriate for a particular map
+is defined by the map provider.
+.le
+.ls nside = 512
+The number of pixels per face side.
+.le
+.ls cunits = "degrees" (degrees|hourdegree|radians)
+The units of the longitude and latitude. The "hourdegree" is for
+longitude in hours and latitude in degrees.
+.le
+.ls maptype = "nest" (nest|ring)
+The map pixelization type which may be "nest" or "ring".
+.le
+.ls direction = "ang2row" (ang2row|row2ang)
+The conversion direction. "ang2row" converts a spherical coordinate
+to a map row or pixel number. "row2ang" converts a map row or pixel
+number to a spherical coordinate.
+.le
+.ih
+DESCRIPTION
+HEALPix is an acronym for Hierarchical Equal Area isoLatitude Pixelization
+of a sphere. See the reference section for a technical description of the
+pixelization and mathematics. As suggested in the name, this pixelization,
+or tiling, produces a subdivision of a spherical surface in which each
+"pixel" covers the same surface area as every other pixel. A HEALPix FITS
+"map" is a table where each row contains "pixel" data for a region on the
+sphere. It is a table because the pixels don't form a raster as in an
+image.
+
+The pixelization is defined by a resolution parameter which may be expressed
+in various ways. This task uses the number of pixels along a side of one of
+the 12 basic faces. The number of pixels/rows is 12 * nside * nside. The
+pixelization has two forms supported by this task. These are called
+"nested" and "ring".
+
+The HEALPix WCS task, \fBhpctran\fR, provides a translation between
+the table row number and a spherical coordinate. It is up to the
+creator of the table to choose the spherical coordinate system. This
+might be an equatorial, galactic, or super-galactic system. There may
+be a keyword specifying the system. This is the case with WMAP data.
+
+This task only provides the conversion. Access to the "pixel" data
+requires other tools. For binary tables the \fBtables\fR may be used.
+
+This task allows the spherical coordinates to be input and output in three
+forms, as hours and degrees (e.g. RA/DEC), as degrees (e.g. l/b), and as
+radians. On input one may use sexagesimal since IRAF automatically converts
+this to decimal. On output the values are produced in decimal form.
+
+The output is provide in two ways to provide flexibility in scripting. One
+is writing the results to the task parameters. Note that it is recommended
+that tasks which write to there parameter be "cached" with the \fBcache\fR
+command to avoid problems with background submission or multiple scripts
+running in parallel. The other output is printed to the standard output.
+Regardless of the direction of conversion the printed output is in the same
+order of row number, longitude, and latitude.
+
+.ih
+EXAMPLES
+A CMB WMAP file is obtained and one wants the temperature at a particular
+point on the sky. Note that the WMAP format is "nested" and
+coordinate system is galactic.
+
+.nf
+cl> hpctran lng=50.12 lat=-33.45
+2298092 50.12 -33.45000000000001
+cl> = hpctran.row
+2298092
+cl> tdump wmap_iqusmap_r9_5yr_K1_v3.fits col=TEMPERATURE row=2298092
+cl> tdump ("wmap_iqusmap_r9_5yr_K1_v3.fits", col="TEMPERATURE",
+>>> row=hpctran.row)
+.fi
+
+.ih
+REFERENCE
+\fIHEALPIX - a Framework for High Resolution Discretization, and Fast
+Analysis of Data Distributed on the Sphere\fR,
+by K.M. Gorski, Eric Hivon, A.J. Banday, B.D. Wandelt, F.K. Hansen, M.
+Reinecke, M. Bartelmann, 2005, ApJ 622, 759.
+.ih
+CREDIT
+Some code from the HEALPix distribution at http://healpix.jpl.nasa.gov
+was translated to SPP for use in this routine.
+.ih
+SEE ALSO
+ttools
+.endhelp
diff --git a/pkg/images/imcoords/doc/imcctran.hlp b/pkg/images/imcoords/doc/imcctran.hlp
new file mode 100644
index 00000000..760f3caf
--- /dev/null
+++ b/pkg/images/imcoords/doc/imcctran.hlp
@@ -0,0 +1,598 @@
+.help imcctran Oct00 images.imcoords
+.ih
+NAME
+imcctran -- convert between image celestial coordinate systems
+.ih
+USAGE
+imcctran image outsystem
+.ih
+PARAMETERS
+.ls image
+The list of images whose celestial coordinate systems are to be converted. The
+image celestial coordinate system must be one of the standard FITS celestial
+coordinate systems: equatorial (FK4, FK4-NO-E, FK5, ICRS, or GAPPT), ecliptic,
+galactic, or supergalactic.
+.le
+.ls outsystem
+The input and output celestial coordinate systems. The options are
+the following:
+.ls <imagename> [wcs]
+The celestial coordinate system is the world coordinate system of the image
+<imagename> and the input or output pixel coordinates may be in the
+"logical", "tv", "physical" or "world" coordinate systems. If wcs is not
+specified "logical" is assumed, unless the input coordinates are read from the
+image cursor, in which case "tv" is assumed. The image celestial coordinate
+system must be one of the valid FITS celestial coordinate systems:
+equatorial (FK4, FK4-NO-E, FK5, or GAPPT), ecliptic, galactic, or
+supergalactic.
+.le
+.ls equinox [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system if equinox is a
+Julian epoch, e.g. J2000.0 or 2000.0, or the equatorial mean place
+pre-IAU 1976 system (FK4) if equinox is a Besselian epoch, e.g. B1950.0
+or 1950.0. Julian equinoxes are prefixed by a J or j, Besselian equinoxes
+by a B or b. Equinoxes without the J / j or B / b prefix are treated as
+Besselian epochs if they are < 1984.0, Julian epochs if they are >= 1984.0.
+Epoch is the epoch of the observation and may be a Julian
+epoch, a Besselian epoch, or a Julian date. Julian epochs
+are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to the epoch type of
+equinox if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls icrs [equinox] [epoch]
+The International Celestial Reference System where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk5 [equinox] [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system where equinox is a
+Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0. Epoch
+is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls noefk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system but without the E-terms
+where equinox is a Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day. If undefined epoch defaults to equinox.
+.le
+.ls apparent epoch
+The equatorial geocentric apparent place post-IAU 1976 system where
+epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date.
+.le
+.ls ecliptic epoch
+The ecliptic coordinate system where epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch values < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day.
+.le
+.ls galactic [epoch]
+The IAU 1958 galactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+.ls supergalactic [epoch]
+The deVaucouleurs supergalactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+
+In all the above cases fields in [] are optional with the defaults as
+described. The epoch field for the fk5, icrs, galactic, and supergalactic
+coordinate systems is required only if the input coordinates are in the
+equatorial fk4, noefk4, fk5, or icrs systems and proper motions are defined.
+.le
+.ls nx = 10, ny = 10
+The dimensions of the coordinate grid used to compute the rotation angle and,
+optionally, the x and y magnification factors required to transform the input
+image celestial coordinate system to the output celestial coordinate system.
+.le
+.ls longpole = no
+If longpole = yes the zenithal projections ARC, SIN, STG, TAN, and ZEA
+will be transformed by updating the longpole and latpole parameters instead
+of rotating the CD matrix in the usual manner.
+.le
+.ls verbose = yes
+Print messages about actions taken by the task on the standard output ?
+.le
+.ls update = yes
+Update the image celestial coordinate system ?
+.le
+
+.ih
+DESCRIPTION
+
+IMCCTRAN converts the celestial coordinate system stored in the headers of the
+input images \fIimage\fR to the celestial coordinate system specified by
+\fIoutsystem\fR, and updates the input image header appropriately. The input
+and output celestial coordinate systems must be one of the following:
+equatorial, ecliptic, galactic, or supergalactic. The equatorial coordinate
+systems must be one of: 1) FK4, the mean place pre-IAU 1976 system, 2) FK4-NO-E,
+the same as FK4 but without the E-terms, 3) FK5, the mean place post-IAU 1976
+system, 4), ICRS, the International Celestial Reference System, 5) GAPPT,
+the geocentric apparent place in the post-IAU 1976 system.
+
+The input celestial coordinate system is read from the input image header.
+IMCCTRAN assumes that the celestial coordinate system is specified by the FITS
+keywords CTYPE, CRPIX, CRVAL, CD (or alternatively CDELT / CROTA), RADECSYS,
+EQUINOX (or EPOCH), MJD-WCS (or MJD-OBS, or DATE-OBS). USERS SHOULD TAKE NOTE
+THAT MJD-WCS IS CURRENTLY NEITHER A STANDARD OR A PROPOSED FITS STANDARD
+KEYWORD. HOWEVER IT OR SOMETHING SIMILAR, IS REQUIRED TO SPECIFY THE EPOCH OF
+THE COORDINATE SYSTEM WHICH MAY BE DIFFERENT FROM THE EPOCH OF THE OBSERVATION.
+
+The first four characters of the values of the ra / longitude and dec / latitude
+axis CTYPE keywords specify the celestial coordinate system. The currently
+permitted values of CTYPE[1:4] are RA-- / DEC- for equatorial coordinate
+systems, ELON / ELAT for the ecliptic coordinate system, GLON / GLAT for the
+galactic coordinate system, and SLON / SLAT for the supergalactic coordinate
+system.
+
+The second four characters of the values of the ra / longitude and dec /
+latitude axis CTYPE keywords specify the sky projection geometry. IRAF
+currently supports the AIT, ARC, CAR, CSC, GLS, MER, PAR, PCO, QSC,
+SIN, STG, TAN, TSC, and ZEA geometries as well as two internal projection
+geometries TNX, and ZPX. Consequently the currently permitted values of
+CTYPE[5:8] are -AIT, -ARC, -CAR, -CSC, -GLS, -MER, -PAR, -PCO, -QSC,
+-SIN, -STG, -TAN, -TSC, -ZEA as well as -ZPX and -TNX.
+
+If the input image celestial coordinate system is equatorial, the value of the
+RADECSYS keyword specifies which fundamental equatorial system is to be
+considered. The permitted values of RADECSYS are FK4, FK4-NO-E, FK5, ICRS,
+and GAPPT. If the RADECSYS keyword is not present in the image header, the
+values of the EQUINOX / EPOCH keywords (in that order of precedence) are used
+to determine the fundamental equatorial coordinate system. EQUINOX or EPOCH
+contain the epoch of the mean place and equinox for the FK4, FK4-NO-E, FK5,
+and ICRS systems (e.g 1950.0 or 2000.0). The default equatorial system is
+FK4 if EQUINOX or EPOCH < 1984.0, FK5 if EQUINOX or EPOCH >= 1984.0, and FK5
+if RADECSYS, EQUINOX, and EPOCH are undefined. If RADECSYS is defined but
+EQUINOX and EPOCH are not, the equinox defaults to 1950.0 for the FK4 and
+FK4-NO-E systems, and 2000.0 for the FK5 and ICRS systems. The equinox value is
+interpreted as a Besselian epoch for the FK4 and FK4-NO-E systems, and as a
+Julian epoch for the FK5 and ICRS systems. Users are
+strongly urged to use the EQUINOX keyword in preference to the EPOCH keyword,
+if they must enter their own equinox values into the image header. The FK4 and
+FK4-NO-E systems are not inertial and therefore also require the epoch of the
+observation (the time when the mean place was correct), in addition to the
+equinox. The epoch is specified, in order of precedence, by the values of the
+keywords MJD-WCS or MJD-OBS (which contain the modified Julian date, JD -
+2400000.5, of the coordinate system), or the DATE-OBS keyword (which contains
+the date of the observation in the form DD/MM/YY, CCYY-MM-DD, or
+CCYY-MM-DDTHH:MM:SS.S). As the latter quantity may
+only be accurate to a day, the MJD-WCS or MJD-OBS specification is preferred.
+If all 3 keywords are absent the epoch defaults to the value of equinox.
+Equatorial coordinates in the GAPPT system require only the specification
+of the epoch of observation which is supplied via the MJD-WCS, MJD-OBS,
+or DATE-OBS keywords (in that order of precedence) as for the FK4 and
+FK4-NO-E system.
+
+If the input image celestial coordinate system is ecliptic the mean ecliptic
+and equinox of date are required. These are supplied via the MJD-WCS, MJD-OBS,
+or DATE-OBS keywords (in that order or precedence) as for the equatorial FK4,
+FK4-NO-E, and GAPPT systems.
+
+The output coordinate system is specified by the \fIoutsystem\fR parameter
+as described in the PARAMETERS section.
+
+If an error is encountered when decoding the input or output world coordinate
+systems, an error message is printed on the standard output (if \fIverbose\fR
+is "yes"), and the input image left unmodified.
+
+If the input projection is one of the zenithal projections TAN, SIN, STG,
+ARC, or ZEA, then the header coordinate transformation can be preformed by
+transforming the CRVAL parameters and rotating the CD matrix as described in
+detail below. Otherwise the CRVAL values are transformed, the CD matrix is
+left unmodified, and the LONGPOLE and LATPOLE parameters required to perform
+the rotation are computed. If \fIlongpole\fR is yes then the zenithal
+coordinate systems will also be transformed using LONGPOLE and LATPOLE. At
+present IRAF looks for longpole and latpole parameters in the appropriate
+WATN_* keywords. If these are undefined the appropriate default values for
+each projection are assumed and new values are written to the WATN_* keywords.
+
+The new image celestial coordinate system is computed as follows. First a
+grid of \fInx\fR by \fIny\fR pixel and celestial coordinates, evenly spaced
+over the input image, is generated using the input image celestial coordinate
+system. Next these input celestial coordinates are transformed to coordinates
+in the output celestial coordinate system. Next the input celestial coordinates
+of the reference point (stored in degrees in the input image CRVAL keywords)
+are transformed to coordinates in the output celestial coordinate system,
+and new x and y pixel coordinates are computed using the transformed reference
+point coordinates but the original input CD matrix. The differences
+between the predicted and initial x and y pixel coordinates are used to
+compute the x and y axis rotation angles and the x and y magnification factors
+required to transform the original CD matrix to the correct new CD matrix.
+The process is shown schematically below.
+
+.nf
+1. x,y(input grid) -> ra,dec(input grid)
+
+2. ra,dec(input grid) -> ra,dec(output grid)
+
+3. ra_ref,dec_ref(input) -> ra_ref,dec_ref(output)
+
+4. ra,dec(output grid) -> x,y(predicted grid)
+
+5. x,y(input grid) -> F -> x,y(predicted grid)
+
+6. cd matrix(input) -> F -> cd matrix(output)
+.fi
+
+F is the fitted function of the x and y axis rotation angles and the
+x and y scaling factors required to match the input x and y values to the
+predicted x and y values.
+
+For most celestial coordinate transformations the fitted x and y scale factors
+will be very close to 1.0 and the x and y rotation angles will be almost
+identical. However small deviations from unity scale factors and identical
+x and y axis rotation angles do occur when transforming coordinates systems
+with the skewed axes.
+
+The precision of the transformations is usually very high, on the order
+of 10E-10 to 10E-11 in most cases. However conversions to and from the FK4
+equatorial system are less precise as these transformations
+involve the addition and subtraction of the elliptical aberration
+or E-terms. In this case the x and y scale factors correct for the first
+order E-terms and do significantly improve the precision of the coordinate
+transformation. The quadratic terms, i.e. terms in xy, x**2, and y**2
+however are not corrected for, and their absence does diminish the precision
+of the transformation coordinate transformation. For most practical purposes
+this loss of precision is insignificant.
+
+After the fit is completed, the celestial coordinates of the reference point
+in dd:mm:ss.s in the old and new systems, the rotation angle in degrees, the x
+and y scaling factors, and an estimate of the rms error of the x and y
+coordinate transformation are printed on the standard output.
+
+If \fIupdate\fR is yes, then the image header parameters CRVAL, CD,
+CTYPE, RADECSYS, EQUINOX, EPOCH, and MJD-WCS are modified, deleted, or
+added as appropriate. The position of the reference pixel in the
+image (stored in the CRPIX keywords), and the sky projection geometry, e.g.
+TAN, SIN, ARC, ETC are unchanged.
+
+USERS NEED TO BE AWARE THAT THE IRAF IMAGE WORLD COORDINATE SYSTEM
+CURRENTLY (IRAF VERSIONS 2.10.4 PATCH 2 AND EARLIER) SUPPORTS ONLY THE
+EQUATORIAL SYSTEM (CTYPE (ra axis) = "RA--XXXX" CTYPE (dec axis) = "DEC-XXXX")
+WHERE XXXX IS THE PROJECTION TYPE, EVEN THOUGH THE IMCCTRAN TASK
+SUPPORTS GALACTIC, ECLIPTIC, AND SUPERGALACTIC COORDINATES. IMCCTRAN will
+update the image correctly for non-equatorial systems, but IRAF will
+not be able to read these transformed image coordinate systems correctly.
+
+USERS SHOULD ALSO REALIZE THAT IMAGE WORLD COORDINATE SYSTEM REPRESENTATION
+IN FITS IS STILL IN THE DRAFT STAGE. ALTHOUGH IMCCTRAN TRIES TO CONFORM TO
+THE CURRENT DRAFT PROPOSAL AS MUCH AS POSSIBLE, WHERE NO ADOPTED STANDARDS
+CURRENTLY EXIST, THE FINAL FITS STANDARD MAY DIFFER FROM THE ONE ADOPTED HERE.
+
+.ih
+REFERENCES
+
+Additional information on the IRAF world coordinate systems can be found in
+the help pages for the WCSEDIT and WCRESET tasks.
+Detailed documentation for the IRAF world coordinate system interface MWCS
+can be found in the file "iraf$sys/mwcs/MWCS.hlp". This file can be
+formatted and printed with the command "help iraf$sys/mwcs/MWCS.hlp fi+ |
+lprint".
+
+Details of the FITS header world coordinate system interface can
+be found in the draft paper "World Coordinate Systems Representations Within the
+FITS Format" by Hanisch and Wells, available from the iraf anonymous ftp
+archive and the draft paper which supersedes it "Representations of Celestial
+Coordinates in FITS" by Greisen and Calabretta available from the NRAO
+anonymous ftp archives.
+
+The spherical astronomy routines employed here are derived from the Starlink
+SLALIB library provided courtesy of Patrick Wallace. These routines
+are very well documented internally with extensive references provided
+where appropriate. Interested users are encouraged to examine the routines
+for this information. Type "help slalib" to get a listing of the SLALIB
+routines, "help slalib opt=sys" to get a concise summary of the library,
+and "help <routine>" to get a description of each routine's calling sequence,
+required input and output, etc. An overview of the library can be found in the
+paper "SLALIB - A Library of Subprograms", Starlink User Note 67.7
+by P.T. Wallace, available from the Starlink archives.
+
+.ih
+EXAMPLES
+
+[1]. Precess the equatorial FK5 J2000 celestial coordinate system of the
+input 512 by 512 pixel square input image to J1975.0.
+
+.nf
+cl> imcctran image j1975.0
+
+INPUT IMAGE: image
+Insystem: image logical Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK5 Equinox: J2000.000
+ Epoch: J1987.25667351 MJD: 46890.00000
+Outsystem: j1975 Coordinates: equatorial FK5
+ Equinox: J1975.000 Epoch: J1975.00000000 MJD: 42413.25000
+Crval1,2: 201:56:43.5, 47:27:16.0 -> 201:40:53.8, 47:35:01.2 dd:mm:ss.s
+ Scaling: Xmag: 1.000000 Ymag: 1.000000 Xrot: 359.923 Yrot: 359.923 degrees
+ Rms: X fit: 8.465123E-11 pixels Y fit: 5.204446E-11 pixels
+.fi
+
+Before the transformation the image coordinate system looked like the following.
+
+.nf
+ ...
+ EPOCH = 2000
+ DATE-OBS= '05/04/87'
+ CRPIX1 = 257.75
+ CRPIX2 = 258.93
+ CRVAL1 = 201.94541667302
+ CRVAL2 = 47.45444
+ CDELT1 = -2.1277777E-4
+ CDELT2 = 2.1277777E-4
+ CTYPE1 = 'RA---TAN'
+ CTYPE2 = 'DEC--TAN'
+ ...
+.fi
+
+After the transformation the header looks like the following.
+
+.nf
+ ...
+ DATE-OBS= '05/04/87'
+ CRPIX1 = 257.75
+ CRPIX2 = 258.93
+ CRVAL1 = 201.681616387759
+ CRVAL2 = 47.583668865029
+ CTYPE1 = 'RA---TAN'
+ CTYPE2 = 'DEC--TAN'
+ RADECSYS= 'FK5 '
+ EQUINOX = 1975.
+ MJD-WCS = 42413.25
+ WCSDIM = 2
+ CD1_1 = -2.1277757990523E-4
+ CD1_2 = 2.84421945372844E-7
+ CD2_1 = 2.84421945363011E-7
+ CD2_2 = 2.12777579905235E-4
+ LTM1_1 = 1.
+ LTM2_2 = 1.
+ WAT0_001= 'system=image'
+ WAT1_001= 'wtype=tan axtype=ra'
+ WAT2_001= 'wtype=tan axtype=dec'
+ ...
+.fi
+
+Note the rms of the x and y fits is on the order 10.0e-10 to 10.0e-11 which
+is the expected numerical precision of the transformation.
+
+
+[2]. Convert the input image used in example 1 to the BFK4 1950.0 system.
+
+.nf
+cl> imcctran image B1950.0
+
+INPUT IMAGE: image
+Insystem: image logical Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK5 Equinox: J2000.000
+ Epoch: J1987.25667351 MJD: 46890.00000
+Outsystem: B1950 Coordinates: equatorial FK4
+ Equinox: B1950.000 Epoch: B1950.00000000 MJD: 33281.92346
+Crval1,2: 201:56:43.5, 47:27:16.0 -> 201:25:02.3, 47:42:47.1 dd:mm:ss.s
+ Scaling: Xmag: 0.999999 Ymag: 0.999999 Xrot: 359.848 Yrot: 359.848 degrees
+ Rms: X fit: 1.302837E-7 pixels Y fit: 8.545616E-8 pixels
+
+.fi
+
+Note that precision of the transformation is still good but is significantly
+less that the precision of the previous example. This is due to the fact
+that the quadratic terms in the E-term computation are not included in the
+transformation.
+
+The transformed image header in this case looks like the following.
+
+.nf
+ ...
+ DATE-OBS= '05/04/87'
+ CRPIX1 = 257.75
+ CRPIX2 = 258.93
+ CRVAL1 = 201.417300629944
+ CRVAL2 = 47.7130749603847
+ CTYPE1 = 'RA---TAN'
+ CTYPE2 = 'DEC--TAN'
+ RADECSYS= 'FK4 '
+ EQUINOX = 1950.
+ MJD-WCS = 33281.92345905
+ WCSDIM = 2
+ CD1_1 = -2.1277680505752E-4
+ CD1_2 = 5.66226465943254E-7
+ CD2_1 = 5.66226470798410E-7
+ CD2_2 = 2.12776805056766E-4
+ LTM1_1 = 1.
+ LTM2_2 = 1.
+ WAT0_001= 'system=image'
+ WAT1_001= 'wtype=tan axtype=ra'
+ WAT2_001= 'wtype=tan axtype=dec'
+ ...
+.fi
+
+
+[3]. Transform the celestial coordinate system of the input image used in
+examples 1 and 2 to the galactic coordinate system.
+
+.nf
+cl> imcctran image galactic
+
+INPUT IMAGE: image
+Insystem: image logical Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK5 Equinox: J2000.000
+ Epoch: J1987.25667351 MJD: 46890.00000
+Outsystem: galactic Coordinates: galactic
+ MJD: 33281.92346 Epoch: J1949.99979044 B1950.00000000
+rval1,2: 201:56:43.5, 47:27:16.0 -> 106:01:19.4, 68:27:46.1 dd:mm:ss.s
+ Scaling: Xmag: 1.000000 Ymag: 1.000000 Xrot: 202.510 Yrot: 202.510 degrees
+ Rms: X fit: 9.087450E-11 pixels Y fit: 3.815443E-11 pixels
+.fi
+
+The transformed header looks like the following.
+
+.nf
+ ...
+ DATE-OBS= '05/04/87'
+ CRPIX1 = 257.75
+ CRPIX2 = 258.93
+ CRVAL1 = 106.022047915293
+ CRVAL2 = 68.4627934475432
+ CTYPE1 = 'GLON-TAN'
+ CTYPE2 = 'GLAT-TAN'
+ MJD-WCS = 33281.92345905
+ WCSDIM = 2
+ CD1_1 = 1.96567112095654E-4
+ CD1_2 = 8.14601120181094E-5
+ CD2_1 = 8.14601120174619E-5
+ CD2_2 = -1.9656711209802E-4
+ LTM1_1 = 1.
+ LTM2_2 = 1.
+ WAT0_001= 'system=image'
+ WAT1_001= 'wtype=tan axtype=glon'
+ WAT2_001= 'wtype=tan axtype=glat'
+ ...
+.fi
+
+Users should not that although imcctran can write a legal galactic coordinate
+system to the image header, it and other iraf tasks cannot currently
+read this coordinate system.
+
+[4]. Repeat the previous example but don't update the image header.
+
+.nf
+cl> imcctran image galactic update-
+
+INPUT IMAGE: image
+Insystem: image logical Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK5 Equinox: J2000.000
+ Epoch: J1987.25667351 MJD: 46890.00000
+Outsystem: galactic Coordinates: galactic
+ MJD: 33281.92346 Epoch: J1949.99979044 B1950.00000000
+
+Current wcs
+ Axis 1 2
+ Crval 201.9454 47.4544
+ Crpix 257.75 258.93
+ Cd 1 -2.128E-4 0.
+ Cd 2 0. 2.128E-4
+
+New wcs
+ Axis 1 2
+ Crval 106.0220 68.4628
+ Crpix 257.75 258.93
+ Cd 1 1.966E-4 8.146E-5
+ Cd 2 8.146E-5 -1.966E-4
+
+Crval1,2: 201:56:43.5, 47:27:16.0 -> 106:01:19.4, 68:27:46.1 dd:mm:ss.s
+ Scaling: Xmag: 1.000000 Ymag: 1.000000 Xrot: 202.510 Yrot: 202.510 degrees
+ Rms: X fit: 9.087450E-11 pixels Y fit: 3.815443E-11 pixels
+.fi
+
+[5]. Repeat example 1 and check the accuracy of the results by using the
+skyctran task on the original image and on the transformed image.
+
+.nf
+cl> type coords
+ 1.0 1.0
+512.0 1.0
+512.0 512.0
+ 1.0 512.0
+
+cl> skyctran coords STDOUT "image logical" J1975.0
+
+Insystem: image logical Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK5 Equinox: J2000.000
+ Epoch: J1987.25667351 MJD: 46890.00000
+Outsystem: j1975 Coordinates: equatorial FK5
+ Equinox: J1975.000 Epoch: J1975.00000000 MJD: 42413.25000
+
+Input file: coords Output file: STDOUT
+
+ 1.0 1.0 13:27:02.9797 47:31:43.269
+512.0 1.0 13:26:24.3330 47:31:43.793
+512.0 512.0 13:26:24.3448 47:38:15.219
+ 1.0 512.0 13:27:03.0718 47:38:14.693
+
+cl> imcctran image j1975.0
+
+cl> skyctran coords STDOUT "image logical" "image world"
+
+Insystem: image logical Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK5 Equinox: J1975.000
+ Epoch: J1975.00000000 MJD: 42413.25000
+Outsystem: image world Projection: TAN Ra/Dec axes: 1/2
+ Coordinates: equatorial FK5 Equinox: J1975.000
+ Epoch: J1975.00000000 MJD: 42413.25000
+
+Input file: coords Output file: STDOUT
+
+ 1.0 1.0 13:27:02.9797 47:31:43.269
+512.0 1.0 13:26:24.3330 47:31:43.793
+512.0 512.0 13:26:24.3448 47:38:15.219
+ 1.0 512.0 13:27:03.0718 47:38:14.693
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+At present IRAF requires that the LONGPOLE and or LATPOLE keywords be
+defined in the appropriate WAT_* keywords, e.g. WAT1_* and WAT2_* for
+a 2D image. If these are not present then default values are assumed.
+The new values are computed and added to the WAT1_* and WAT2_* keywords.
+
+At present the experimental TNX and ZPX projections cannot be transformed
+with precision. Users should use the SKYCTRAN task to transform individual
+coordinate pairs.
+
+.ih
+SEE ALSO
+setjd,precess,galactic,xray.xspatial.skypix,stsdas.toolbox.tools.tprecess
+.endhelp
diff --git a/pkg/images/imcoords/doc/mkcwcs.hlp b/pkg/images/imcoords/doc/mkcwcs.hlp
new file mode 100644
index 00000000..542e4ff9
--- /dev/null
+++ b/pkg/images/imcoords/doc/mkcwcs.hlp
@@ -0,0 +1,93 @@
+.help mkcwcs Jun05 images.imcoords
+.ih
+NAME
+mkcwcs -- make or update a simple celestial wcs
+.ih
+USAGE
+mkcwcs wcsname
+.ih
+PARAMETERS
+.ls wcsname
+Image to be created or modified. If a new (non-existent) image is specified
+then a data-less image (NDIM=0) is created.
+.le
+.ls wcsref = ""
+Image whose WCS is first inherited and then updated.
+.le
+
+.ls equinox = INDEF
+Equinox of the coordinates specified in decimal years. If INDEF then the
+current value is not modified.
+.le
+.ls ra = INDEF
+Right ascension in hours. This may be typed in standard sexagesimal
+notation though it will be converted to decimal hours in EPARAM and
+to decimal degrees in the WCS as required by the standard. If INDEF
+then the current value is not modified.
+.le
+.ls dec = INDEF
+Declination in degrees. This may be typed in standard sexagesimal
+notation though it will be converted to decimal degrees in EPARAM.
+If INDEF then the current value is not modified.
+.le
+.ls scale = INDEF, pa = 0., lefthanded = yes
+Celestial pixel scale in arc seconds per pixel, the position angle in
+degrees, and the handedness of the axes. These are all represented by
+the WCS rotation matrix. If the scale is INDEF the current
+rotation matrix is unchanged and the position angle is ignored. If the
+scale is not INDEF then orthogonal axes are defined with the same scale on
+both axes. The handedness of the axes are specified by the
+\fIlefthanded\fR parameter. The position angle is measured from north
+increasing with the image lines (up in a standard display) and rotated
+towards east. Note that if the axes are lefthanded the angle is
+counterclockwise and if not it is clockwise.
+.le
+.ls projection = "tan" (tan|sin|linear)
+WCS projection function which may be "tan", "sin", or "linear".
+.le
+.ls rapix = INDEF, decpix = INDEF
+The reference pixel for the right ascension (first image axis) and for
+the declination (second image axes). The reference pixel may be fractional
+and lie outside the size of the image as allowed by the standard.
+.le
+.ih
+DESCRIPTION
+MKCWCS creates or modifies a celestial (RA/DEC) WCS in an image header. If a
+new image is specified the WCS is created in a data-less image header. A
+data-less WCS may be used in various tasks as a template. If a reference
+WCS is specified it is copied in whole and then desired elements of the WCS
+are modified. If a new WCS is created without a reference the initial values
+are for the pixel coordinates.
+
+The elements of the WCS which may be set are the coordinate equinox,
+the right ascension and declination, the pixel scale, the axes orientation,
+and the reference pixel in the image which corresponds to the specified
+right ascension and declination. If values are specified they WCS elements
+are left unchanged.
+
+The WCS is simple and not completely general because it defines the first
+coordinate axis to be right ascension and the second to be declination and
+that the axes are orthogonal with a uniform pixel scale (apart from the
+projection function).
+.ih
+EXAMPLES
+1. Create a data-less header by specifying a new wcs name.
+
+.nf
+ cl> mkcwcs new ra=1:20:23.1 dec=-12:11:13 scale=0.25
+.fi
+
+The reference pixel will be (0,0). To apply it later to an actual
+image (say with WCSCOPY) would require assigning the reference pixel.
+Note the use of sexagesimal notation.
+
+2. Modify the WCS of an existing image by changing the reference value
+and pixel.
+
+.nf
+ cl> mkcwcs old ra=1:20:23.1 dec=-12:11:13 rapix=1234 decpix=345
+.fi
+.ih
+SEE ALSO
+wcsedit,wcscopy,mkcwwcs
+.endhelp
diff --git a/pkg/images/imcoords/doc/mkcwwcs.hlp b/pkg/images/imcoords/doc/mkcwwcs.hlp
new file mode 100644
index 00000000..7140aa8c
--- /dev/null
+++ b/pkg/images/imcoords/doc/mkcwwcs.hlp
@@ -0,0 +1,110 @@
+.help mkcwwcs Jun05 images.imcoords
+.ih
+NAME
+mkcwwcs -- make or update a simple celestial/wavelength wcs
+.ih
+USAGE
+mkcwwcs wcsname
+.ih
+PARAMETERS
+.ls wcsname
+Image to be created or modified. If a new (non-existent) image is specified
+then a data-less image (NDIM=0) is created.
+.le
+.ls wcsref = ""
+Image whose WCS is first inherited and then updated.
+.le
+
+.ls equinox = INDEF
+Equinox of the coordinates specified in decimal years. If INDEF then the
+current value is not modified.
+.le
+.ls ra = INDEF
+Right ascension in hours. This may be typed in standard sexagesimal
+notation though it will be converted to decimal hours in EPARAM and
+to decimal degrees in the WCS as required by the standard. If INDEF
+then the current value is not modified.
+.le
+.ls dec = INDEF
+Declination in degrees. This may be typed in standard sexagesimal
+notation though it will be converted to decimal degrees in EPARAM.
+If INDEF then the current value is not modified.
+.le
+.ls scale = INDEF, pa = 0., lefthanded = yes
+Celestial pixel scale in arc seconds per pixel, the position angle in
+degrees, and the handedness of the axes. These are all represented by
+the WCS rotation matrix. If the scale is INDEF the current
+rotation matrix is unchanged and the position angle is ignored. If the
+scale is not INDEF then orthogonal axes are defined with the same scale on
+both axes. The handedness of the axes are specified by the
+\fIlefthanded\fR parameter. The position angle is measured from north
+increasing with the image lines (up in a standard display) and rotated
+towards east. Note that if the axes are lefthanded the angle is
+counterclockwise and if not it is clockwise.
+.le
+.ls projection = "tan" (tan|sin|linear)
+WCS projection function for the celestial axes which may be
+"tan", "sin", or "linear".
+.le
+
+.ls wave = INDEF
+Reference wavelength in arbitrary units. If INDEF then the current
+value is not modified.
+.le
+.ls wscale = INDEF
+Wavelength scale in arbitrary units per pixel. If INDEF then the current
+value is not modified.
+.le
+
+.ls rapix = INDEF, decpix = INDEF, wpix = INDEF
+The reference pixel for the right ascension (first image axis), for
+the declination (second image axes), and for the wavelength
+(third axis). The reference pixel may be fractional
+and lie outside the size of the image as allowed by the standard.
+.le
+.ih
+DESCRIPTION
+MKCWWCS creates or modifies a celestial (RA/DEC) plus wavelength
+three-dimensional WCS in an image header. If a
+new image is specified the WCS is created in a data-less image header. A
+data-less WCS may be used in various tasks as a template. If a reference
+WCS is specified it is copied in whole and then desired elements of the WCS
+are modified. If a new WCS is created without a reference the initial values
+are for the pixel coordinates.
+
+The elements of the WCS which may be set are the coordinate equinox,
+the right ascension and declination, the pixel scale, the axes orientation,
+the reference wavelength, the wavelength scale (i.e. dispersion),
+and the reference pixel in the image which corresponds to the specified
+right ascension and declination. If values are specified the WCS elements
+are left unchanged.
+
+The WCS is simple and not completely general because it defines the first
+coordinate axis to be right ascension, the second to be declination, and
+the third to be wavelength. The axes are orthogonal and the celestial axes
+have a uniform pixel scale (apart from the effects of the projection
+function).
+.ih
+EXAMPLES
+1. Create a data-less header by specifying a new wcs name.
+
+.nf
+ cl> mkcwwcs new ra=1:20:23.1 dec=-12:11:13 wave=5500. \
+ >>> scale=0.25 wscale=1.23
+.fi
+
+The reference pixel will be (0,0,0). To apply it later to an actual
+image (say with WCSCOPY) would require assigning the reference pixel.
+Note the use of sexagesimal notation.
+
+2. Modify the WCS of an existing image by changing the reference value
+and pixel.
+
+.nf
+ cl> mkcwwcs old ra=1:20:23.1 dec=-12:11:13 wave=5500. \
+ >>> rapix=1234 decpix=345 wpix=1024
+.fi
+.ih
+SEE ALSO
+wcsedit,wcscopy,mkcwcs
+.endhelp
diff --git a/pkg/images/imcoords/doc/skyctran.hlp b/pkg/images/imcoords/doc/skyctran.hlp
new file mode 100644
index 00000000..d91dd983
--- /dev/null
+++ b/pkg/images/imcoords/doc/skyctran.hlp
@@ -0,0 +1,861 @@
+.help skyctran Jun99 images.imcoords
+.ih
+NAME
+skyctran -- convert astronomical coordinates from one system to another
+.ih
+USAGE
+skyctran input output insystem outsystem
+.ih
+PARAMETERS
+.ls input
+The source of the input coordinates. The options are:
+.ls <filename>
+The list of input coordinate files. Coordinates may be entered by hand by
+setting input to "STDIN". A STDIN coordinate list is terminated by typing
+q or <EOF> (usually <ctrl/d> or <ctrl/z>).
+.le
+.ls imcursor
+If the input file name is equal to the reserved keyword "imcursor" the input
+coordinates are read from the image cursor and the input coordinate system
+is the coordinate system of the image specified by the insystem parameter.
+The coordinate list is terminated by typing q or <EOF> (usually <ctrl/d> or
+<ctr/z>).
+.le
+.ls grid
+If the input file name is equal to the reserved
+keyword "grid", an \fInilng\fR by \fInilat\fR grid of equally spaced
+input coordinates
+is generating spanning the region defined by \fIilngmin\fR, \fIilngmax\fR,
+\fIilatmin\fR, \fIilatmax\fR.
+.le
+.le
+.ls output
+The list of output coordinate files. The number of output files must be
+equal to one or the number of input files. Results may be printed on the
+terminal by setting output to "STDOUT".
+.le
+.ls insystem, outsystem
+The input and output celestial coordinate systems. The options are
+the following:
+.ls <imagename> [wcs]
+The celestial coordinate system is the world coordinate system of the image
+<imagename> and the input or output pixel coordinates may be in the
+"logical", "tv", "physical" or "world" coordinate systems. If wcs is not
+specified "logical" is assumed, unless the input coordinates are read from the
+image cursor, in which case "tv" is assumed. The image celestial coordinate
+system must be one of the valid FITS celestial coordinate systems:
+equatorial (FK4, FK4-NO-E, FK5, ICRS, or GAPPT), ecliptic, galactic, or
+supergalactic.
+.le
+.ls icrs [equinox] [epoch]
+The International Celestial Reverence System where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls equinox [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system if equinox is a
+Julian epoch, e.g. J2000.0 or 2000.0, or the equatorial mean place
+pre-IAU 1976 system (FK4) if equinox is a Besselian epoch, e.g. B1950.0
+or 1950.0. Julian equinoxes are prefixed by a J or j, Besselian equinoxes
+by a B or b. Equinoxes without the J / j or B / b prefix are treated as
+Besselian epochs if they are < 1984.0, Julian epochs if they are >= 1984.0.
+Epoch is the epoch of the observation and may be a Julian
+epoch, a Besselian epoch, or a Julian date. Julian epochs
+are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to the epoch type of
+equinox if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk5 [equinox] [epoch]
+The equatorial mean place post-IAU 1976 (FK5) system where equinox is
+a Julian or Besselian epoch e.g. J2000.0 or B1980.0.
+Equinoxes without the J / j or B / b prefix are treated as Julian epochs.
+The default value of equinox is J2000.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls fk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system where equinox is a
+Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0. Epoch
+is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. If undefined epoch defaults to equinox.
+.le
+.ls noefk4 [equinox] [epoch]
+The equatorial mean place pre-IAU 1976 (FK4) system but without the E-terms
+where equinox is a Besselian or Julian epoch e.g. B1950.0 or J2000.0,
+and epoch is the Besselian epoch, the Julian epoch, or the Julian date of the
+observation.
+Equinoxes without the J / j or B / b prefix are treated
+as Besselian epochs. The default value of equinox is B1950.0.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day. If undefined epoch defaults to equinox.
+.le
+.ls apparent epoch
+The equatorial geocentric apparent place post-IAU 1976 system where
+epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date.
+.le
+.ls ecliptic epoch
+The ecliptic coordinate system where epoch is the epoch of observation.
+Epoch is a Besselian epoch, a Julian epoch, or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian epochs
+if the epoch values < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian day.
+.le
+.ls galactic [epoch]
+The IAU 1958 galactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+.ls supergalactic [epoch]
+The deVaucouleurs supergalactic coordinate system.
+Epoch is a Besselian epoch, a Julian epoch or a Julian date.
+Julian epochs are prefixed by a J or j, Besselian epochs by a B or b.
+Epochs without the J / j or B / b prefix default to Besselian
+epochs if the epoch value < 1984.0, Julian epochs
+if the epoch value <= 3000.0, otherwise epoch is interpreted as
+a Julian date. The default value of epoch is B1950.0.
+.le
+
+In all the above cases fields in [] are optional with the defaults as
+described. The epoch field for fk5, icrs, galactic, and supergalactic
+coordinate systems is required only if the input coordinates are in the
+equatorial fk4, noefk4, fk5, or icrs systems and proper motions are defined.
+.le
+.ls transform = no
+If transform = no the computed output coordinates are appended to the
+input line and the new extended line is written to the output file. If
+transform = yes the computed output coordinates replace
+the input coordinates in the input line and the edited line is written
+to the output file. Transform is always set to "no" if the input
+is from the unredirected standard input.
+.le
+.ls lngcolumn = 1, latcolumn = 2
+The columns in the input file containing the x/ra/longitude and
+y/dec/latitude coordinates. Lngcolumn and latcolumn are always 1 and
+2 if the input is from the unredirected standard input.
+.le
+.ls plngcolumn = INDEF, platcolumn = INDEF
+The columns in the input file containing the ra and dec proper motions
+in " / year. If plngcolumn and platcolumn are INDEF the proper motions
+are assumed to be undefined. Proper motions
+are used only if the input coordinate system is equatorial fk4, noefk4,
+fk5, or icrs. Plngcolumn and platcolumn are always 3 and 4 if the input is from
+the unredirected standard input.
+.le
+.ls pxcolumn = INDEF, rvcolumn = INDEF
+The columns in the input file containing the parallax and radial velocity in
+in " and km / sec respectively. If pxcolumn and rvcolumn are INDEF, the
+parallax and radial velocities are assumed to be 0.0 and 0.0.
+Parallaxes and radial velocities are only used if proper motions are
+defined. Pxcolumn and rvcolumn are always 5 and 6 if the input is from the
+unredirected standard input.
+.le
+.ls ilngmin = INDEF, ilngmax = INDEF, ilatmin = INDEF, ilatmax = INDEF
+The lower and upper limits of the coordinate grid if \fIinput\fR =
+"grid".
+Ilngmin and ilngmax default to 1.0, 1.0, 0.0, 0.0, 0.0 and, 2048.0, ncols, 24.0,
+360.0, and TWOPI for coordinates in units of INDEF, pixels, hours, degrees,
+and radians respectively. Ilatmin and ilatmax default to 1.0, 1.0,
+-90.0, -90.0, -HALFPI and, 2048.0, nlines, 90.0, 90.0, and HALFPI
+for units of INDEF, pixels, degrees, degrees, and radians respectively.
+.le
+.ls nilng = 10, nilat = 10
+The size of the computed coordinate grid if \fIinput\fR = "grid".
+.le
+.ls ilngunits = "", ilatunits = ""
+The units of the input ra/longitude and dec/latitude coordinates.
+The options are:
+.ls hours
+Read the sky coordinates in hours.
+.le
+.ls degrees
+Read the sky coordinates in degrees.
+.le
+.ls radians
+Read the sky coordinates in radians.
+.le
+
+If the input system is the <imagename> [logical/tv/physical]
+system, pixel units are assumed regardless of the values
+of ilngunits or ilatunits. The default ilngunits and
+ilatunits values are
+hours and degrees for the equatorial coordinate systems and degrees and
+degrees for the remaining sky coordinate systems.
+.le
+.ls ilngformat = "", ilatformat = ""
+The output format of the input x/ra/longitude and y/dec/latitude coordinates
+if \fIinput\fR = "grid".
+The options are discussed in the formats section of the help page below.
+If the input coordinate system is the <imagename> [logical/tv/physical]
+system, default formats of %10.3f and %10.3f are assumed regardless
+of the values of ilngunits and ilatunits. Otherwise default formats
+of %12.3h, %12.2h, and %13.7g are assumed for input units of "hours", "degrees",
+and "radians" respectively. For values of \fIinput\fR other than "grid"
+the output formats of the input coordinates are the same as the input
+formats.
+.le
+.ls olngunits = "", olatunits = ""
+The units of the output ra/longitude and dec/latitude coordinates.
+The options are:
+.ls hours
+Output the sky coordinates in hours.
+.le
+.ls degrees
+Output the sky coordinates in degrees.
+.le
+.ls radians
+Output the sky coordinates in radians.
+.le
+
+If the output system is the <imagename> [logical/tv/physical]
+system, pixel units are assumed regardless of the values
+of olngunits or olatunits. The default olngunits and
+olatunits values are
+hours and degrees for the equatorial coordinate systems and degrees and
+degrees for the remaining sky coordinate systems.
+.le
+.ls olngformat = "", olatformat = ""
+The format of the computed x/ra/longitude and y/dec/latitude coordinates.
+The options are discussed in the formats section of the help page below.
+If the output coordinate system is the <imagename> [logical/tv/physical]
+system, default formats of %10.3f and %10.3f are assumed regardless
+of the values of olngunits and olatunits. Otherwise default formats
+of %12.3h, %12.2h, and %13.7g are assumed for output units of "hours",
+"degrees", and "radians" respectively.
+.le
+.ls icommands = ""
+The default image display cursor.
+.le
+.ls verbose = yes
+Print messages about actions taken by the task on the standard output?
+.le
+
+.ih
+DESCRIPTION
+
+SKYCTRAN converts coordinates in the input files
+\fIinput\fR from the input celestial coordinate system \fIinsystem\fR
+to the output celestial coordinate system \fIoutsystem\fR and writes the
+converted coordinates to the output files \fIoutput\fR. The input
+files may be simple text files, the standard input "STDIN",
+the image display cursor "imcursor", or a user specified coordinate grid.
+The output files may be simple
+text files or the standard output "STDOUT". SKYCTRAN may be used
+to change the units of the input coordinates, e.g. from degrees and degrees
+to hours and degrees, to precess the coordinates, to convert from one
+celestial coordinate system to another, e.g. from equatorial to ecliptic
+coordinates and vice versa, and to locate common objects in
+images whose fundamental coordinate systems are the same but observed at
+different epochs, e.g. FK4 B1950.0 and FK4 B1975.0, or different, e.g.
+equatorial FK4 B1950.0 and galactic.
+
+The input data are read from columns \fIlngcolumn\fR, \fIlatcolumn\fR,
+\fIplngcolumn\fR, \fIplatcolumn\fR, \fIpxcolumn\fR, and \fIrvcolumn\fR
+in the input files and if \fItransform\fR = yes, the converted coordinates are
+written to the same columns in the output files. If \fItransform\fR = "no",
+the converted coordinates are appended to the input line creating two
+additional columns in the output file. If the input file is the
+unredirected standard input then transpose is always "no". Comment lines, blanks
+lines, and lines for which the input coordinates could not be successfully
+decoded are passed on to the output file without modification.
+
+The input and output celestial coordinate systems \fIinsystem\fR and
+\fIoutsystem\fR must be one of the following: equatorial, ecliptic, galactic, or
+supergalactic. The equatorial systems must be one of: 1) FK4, the mean
+place pre-IAU 1976 system, 2) FK4-NO-E, the same as FK4 but without the
+E-terms, 3) FK5, the mean place post-IAU 1976 system, 4) ICRS,
+the International Celestial Reference System, 5) GAPPT, the geocentric
+apparent place in the post-IAU 1976 system.
+
+If \fIinsystem\fR or \fIoutsystem\fR is an image name then the celestial
+coordinate system is read from the image header. SKYCTRAN assumes that
+the celestial coordinate system is represented in the image header by
+the FITS keywords CTYPE, CRPIX, CRVAL, CD (or alternatively CDELT / CROTA),
+RADECSYS, EQUINOX (or EPOCH), and MJD-WCS (or MJD_OBS or DATE-OBS). USERS
+SHOULD TAKE NOTE THAT MJD-WCS IS CURRENTLY NEITHER A STANDARD OR
+PROPOSED FUTS STANDARD KEYWORD. HOWEVER IT OR SOMETHING SIMILAR IS REQUIRED
+TO SPECIFY THE EPOCH OF THE COORDINATE SYSTEM WHICH MAY BE DIFFERENT
+FROM THE EPOCH OF THE OBSERVATION.
+
+The first four characters of the values of the ra/longitude and dec/latitude
+axis CTYPE keywords specify the celestial coordinate system.
+The permitted CTYPE values are RA--/DEC- for equatorial coordinate systems,
+ELON/ELAT for the ecliptic coordinate system, GLON/GLAT for the galactic
+coordinate system, and SLON/SLAT for the supergalactic coordinate system,
+
+If the image celestial coordinate system is equatorial, the value
+of the RADECSYS keyword specifies the fundamental equatorial system.
+The permitted values of RADECSYS are FK4, FK4-NO-E,
+FK5, ICRS, and GAPPT. If the RADECSYS keyword is not
+present in the image header, the values of the EQUINOX or EPOCH keywords
+in that order of precedence are used to determine the fundamental
+equatorial system. EQUINOX or EPOCH contain the
+epoch of the mean place and equinox for the FK4, FK4-NO-E, FK5, and ICRS
+systems, e.g 1950.0 or 2000.0. The default equatorial system is FK4 if
+EQUINOX or EPOCH < 1984.0, FK5 if EQUINOX or EPOCH >= 1984.0, and FK5 if
+RADECSYS, EQUINOX and EPOCH are undefined.
+If RADECSYS is defined but EQUINOX and EPOCH are not the equinox
+defaults to 1950.0 for the FK4 and FK4-NO-E systems and 2000.0 for the FK5
+and ICRS systems.
+The equinox value is interpreted as a Besselian epoch for the FK4 and
+FK4-NO-E systems and as a Julian epoch for the FK5 and ICRS systems. Users are
+strongly urged to use the EQUINOX keyword in preference to the EPOCH
+keyword if they must enter their own values of the equinox into
+the image header. The FK4 and
+FK4-NO-E systems are not inertial and therefore also require the epoch of the
+observation (the time when the mean place was correct) in addition to the
+equinox. The input coordinate system epoch of the observation is also required
+if the input coordinate system is FK4, FK4-NO-E, FK5, or ICRS and proper motions
+are supplied.
+The epoch is specified, in order of precedence, by the values of
+the keywords MJD-WCS or MJD-OBS containing the modified Julian date
+(JD - 2400000.5) of
+the coordinate system, or the DATE-OBS keyword containing
+the date of the observation in the form DD/MM/YY, CCYY-MM-DD, or
+CCYY-MM-DDTHH:MM:SS.S. As the latter quantity may
+only be accurate to a day, the MJD-WCS or MJD-OBS specifications are
+preferable. If both
+keywords are absent the epoch defaults to the value of equinox.
+Equatorial coordinates in the GAPPT system require
+only the specification of the epoch of observation which is supplied
+via the MJD-WCS, MJD-OBS or DATE-OBS keywords as for the FK4, FK4-NO-E, FK5,
+and ICRS systems.
+
+If the celestial coordinate system is ecliptic the mean ecliptic and equinox of
+date are required. They are supplied via the MJD-WCS, MJD-OBS or DATE-OBS
+keywords as for the equatorial FK4, FK4-NO-E, FK5, ICRS, and GAPPT systems.
+
+If, the output coordinate system is galactic or supergalactic, the input
+coordinate system is FK4, FK4-NO-E, FK5, or ICRS and proper motions are
+supplied with the input coordinates, then the output epoch of the
+observation is also required. This is supplied via the MJD-WCS, MJD-OBS or
+DATE-OBS keywords as for the equatorial FK4, FK4-NO-E, FK5, ICRS, GAPPT,
+and ecliptic systems.
+
+USERS NEED TO BE AWARE THAT THE IRAF IMAGE WORLD COORDINATE SYSTEM
+CURRENTLY (IRAF VERSIONS 2.10.4 PATCH 2 AND EARLIER) SUPPORTS ONLY THE
+EQUATORIAL SYSTEM (CTYPE (ra axis) = "RA--XXXX" CTYPE (dec axis) = "DEC-XXXX")
+WHERE XXXX IS THE PROJECTION TYPE, EVEN THOUGH THE SKYCTRAN TASK
+SUPPORTS GALACTIC, ECLIPTIC, AND SUPERGALACTIC COORDINATES.
+
+USERS SHOULD ALSO REALIZE THAT IMAGE WORLD COORDINATE SYSTEM REPRESENTATION
+IN FITS IS STILL IN THE DRAFT STAGE. ALTHOUGH SKYCTRAN TRIES TO CONFORM TO
+THE CURRENT DRAFT PROPOSAL WHERE NO ADOPTED STANDARDS CURRENTLY EXIST, THE
+FINAL FITS STANDARD MAY DIFFER FROM THE ONE ADOPTED HERE.
+
+The IRAF builtin world coordinate systems "logical", "tv", "physical", and
+world are also supported. This means for example that users can begin
+with cursor coordinates in image 1, use the image header of image 1
+to transform the pixel coordinates to the celestial coordinate system of
+image 1, convert the image 1 celestial coordinates to celestial coordinates
+in the image 2 celestial coordinate system, and finally transform the
+celestial coordinate system 2 coordinates to pixel coordinates in image 2,
+all in one step.
+
+The \fIlogical coordinate system\fR is the pixel coordinate system of the
+current image. This coordinate system is the one used by the image
+input/output routines to access the image on disk. In the
+logical coordinate system,
+the coordinates of the pixel centers must lie within the following
+range: 1.0 <= x[i] <= nx[i], where x[i] is the coordinate in dimension i,
+nx[i] is the size of the image in dimension i, and the current maximum
+number of image dimensions is 7. In the case of an image section,
+the nx[i] refer to the dimensions of the section, not the dimensions
+of the full image.
+
+The \fItv coordinate system\fR is the pixel coordinate system used by the
+display servers XIMTOOL, SAOIMAGE, and IMTOOL.
+For images which are not image sections
+the tv and logical coordinate systems are identical. For images which are
+image sections the tv and physical coordinate systems are identical if
+the image has not undergone any prior linear transformations such as
+axis flips, section copies, shifts, scale changes, rotations, etc.
+
+The \fIphysical coordinate system\fR is the coordinate system in which the
+pixel coordinates of an object are invariant to successive linear
+transformations
+of the image. In this coordinate system, the pixel coordinates of an object
+in an image remain the same, regardless of any section copies, shifts,
+rotations, etc on the image. For example, an object with the
+physical coordinates (x,y) in an image would still have physical
+coordinates (x, y) in an image which is a section of the original image.
+
+The \fIworld coordinate system\fR is the default coordinate system for the
+image. The default world coordinate system is the one named by the
+environment variable "defwcs" if defined in the user environment (initially
+it is undefined) and present in the image header; else it is the first
+world coordinate system
+defined for the image (the .imh and .hhh image format support only one wcs
+but the .qp format can support more); else it is the physical coordinate
+system.
+
+IF AN ERROR IS ENCOUNTERED WHEN DECODING THE INPUT OR OUTPUT WORLD COORDINATE
+SYSTEMS, THEN AN ERROR FLAG IS PRINTED IN THE OUTPUT FILE AND ON THE STANDARD
+OUTPUT IF \fIVERBOSE\fR IS YES, AND THE INPUT COORDINATES ARE COPIED TO THE
+OUTPUT COORDINATES WITHOUT CHANGE.
+
+\fIIlngunits\fR, \fIilatunits\fR, \fIolngunits\fR, and \fIolatunits\fR
+set the units of the input and output coordinate systems.
+If the input or output system is the <imagename> [logical/tv/physical]
+system pixel units are assumed regardless of the values
+of <i/o>lngunits or <i/o>latunits. The default <i/o>lngunits and
+<i/o>latunits values are
+hours and degrees for the equatorial celestial coordinate system and
+degrees and degrees for the remaining celestial coordinate systems.
+
+The formats of the computed x/ra/longitude and y/dec/longitude coordinates
+are specified with the \fIolngformat\fR and \fIolatformat\fR parameters.
+The options are discussed in the formats section of the help page below.
+If the output coordinate system is the <imagename> [logical/tv/physical],
+default formats of %10.3f and %10.3f are assumed regardless
+of the values of olngunits and olatunits. Otherwise default formats
+of %12.3h, %12.2h, and %g are assumed for output units of "hours", "degrees",
+and "radians" respectively.
+
+.ih
+USER COMMANDS
+
+If the input file is STDIN the user can type in the input data by hand and
+set the input and output coordinate systems, the input and output coordinate
+units, and the output coordinate format interactively. The available commands
+are listed below.
+
+.nf
+ INTERACTIVE KEYSTROKE COMMANDS
+
+The following commands must be followed by a carriage return.
+
+? Print help
+: Execute colon command
+data Measure object
+q Exit task
+
+
+ VALID DATA STRING
+
+x/ra/long y/dec/lat [pmra pmdec [parallax radial velocity]]
+
+... x/ra/long y/dec/lat must be in pixels or the input units
+... pmra and pmdec must be in " / year
+... parallax must be in "
+... radial velocity must be in km / sec
+
+ COLON COMMANDS
+
+The following commands must be followed by a carriage return.
+
+:show Show the input and output coordinate systems
+:isystem [string] Show / set the input coordinate system
+:osystem [string] Show / set the output coordinate system
+:iunits [string string] Show / set the input coordinate units
+:ounits [string string] Show / set the output coordinate units
+:oformat [string string] Show / set the output coordinate format
+
+ VALID INPUT AND OUTPUT COORDINATE SYSTEMS
+
+image [logical/tv/physical/world]
+equinox [epoch]
+noefk4 [equinox [epoch]]
+fk4 [equinox [epoch]]
+fk5 [equinox [epoch]]
+icrs [equinox [epoch]]
+apparent epoch
+ecliptic epoch
+galactic [epoch]
+supergalactic [epoch]
+
+ VALID INPUT AND OUTPUT CELESTIAL COORDINATE UNITS
+ AND THEIR DEFAULT FORMATS
+
+hours %12.3h
+degrees %12.2h
+radians %13.7h
+.fi
+
+.ih
+IMAGE CURSOR COMMANDS
+
+In interactive image cursor mode the user can set the input and output
+coordinate systems, the output coordinate units, and the output coordinate
+formats. The available commands are listed below.
+
+.nf
+ INTERACTIVE KEYSTROKE COMMANDS
+
+? Print help
+: Execute colon command
+spbar Measure object
+q Exit task
+
+
+ COLON COMMANDS
+
+:show Show the input and output coordinate systems
+:isystem [string] Show / set the input coordinate system
+:osystem [string] Show / set the output coordinate system
+:ounits [string string] Show / set the output coordinate units
+:oformat [string string] Show / set the output coordinate format
+
+ VALID INPUT COORDINATE SYSTEMS
+
+image [tv]
+
+ VALID OUTPUT COORDINATE SYSTEMS
+
+image [logical/tv/physical/world]
+equinox [epoch]
+noefk4 [equinox [epoch]]
+fk4 [equinox [epoch]]
+fk5 [equinox [epoch]]
+icrs [equinox [epoch]]
+apparent epoch
+ecliptic epoch
+galactic [epoch]
+supergalactic [epoch]
+
+ VALID OUTPUT COORDINATE UNITS AND THEIR DEFAULT FORMATS
+
+hours %12.3h
+degrees %12.2h
+radians %13.7g
+.fi
+
+
+.ih
+FORMATS
+
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+
+.ih
+REFERENCES
+
+Additional information on the IRAF world coordinate systems can be found in
+the help pages for the WCSEDIT and WCRESET tasks.
+Detailed documentation for the IRAF world coordinate system interface MWCS
+can be found in the file "iraf$sys/mwcs/MWCS.hlp". This file can be
+formatted and printed with the command "help iraf$sys/mwcs/MWCS.hlp fi+ |
+lprint".
+
+Details of the FITS header world coordinate system interface can
+be found in the draft paper "World Coordinate Systems Representations Within the
+FITS Format" by Hanisch and Wells, available from the iraf anonymous ftp
+archive and the draft paper which supersedes it "Representations of Celestial
+Coordinates in FITS" by Greisen and Calabretta available from the NRAO
+anonymous ftp archives.
+
+The spherical astronomy routines employed here are derived from the Starlink
+SLALIB library provided courtesy of Patrick Wallace. These routines
+are very well documented internally with extensive references provided
+where appropriate. Interested users are encouraged to examine the routines
+for this information. Type "help slalib" to get a listing of the SLALIB
+routines, "help slalib opt=sys" to get a concise summary of the library,
+and "help <routine>" to get a description of each routine's calling sequence,
+required input and output, etc. An overview of the library can be found in the
+paper "SLALIB - A Library of Subprograms", Starlink User Note 67.7
+by P.T. Wallace, available from the Starlink archives.
+
+.ih
+EXAMPLES
+
+1. Precess the fk4 coordinates typed in by the user to the fk5 system with
+and without the proper motion values.
+
+.nf
+ cl> skyctran STDIN STDOUT fk4 fk5
+
+ # Insystem: fk4 Coordinates: equatorial FK4
+ # Equinox: B1950.000 Epoch: B1950.00000000 MJD: 33281.92346
+ # Outsystem: fk5 Coordinates: equatorial FK5
+ # Equinox: J2000.000 Epoch: J2000.00000000 MJD: 51544.50000
+
+ # Input file: STDIN Output file: STDOUT
+
+ ... not including proper motion
+ 13:28:43.2 27:18:01.1
+ 13:28:43.2 27:18:01.1 13:31:03.855 27:02:35.13
+
+ ... including proper motion
+ 13:28:43.2 27:18:01.1 .36 -0.16
+ 13:28:43.2 27:18:01.1 .36 -0.16 13:31:05.215 27:02:27.37
+
+ ... change the output coordinate system to fk5 1975.0 and repeat
+ :os fk5 1975.0
+ :os
+
+ # Outsystem: fk5 1975.0 Coordinates: equatorial FK5
+ # Equinox: J1975.000 Epoch: J1975.00000000 MJD: 42413.25000
+
+ 13:28:43.2 27:18:01.1
+ 13:28:43.2 27:18:01.1 13:29:53.564 27:10:17.69
+
+ 13:28:43.2 27:18:01.1 .36 -0.16
+ 13:28:43.2 27:18:01.1 .36 -0.16 13:29:54.244 27:10:13.80
+
+ ... type EOF to quit
+ <EOF>
+.fi
+
+2. Precess a list of RAS in hours and DECS in degrees in the FK5 system
+equinox 1980.0 to equinox 2000.0 and write both the input coordinates and
+the output coordinates in hours and degrees to the output file.
+
+.nf
+ cl> skyctran inlist outlist j1980.0 j2000.0
+
+ ... or equivalently ...
+
+ cl> skyctran inlist outlist j1980.0 2000.0
+
+ ... or equivalently ...
+
+ cl> skyctran inlist outlist "fk5 1980.0" fk5
+.fi
+
+Note that if the coordinate system, e.g. fk5, is not specified explicitly
+then equinoxes < 1984 must be prefixed by J, or a Besselian rather than
+a Julian epoch will be assumed.
+
+3. Repeat the previous example but replace the input coordinates with
+the precessed coordinates in the output file.
+
+.nf
+ cl> skyctran inlist outlist j1980.0 j2000.0 transform+
+.fi
+
+4. Precess a list of RAS in hours and DECS in degrees in the FK4 system
+equinox 1950.0 to equinox 1975.0 and write both the input coordinates and
+the output coordinates in hours and degrees to the output file. The input
+and output epochs of observation default to the respective equinox
+values.
+
+.nf
+ cl> skyctran inlist outlist 1950.0 1975.0
+
+ ... or equivalently ...
+
+ cl> skyctran inlist outlist b1950.0 b1975.0
+
+ ... or equivalently ...
+
+ cl> skyctran inlist outlist fk4 b1975.0
+
+ ... or equivalently ...
+
+ cl> skyctran inlist outlist fk4 "fk4 1975.0"
+.fi
+
+5. Convert a list of RAS in hours and DECS in degrees in the FK4 system
+equinox 1950.0 to RAS in hours and DECS in degrees in the FK5 system
+equinox 2000.0, and replace the input coordinates with the
+output coordinates in the output file. The Besselian epoch of the
+observation is 1987.25.
+
+.nf
+ cl> skyctran inlist outlist "b1950.0 1987.25" j2000.0 \
+ transform+
+.fi
+
+6. Convert a list of RAS in hours and DECS in degrees to RAS in degrees
+and DECS in degrees, and replace the input coordinates with the output
+coordinates in the output file. As the input and output coordinate systems
+and equinoxes are the same no precession is performed.
+
+.nf
+ cl> skyctran inlist outlist 2000.0 2000.0 olngunits=degrees \
+ transform+
+.fi
+
+7. Convert a list of RAS in hours and DECS in degrees in the FK4
+system, equinox 1950.0, epoch of observation 1987.24, to galactic
+coordinates, and write both the input and output coordinate to the
+output file.
+
+.nf
+ cl> skyctran inlist outlist "b1950.0 1987.25" galactic
+.fi
+
+8. Convert a list of RAS in hours and DECS in degrees in the FK5
+system, equinox 2000.0, to ecliptic coordinates on Julian date
+2449879.5, replacing the input coordinates with the converted
+coordinates in the output file.
+
+.nf
+ cl> skyctran inlist outlist j2000 "ecliptic 2449879.5" \
+ transform+
+.fi
+
+9. Display an image and use the cursor and image header coordinate
+system, equatorial FK4, equinox 1950.0, epoch 1987.25 to print the pixel
+and galactic coordinates of the marked objects on the image display.
+Note that the test image dev$wpix has an incorrect value of EPOCH (0.0) that
+would have confused skyctran and need to be changed.
+
+.nf
+ cl> imcopy dev$wpix wpix
+ cl> hedit wpix epoch 1950.0
+ cl> display wpix 1 fi+
+ cl> skyctran imcursor STDOUT wpix galactic
+.fi
+
+10. Convert a list of RAS in hours and DECS in degrees measured in the
+image created in example 9 to the FK5 equinox 2000.0 coordinate system.
+
+.nf
+ cl> skyctran inlist outlist "wpix world" j2000.0
+
+ ... or equivalently ...
+
+ cl> skyctran inlist outlist "b1950.0 1987.25" j2000.0
+.fi
+
+11. Using an image whose header coordinate system is equatorial FK5
+equinox 2000.0 and a different image of the same region whose coordinate
+system is galactic use the image display and cursor to create a list of
+tie points in logical pixel coordinates that can be used as input to the
+registration tasks geomap and geotran. Note that this example and examples
+12 and 13 below will not work on iraf system earlier than 2.11 because galactic
+image header coordinates are not fully supported. They will work
+however on two images which have equatorial coordinates systems
+which are precessed with respect to each other.
+
+
+.nf
+ cl> display image1
+
+ ... this is the reference image
+
+ cl> skyctran imcursor outlist image1 "image2 logical"
+
+ ... mark many widely scattered points on the displayed
+ image image1 terminating the input list with
+ <EOF> which is usually <ctrl/z> or <ctrl/d>
+.fi
+
+12. Repeat example 11 but use a previously prepared list of image1
+logical pixel coordinates as input to the task.
+
+.nf
+ cl> skyctran inlist outlist "image1 logical"\
+ "image2 logical"
+.fi
+
+13. Repeat example 11 but have skyctran automatically generate a grid
+of 100 tie points.
+
+.nf
+ cl> skyctran grid outlist "image1 logical"\
+ "image2 logical"
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+setjd,precess,galactic,xray.xspatial.skypix,stsdas.toolbox.tools.tprecess
+.endhelp
diff --git a/pkg/images/imcoords/doc/starfind.hlp b/pkg/images/imcoords/doc/starfind.hlp
new file mode 100644
index 00000000..9817735e
--- /dev/null
+++ b/pkg/images/imcoords/doc/starfind.hlp
@@ -0,0 +1,304 @@
+.help starfind May97 images.imcoords
+.ih
+NAME
+starfind -- automatically detect stellar objects in a list of images
+.ih
+USAGE
+starfind image output hwhmpsf threshold
+.ih
+PARAMETERS
+.ls image
+The list of input images. The input images must be two-dimensional.
+.le
+.ls output
+The list of output object files. The number of output files must equal the
+number of input images. If output is "default", or "dir$default", or a
+directory specification then a default name of the form
+dir$root.extension.version is constructed, where dir$ is the directory name,
+root is the root image name, extension is "obj", and version is the next
+available version number.
+.le
+.ls hwhmpsf
+The half-width half-maximum of the image PSF in pixels.
+.le
+.ls threshold
+The detection threshold above local background in ADU.
+.le
+.ls datamin = INDEF, datamax = INDEF
+The minimum and maximum good data values in ADU. Datamin and datamax
+default to the constants -MAX_REAL and MAX_REAL respectively.
+.le
+.ls fradius = 2.5 (hwhmpsf)
+The fitting radius in units of hwhmpsf. Fradius defines the size
+of the Gaussian kernel used to compute the density enhancement image, and
+the size of the image region used to do the moment analysis.
+.le
+.ls sepmin = 5.0 (hwhmpsf)
+The minimum separation for detected objects in units of hwhmpsf.
+.le
+.ls npixmin = 5
+The minimum area of the detected objects in pixels.
+.le
+.ls maglo = INDEF, maghi = INDEF
+The minimum and maximum magnitudes of the detected objects. Maglo and maghi
+default to the constants -MAX_REAL and MAX_REAL respectively.
+.le
+.ls roundlo = 0.0, roundhi = 0.2
+The minimum and maximum ellipticity values of the detected objects, where
+ellipticity is defined as 1 - b / a, and a and b are the semi-major and
+semi-minor axis lengths respectively.
+.le
+.ls sharplo = 0.5, sharphi = 2.0
+The minimum and maximum sharpness values of the detected objects, where
+sharpness is defined to be the ratio of the object size to the
+hwhmpsf parameter value.
+.le
+.ls wcs = ""
+The world coordinate system. The options are:
+.ls " "
+The world coordinate system is undefined. Only logical (pixel) coordinates
+are printed.
+.le
+.ls logical
+The world coordinate system is the same as the logical (pixel) coordinate
+system, but two sets of identical logical (pixel) coordinates are printed.
+.le
+.ls physical
+The world coordinate system is the same as the logical (pixel) coordinate
+system of the parent image if any.
+.le
+.ls world
+The world coordinate system of the image if any.
+.le
+.le
+.ls wxformat = "", wyformat = ""
+The output format for the x and y axis world coordinates. If wxformat and
+wyformat are undefined then: 1) the value of the wcs format attribute is
+used if the output wcs is "world" and the attribute is defined, 2) "%9.3f"
+is used if the output wcs is "logical" or "physical", and "%11.8g" is used
+if the output wcs is "world". If the input image is a sky projection image and
+the x and y axes are ra and dec respectively, then the formats "%12.2H" and
+"%12.1h" will print the world coordinates in hours and degrees respectively.
+.le
+.ls boundary = "nearest"
+The boundary extension type. The choices are:
+.ls nearest
+Use the value of the nearest boundary pixel.
+.le
+.ls constant
+Use a constant value.
+.le
+.ls reflect
+Generate a value by reflecting around the boundary.
+.le
+.ls wrap
+Generate a value by wrapping around to the other side of the image.
+.le
+.le
+.ls constant = 0.0
+The constant for constant boundary extension.
+.le
+.ls nxblock = INDEF, nyblock = 256
+The working block size. If undefined nxblock and nyblock default
+to the number of columns and rows in the input image respectively.
+.le
+.ls verbose = no
+Print messages about the progress of the task ?
+.le
+
+.ih
+DESCRIPTION
+
+STARFIND searches the input images \fIimage\fR for local density maxima
+with half-widths at half-maxima of ~ \fIhwhmpsf\fR and peak amplitudes
+greater than ~ \fIthreshold\fR above the local background, and writes
+the list of detected objects to \fIoutput\fR.
+
+STARFIND is a modified version of the DAOPHOT package DAOFIND algorithm.
+However STARFIND is intended for use with the IMAGES package image matching
+and image coordinates tasks and is therefore configured somewhat differently
+than the version used in the photometry packages.
+
+.ih
+ALGORITHMS
+
+STARFIND assumes that the point spread function can be approximated by a radial
+Gaussian function whose sigma is 0.84932 * \fIhwhmpsf\fR pixels. STARFIND uses
+this model to construct a convolution kernel which is truncated at
+max (2.0, \fIfradius * hwhmpsf\fR) pixels and normalized to zero power.
+
+For each point in the image density enhancement values are computed by
+convolving the input image with the radial Gaussian function. This operation
+is mathematically equivalent to fitting the image data at each point, in the
+least-squares sense, with a truncated, lowered, radial Gaussian function.
+After the convolution each density enhancement value is an estimate of
+the amplitude of the best fitting radial Gaussian function at that point.
+If \fIdatamin\fR and \fIdatamax\fR are defined then bad data is ignored,
+i.e. rejected from the fit, during the computation of the density enhancement
+values. Out of bounds image pixels are evaluated using the boundary extension
+algorithm parameters \fIboundary\fR and \fIconstant\fR. Out of
+bounds density enhancement values are set to zero.
+
+After the convolution, STARFIND steps through the density enhancement
+image searching for density enhancements greater then \fIthreshold\fR
+and brighter than any density enhancements within a radius of
+\fIsepmin * hwhmpsf\fR pixels. For each potential detection the
+local background is estimated and used, along with the values of
+\fIdatamin\fR and \fIdatamax\fR, to estimate the position (Xc and Yc),
+size (Area and Hwhm), shape (E and Sharp), orientation (Pa), and
+brightness (Mag) of each object using the second order moments analysis
+shown below.
+
+.nf
+ I0 = sum (I)
+ N = sum (1.0)
+ if (N <= 0)
+ Sky = maxdata - maxden
+ else
+ Sky = I0 / N
+
+ M0 = sum (I - Sky)
+ Mx = sum (X * (I - Sky))
+ My = sum (Y * (I - Sky))
+
+ Xc = Mx / M0
+ Xc = My / M0
+ Mag = -2.5 * log10 (M0)
+ Area = N
+
+ Mxx = sum ((X - Xc) * (X - Xc) * (I - Sky))
+ Mxy = sum ((X - Xc) * (Y - Yc) * (I - Sky))
+ Myy = sum ((Y - Yc) * (Y - Yc) * (I - Sky))
+
+ Hwhm = sqrt (log (2) * (Mxx + Myy))
+ E = sqrt ((Mxx - Myy) ** 2 + 4 * Mxy ** 2) / (Mxx + Myy))
+ Pa = 0.5 * atan (2 * Mxy / (Mxx - Myy))
+Sharp = Hmhw / Hwhmpsf
+.fi
+
+The sums are computed using pixels which lie within \fIfradius * hwhmpsf\fR of
+the maximum density enhancement, and whose values are within the good data
+limits defined by \fIdatamin\fR and \fIdatamax\fR, and which are above the local
+background estimate (Sky).
+
+Objects whose magnitude, roundness, and sharpness characteristics are outside
+the values defined by \fImaglo\fR, \fImaghi\fR, \fIroundlo\fR, \fIroundhi\fR,
+\fIsharplo\fR, and \fIsharphi\fR and whose total areas is less than
+\fInpixmin\fR pixels are rejected from the list.
+
+If \fIwcs\fR parameter is defined, the world coordinates as well as
+the pixel coordinates of the detected objects are computed and printed
+using the formats defined by \fIwxformat\fR and \fIwyformat\fR.
+
+To minimize the memory requirements and increase efficiency, STARFIND
+is configured to operate on data blocks that are \fInxblock * nyblock\fR
+in size. To keep the image i/o operation to a minimum nxblock is set
+to INDEF and defaults to the number of columns in the input image.
+Setting both parameter to INDEF will force STARFIND to perform the
+whole operation in memory.
+
+.ih
+FORMATS
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+ absent, 0 use as much space as needed (D field sets precision)
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+.ih
+EXAMPLES
+
+1. Find stellar objects with peak values greater than 100 counts above
+local background in the test image dev$wpix whose fwhm is ~2.5 pixels.
+
+.nf
+cl> starfind dev$wpix default 1.25 100.
+cl> display dev$wpix 1 fi+
+cl> tvmark 1 wpix.obj.1 col=204
+.fi
+
+2. Repeat the previous example but tell starfind to compute and print
+world coordinates in hours and degrees as well as pixel coordinates.
+
+.nf
+cl> starfind dev$wpix default 1.25 100. wcs=world wxf="%12.2H"\
+ wyf="%12.1h"
+cl> display dev$wpix 1 fi+
+cl> tvmark 1 wpix.obj.1 col=204
+.fi
+
+.ih
+TIME REQUIREMENTS
+Starfind requires approximately 8 CPU seconds to search a 512 by 512
+image using a 7 by 7 pixel convolution kernel (SPARCStation2).
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+imcentroid, apphot.daofind, daophot.daofind
+.endhelp
diff --git a/pkg/images/imcoords/doc/wcsctran.hlp b/pkg/images/imcoords/doc/wcsctran.hlp
new file mode 100644
index 00000000..c8ee4316
--- /dev/null
+++ b/pkg/images/imcoords/doc/wcsctran.hlp
@@ -0,0 +1,340 @@
+.help wcsctran May95 images.imcoords
+.ih
+NAME
+wcsctran -- use the image WCS to transform between IRAF coordinate systems
+.ih
+USAGE
+wcsctran input output image inwcs outwcs
+.ih
+PARAMETERS
+.ls input
+The list of input coordinate files. The number of input coordinate
+files must be one or equal to the number of input images. Coordinates
+may be entered by hand by setting input to "STDIN".
+.le
+.ls output
+The list of output coordinate files. The number of coordinate files
+must be one or equal to the number of input images. Results may be printed
+on the terminal by setting output to "STDOUT".
+.le
+.ls image
+The list of input images containing the WCS information.
+.le
+.ls inwcs, outwcs
+The input and output coordinate systems. Coordinates in the input
+file are assumed to be in the input system. Coordinates are written to
+the output file in the output system. The options are:
+.ls logical
+Logical coordinates are pixel coordinates relative to the current
+image. The logical coordinate system is the coordinate system used by
+the image input/output routines to access the image data on disk.
+.le
+.ls tv
+Tv coordinates are pixel coordinates used by the ximtool and saoimage
+display servers.
+Tv coordinates include the effects of any input image section, but
+do not include the effects of previous linear transformations.
+If the input image name does not include an image section, then tv coordinates
+are identical to logical coordinates. If the input image name does include
+a section, and the input image has not been linearly transformed or
+copied from a parent image, tv coordinates are identical to physical
+coordinates.
+.le
+.ls physical
+Physical coordinates are pixel coordinates invariant with respect to linear
+transformations of the physical image data. For example, if the current
+image was created by extracting a section of another image, the physical
+coordinates of an object in the current image will be equal to the physical
+coordinates of the same object in the parent image, although the logical
+coordinates will be different.
+.le
+.ls world
+World coordinates are image coordinates in any units which are invariant with
+respect to linear transformations of the physical image data. For example,
+the ra and dec of an object will always be the same no matter how the image
+is linearly transformed. The default world coordinate
+system is either 1) the value of the environment variable "defwcs" if
+set in the user's IRAF environment (normally it is undefined) and present
+in the image header, 2) the value of the "system"
+attribute in the image header keyword WAT0_001 if present in the
+image header or, 3) the "physical" coordinate system.
+.le
+.le
+.ls columns = "1 2 3 4 5 6 7"
+The list of columns separated by whitespace or commas in the input coordinate
+file containing the coordinate values.
+The number of specified columns must be greater than or equal to the
+dimensionality of the input image. The coordinates are read in the
+order they are specified in the columns parameter.
+.le
+.ls units = ""
+The units of the input coordinate values, normally degrees for the sky
+projection coordinate systems and angstroms for spectral coordinate
+systems.
+The options are:
+.ls hours
+Input coordinates specified in hours are converted to decimal degrees by
+multiplying by 15.0.
+.le
+.ls native
+The internal units of the wcs. No conversions on the input coordinates
+are performed.
+.le
+
+Units conversions are performed only if the input wcs is "world".
+.le
+.ls formats = ""
+The format for the computed output coordinates. If the formats
+parameter is undefined then: 1) the value of the wcs format attribute
+is used if the output wcs is "world" and the attribute is defined, 2)
+%g format is used with the precision set to the maximum of the precision of
+the input coordinates and the value of the min_sigdigits parameter.
+.le
+.ls min_sigdigits = 7
+The minimum precision of the output coordinates if, the formats parameter
+is undefined, and the output coordinate system is "world" but the wcs
+format attribute is undefined.
+.le
+.ls verbose = yes
+Print comment lines to the output file as the task executes.
+.le
+
+.ih
+DESCRIPTION
+
+WCSCTRAN transforms a list of coordinates, read from the input file
+\fIinput\fR, from the coordinate system defined by \fIinwcs\fR to the
+coordinate system defined by \fIoutwcs\fR using world coordinate system
+information in the input image \fIimage\fR header and writes the results
+to the output file \fIoutput\fR.
+
+The input coordinates are read from and written to the
+columns in the input / output file specified by the \fIcolumns\fR parameter.
+The units of the input coordinate units are assumed to be the internal
+units of the coordinate system as defined in the image header, normally
+degrees for sky projection coordinate systems and angstroms for
+spectral coordinate systems. For convenience input coordinates in hours
+are accepted and converted to decimal degrees if the \fIunits\fR parameter
+is set appropriately.
+
+The format of the output units can be set using the
+\fIformats\fR parameter. If the output formats are unspecified then the
+output coordinates are written using, 1) the value of wcs format attribute if
+outwcs = "world" and the attribute is defined, or, 2) the %g format and a
+precision which is the maximum of the precision of the input coordinates
+and the value of the \fImin_sigdigits\fR parameter. All remaining
+fields in the input file are copied to the output file without modification.
+
+WCSCTRAN transforms coordinates from one builtin IRAF coordinate system
+to another. The builtin coordinate systems are "logical", "physical", and
+"world". For convenience WCSCTRAN also supports the "tv" coordinate system
+which is not a builtin IRAF system, but is used by the display server tasks
+XIMTOOL, SAOIMAGE, and IMTOOL.
+
+The \fIlogical coordinate system\fR is the pixel coordinate system of the
+current image. This coordinate system is the one used by the image
+input/output routines to access the image on disk. In the
+logical coordinate system,
+the coordinates of the pixel centers must lie within the following
+range: 1.0 <= x[i] <= nx[i], where x[i] is the coordinate in dimension i,
+nx[i] is the size of the image in dimension i, and the current maximum
+number of image dimensions is 7. In the case of an image section,
+the nx[i] refer to the dimensions of the section, not the dimensions
+of the full image.
+
+The \fItv coordinate system\fR is the pixel coordinate system used by the
+display servers XIMTOOL, SAOIMAGE, and IMTOOL.
+For images which are not image sections
+the tv and logical coordinate systems are identical. For images which are
+image sections the tv and physical coordinate systems are identical if
+the image has not undergone any prior linear transformations such as
+axis flips, section copies, shifts, scale changes, rotations, etc.
+
+The \fIphysical coordinate system\fR is the coordinate system in which the
+pixel coordinates of an object are invariant to successive linear
+transformations
+of the image. In this coordinate system, the pixel coordinates of an object
+in an image remain the same, regardless of any section copies, shifts,
+rotations, etc on the image. For example, an object with the
+physical coordinates (x,y) in an image would still have physical
+coordinates (x, y) in an image which is a section of the original image.
+
+The \fIworld coordinate system\fR is the default coordinate system for the
+image. The default world coordinate system is the one named by the
+environment variable "defwcs" if defined in the user environment (initially
+it is undefined) and present in the image header; else it is the first
+world coordinate system
+defined for the image (the .imh and .hhh image format support only one wcs
+but the .qp format can support more); else it is the physical coordinate
+system.
+
+In most cases the number of input coordinates is equal to the number of
+output coordinates, and both are equal to the dimensions of the input image.
+In some cases however, the number of output coordinates may be greater or
+less than the number of input coordinates. This situation occurs
+if the input image has been dimensionally-reduced, i.e. is a section
+of a higher-dimensioned parent image, and the input coordinate system
+or the output coordinate system but not both is "logical" or "tv".
+For example, if the input image is a 1D line extracted from a 2D parent
+image with a sky projection world coordinate system, and the user
+specifies a transformation from the "logical" to "world" systems,
+only one input coordinate (column number) is required, but two output
+coordinates (ra and dec) are produced. If the input and output coordinate
+systems are reversed, then two input coordinates (ra and dec) are required,
+but only one output coordinate (column number) is produced. If the number of
+output coordinates is less than the number of input coordinates, the extra
+input coordinate columns in the input file are set to INDEF in the output file.
+If the number of output columns is greater than the number of input columns,
+the extra coordinate columns are added to the end of the output line.
+
+.ih
+FORMATS
+
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+
+.ih
+REFERENCES
+
+Additional information on IRAF world coordinate systems can be found in
+the help pages for the WCSEDIT and WCRESET tasks.
+Detailed documentation for the IRAF world coordinate system interface MWCS
+can be found in the file "iraf$sys/mwcs/MWCS.hlp". This file can be
+formatted and printed with the command "help iraf$sys/mwcs/MWCS.hlp fi+ |
+lprint". Details of the FITS header world coordinate system interface can
+be found in the document "World Coordinate Systems Representations Within the
+FITS Format" by Hanisch and Wells, available from our anonymous ftp
+archive.
+
+.ih
+EXAMPLES
+
+1. Find the pixel coordinates of a list of objects in an image, given a list
+of their ras and decs in hh:mm:ss.s and dd:mm:ss format. Limit the precision
+of the output coordinates to 3 decimal places. In this example, the input
+ras and decs are assumed to be in columns 1 and 2 of the input coordinate
+file, and the ras must be converted from hours to decimal degrees.
+
+.nf
+ im> wcsctran incoords outcoords image world logical units="h n" \
+ formats="%8.3f %0.3f"
+.fi
+
+2. Repeat the previous example using the same input coordinate list to
+produce output coordinate lists for a list of input images.
+
+.nf
+ im> wcsctran incoords @outcoolist @imlist world logical units="h n" \
+ formats="%8.3f %8.3f"
+.fi
+
+3. Transform pixel coordinates in a photometry file to ra and dec
+coordinates, writing the output coordinates in hh:mm:ss.ss and dd:mm:ss.s
+format. The input pixel coordinates are stored in columns 3 and 4 of the
+input coordinate file.
+
+.nf
+ im> wcsctran magfile omagfile image logical world col="3 4" \
+ formats="%12.2H %12.1h"
+.fi
+
+4. Given a set of pixel coordinates in the parent image, find the pixel
+coordinates of the same objects in an image which is a shifted, rotated
+and scaled version of the parent image. The input coordinate list
+is created using the displayed parent image and the rimcursor task.
+The output coordinate lists is marked on the displayed transformed
+image using the tvmark task.
+
+.nf
+ im> display parent 1 fi+
+ im> rimcursor > coolist
+ im> imlintran parent image 45.0 45.0 1.5 1.5 xin=256 yin=256 \
+ xout=281 yout=263
+ im> wcsctran coolist ocoolist image physical logical
+ im> display image 2 fi+
+ im> tvmark 2 outcoolist
+.fi
+
+.ih
+TIME REQUIREMENTS
+
+.ih
+BUGS
+
+.ih
+SEE ALSO
+wcsreset, wcsedit, rimcursor, listpixels, lintran
+
+.endhelp
diff --git a/pkg/images/imcoords/doc/wcsedit.hlp b/pkg/images/imcoords/doc/wcsedit.hlp
new file mode 100644
index 00000000..836add95
--- /dev/null
+++ b/pkg/images/imcoords/doc/wcsedit.hlp
@@ -0,0 +1,429 @@
+.help wcsedit Apr92 images.imcoords
+.ih
+NAME
+wcsedit -- edit an image world coordinate system parameter
+.ih
+USAGE
+wcsedit image parameter value axes1
+.ih
+PARAMETERS
+.ls image
+The list of images for which the WCS is to be edited. Image sections are
+ignored. If the image does not exist a data-less image header is first
+created with the default WCS of dimensionality given by the "wcsdim"
+parameter.
+.le
+.ls parameter
+The WCS parameter to be edited. The WCS parameters recognized by
+WCSEDIT are: 1) the FITS WCS
+parameters crpix, crval, cd and, 2) the IRAF WCS parameters ltv, ltm, wtype,
+axtype, units, label, and format. Only one WCS parameter may be edited at a
+time.
+.le
+.ls value
+The new parameter value. The numerical parameters crpix, crval, cd, ltv, and
+ltm will not be updated if WCSEDIT is unable to decode the parameter value
+into a legal floating point number.
+.le
+.ls axes1
+The list of principal axes for which \fIparameter\fR is to be edited.
+Axes1 can
+be entered as a list of numbers separated by commas, e.g. "1,2" or as a
+range, e.g. "1-2".
+.le
+.ls axes2
+The list of dependent axes for which \fIparameter\fR is to be edited.
+Axes2 can
+be entered as a list of numbers separated by commas, e.g. "1,2" or as a
+range, e.g. "1-2". The axes2 parameter is only required if
+\fIparameter\fR is "cd" or "ltm".
+.le
+.ls wcs = "world"
+The WCS to be edited. The options are: the builtin systems "world" or
+"physical", or a named system, e.g. "image" or "multispec". The builtin system
+"logical" may not be edited.
+.ls world
+If \fIwcs\fR is "world" the default WCS is edited. The default WCS
+is either 1) the value of the environment variable "defwcs" if
+set in the user's IRAF environment (normally it is undefined) and present
+in the image header,
+2) the value of the "system"
+attribute in the image header keyword WAT0_001 if present in the
+image header or, 3) the "physical" coordinate system.
+.le
+.ls physical
+If \fIwcs\fR is "physical", WCS is the pixel coordinate system of
+the original image, which may be different from the pixel coordinate system
+of the current image, if the current image is the result of an
+imcopy or other geometric transformation operation. In the "physical"
+coordinate system the ltv, ltm and the axis attribute
+parameters wtype, axtype, units, label, and format may be edited, but the FITS
+parameters crval, crpix, and cd cannot.
+.le
+.ls name
+A user supplied wcs name.
+If the named WCS does not exist in the image, a new one of that
+name initialized to the identity transform, will be opened for editing, and
+the old WCS will be destroyed. This option should only be used for creating
+a totally new FITS WCS.
+.le
+.le
+.ls wcsdim = 2
+WCS dimensionality when creating a new data-less image header.
+.le
+.ls interactive = no
+Edit the WCS interactively?
+.le
+.ls commands = ""
+The interactive editing command prompt.
+.le
+.ls verbose = yes
+Print messages about actions taken in interactive or non-interactive mode?
+.le
+.ls update = yes
+Update the image header in non-interactive mode? A specific command exists
+to do this in interactive mode.
+.le
+
+.ih
+DESCRIPTION
+WCSEDIT modifies the WCS of an existing image or creates a data-less image
+header of the dimensionality given by the \fIwcsdim\fR parameter.
+
+In non-interactive mode WCSEDIT replaces the current value of the WCS
+parameter \fIparameter\fR with the new value \fIvalue\fR in the headers of
+\fIimages\fR and prints a summary of the new WCS on the terminal. If
+\fIverbose\fR is "no" the summary is not printed. If \fIverbose\fR is
+"yes" and \fIupdate\fR is "no", the result of the editing operation
+is printed on the terminal but the header is not modified.
+
+The WCS parameter \fIparameter\fR may be one of: crval, crpix, cd, ltv, ltm,
+wtype, axtype, units, label, or format in either upper or lower case.
+The WCS array parameters crpix, crval, ltv, wtype, axtype, units, label,
+and format
+may be edited for more than one axis at a time by setting \fIaxes1\fR to a
+range of axes values. The WCS matrix parameters cd and ltm may be edited for
+more than one axis at a time by setting both \fIaxes1\fR and \fIaxes2\fR to
+a range of values. In this case, if no \fIaxes2\fR values are entered,
+\fIaxes2\fR = "", the
+diagonal elements of the cd and ltm matrices specified by \fIaxes1\fR are
+edited. A single non-diagonal element of the cd or ltm matrices can be
+edited by setting \fIaxis1\fR and \fIaxis2\fR to a single number.
+
+The user can create a new WCS from scratch by setting
+\fIwcs\fR to a name different from the name of the WCS in the image header.
+A new WCS with the same dimension as the image and initialized
+to the identity transformation is presented to the user for editing.
+IF THE USER UPDATES THE IMAGE HEADER AFTER EDITING THE NEW WCS, ALL
+PREVIOUS WCS INFORMATION IS LOST.
+
+In interactive mode, WCSEDIT displays the current WCS
+on the terminal if \fIverbose\fR = "yes", and prompts the user for
+an editing command. The supported editing commands are shown below.
+
+.nf
+ BASIC COMMANDS
+
+? Print the WCSEDIT commands
+show Print out the current WCS
+update Quit WCSEDIT and update the image WCS
+quit Quit WCSEDIT without updating the image WCS
+
+
+ PARAMETER DISPLAY AND EDITING COMMANDS
+
+crval [value axes1] Show/set the FITS crval parameter(s)
+crpix [value axes1] Show/set the FITS crpix parameter(s)
+cd [value axes1 [axes2]] Show/set the FITS cd parameter(s)
+ltv [value axes1] Show/set the IRAF ltv parameter(s)
+ltm [value axes1 [axes2]] Show/set the IRAF ltm parameter(s)
+wtype [value axes1] Show/set the FITS/IRAF axes transform(s)
+axtype [value axes1] Show/set the FITS/IRAF axis type(s)
+units [value axes1] Show/set the IRAF units(s)
+label [value axes1] Show/set the IRAF axes label(s)
+format [value axes1] Show/set the IRAF axes coordinate format(s)
+.fi
+
+.ih
+THE WCS PARAMETERS
+
+Below is a list of the WCS parameters as they appear encoded in the in the
+IRAF image header. Parameters marked with E can be edited directly with
+WCSEDIT. Parameters marked with U should be updated automatically by WCSEDIT
+if the proper conditions are met. The remaining parameters cannot be edited
+with WCSEDIT. A brief description of the listed parameters is given below.
+For a detailed description of the meaning of these parameters, the user
+should consult the two documents listed in the REFERENCES section.
+
+.nf
+WCSDIM WCS dimension (may differ from image)
+
+CTYPEn U coordinate type
+CRPIXn E reference pixel
+CRVALn E world coords of reference pixel
+CDi_j E CD matrix
+
+CDELTn U CDi_i if CD matrix not used (input only)
+CROTA2 U rotation angle if CD matrix not used
+
+LTVi E Lterm translation vector
+LTMi_j E Lterm rotation matrix
+
+WATi_jjj U WCS attributes for axis I (wtype,axtype,units,label,format)
+WAXMAPii WCS axis map
+.fi
+
+The WCSDIM and WAXMAP parameters cannot be edited by WCSEDIT, unless a
+new WCS is created in which case WCSDIM is set to
+the dimension of the input image and the axis map is deleted.
+The FITS parameters CRPIX, CRVAL, and CD
+define the transformation between the world coordinate system and the pixel
+coordinate system of the image and may be edited directly. The more general
+FITS CD matrix notation supersedes the FITS CDELT/CROTA notation if both are
+present on input, and is used by preference on output. The FITS parameter
+CTYPE cannot be edited directly by WCSEDIT but is correctly updated on
+output using the current values of the WCS parameters wtype and axtype
+parameters, if there was a pre-existing FITS header in the image. On input
+IRAF currently recognizes the following values of the FITS parameter CTYPE:
+RA---TAN and DEC--TAN (the tangent plane sky projection), RA---SIN and
+DEC--SIN (the sin sky projection), RA---ARC and DEC--ARC (the arc sky
+projection), LINEAR, and MULTISPEC, from which it derives the correct values
+for wtype and axtype.
+
+The LTV and LTM are IRAF parameters which define the transformation between
+the
+current image pixel coordinate system and the original pixel coordinate system,
+if the current image was derived from a previous
+image by a geometric transformation, e.g. IMCOPY or IMSHIFT.
+Both parameters may be edited directly by WCSEDIT, but with the exception
+of resetting the LTV vector to 0 and the LTM matrix to the identity
+matrix it is not usually desirable to do so. The task WCSRESET can also
+be used for this purpose.
+
+The WATi_jjj parameters are not directly accessible by WCSEDIT but the five
+axis attributes which are encoded under these keywords (wtype, axtype,
+units, label, and format) may be edited.
+The IRAF WCS code currently
+recognizes the following values for "wtype": "linear", "tan", "sin",
+"arc", and "multispec". If "wtype" is not defined or cannot
+be decoded by the WCS code "linear" is assumed.
+Axtype should be "ra" or "dec" if wtype is one of the sky projections
+"tan", "sin" or "arc", otherwise it should be undefined.
+WCSEDIT will combine the values of "wtype" and "axtype" on output to
+produce the correct value of the FITS keyword CTYPE.
+The "label" and "units" parameter may be set to any string constant.
+Format must be set to a legal IRAF format as described in the section
+below.
+
+.ih
+FORMATS
+A format specification has the form "%w.dCn", where w is the field
+width, d is the number of decimal places or the number of digits of
+precision, C is the format code, and n is radix character for
+format code "r" only. The w and d fields are optional. The format
+codes C are as follows:
+
+.nf
+b boolean (YES or NO)
+c single character (c or '\c' or '\0nnn')
+d decimal integer
+e exponential format (D specifies the precision)
+f fixed format (D specifies the number of decimal places)
+g general format (D specifies the precision)
+h hms format (hh:mm:ss.ss, D = no. decimal places)
+m minutes, seconds (or hours, minutes) (mm:ss.ss)
+o octal integer
+rN convert integer in any radix N
+s string (D field specifies max chars to print)
+t advance To column given as field W
+u unsigned decimal integer
+w output the number of spaces given by field W
+x hexadecimal integer
+z complex format (r,r) (D = precision)
+
+
+Conventions for w (field width) specification:
+
+ W = n right justify in field of N characters, blank fill
+ -n left justify in field of N characters, blank fill
+ 0n zero fill at left (only if right justified)
+absent, 0 use as much space as needed (D field sets precision)
+
+
+Escape sequences (e.g. "\n" for newline):
+
+\b backspace (not implemented)
+\f formfeed
+\n newline (crlf)
+\r carriage return
+\t tab
+\" string delimiter character
+\' character constant delimiter character
+\\ backslash character
+\nnn octal value of character
+
+Examples
+
+%s format a string using as much space as required
+%-10s left justify a string in a field of 10 characters
+%-10.10s left justify and truncate a string in a field of 10 characters
+%10s right justify a string in a field of 10 characters
+%10.10s right justify and truncate a string in a field of 10 characters
+
+%7.3f print a real number right justified in floating point format
+%-7.3f same as above but left justified
+%15.7e print a real number right justified in exponential format
+%-15.7e same as above but left justified
+%12.5g print a real number right justified in general format
+%-12.5g same as above but left justified
+
+%h format as nn:nn:nn.n
+%15h right justify nn:nn:nn.n in field of 15 characters
+%-15h left justify nn:nn:nn.n in a field of 15 characters
+%12.2h right justify nn:nn:nn.nn
+%-12.2h left justify nn:nn:nn.nn
+
+%H / by 15 and format as nn:nn:nn.n
+%15H / by 15 and right justify nn:nn:nn.n in field of 15 characters
+%-15H / by 15 and left justify nn:nn:nn.n in field of 15 characters
+%12.2H / by 15 and right justify nn:nn:nn.nn
+%-12.2H / by 15 and left justify nn:nn:nn.nn
+
+\n insert a newline
+.fi
+
+.ih
+REFERENCES
+
+Detailed documentation for the IRAF world coordinate system interface MWCS
+can be found in the file "iraf$sys/mwcs/MWCS.hlp". This file can be
+formatted and printed with the command "help iraf$sys/mwcs/MWCS.hlp fi+ |
+lprint". Details of the FITS header world coordinate system interface can
+be found in the document "World Coordinate Systems Representations Within the
+FITS Format" by Hanisch and Wells, available from our anonymous ftp
+archive.
+
+.ih
+EXAMPLES
+
+1. Change the default output coordinate formats for an image with a defined
+FITS tangent plane projection in its header, for the RA axis (axis 1), and the
+DEC axis (axis 2) to %H and %h respectively. Then display the image and use
+rimcursor to produce a coordinate list of objects whose coordinates are
+printed as hh:mm:ss.s and dd:mm:ss.s respectively.
+
+.nf
+ cl> wcsedit image format %H 1
+ cl> wcsedit image format %h 2
+ cl> display image 1
+ cl> rimcursor wcs=world > coordlist
+ ... mark the coordinates
+.fi
+
+2. Change the default sky projection for an image with a defined tangent
+plane projection to one with a sin projection. Note that wtype for both
+axis1 and axis2 must be changed to "sin". Check the results first before
+doing the actual update.
+
+.nf
+ cl> wcsedit image wtype sin 1-2 update-
+ cl> wcsedit image wtype sin 1-2
+.fi
+
+
+3. Change the diagonal elements of the FITS cd matrix to 2.0. The off
+diagonal elements are 0.0. This is equivalent to resetting the image scale.
+
+.nf
+ cl> wcsedit image cd 2.0 1-2 ""
+.fi
+
+4. Set the value of the FITS cd matrix elements, cd[2,1] and cd[1,2] to 0.0.
+This removes any rotation/skew from the WCS definition.
+
+.nf
+ cl> wcsedit image cd 0.0 2 1
+ cl> wcsedit image cd 0.0 1 2
+.fi
+
+5. Change the FITS crval value for axis 2.
+
+.nf
+ cl> wcsedit image crval 47.85 2
+.fi
+
+6. Create a totally new WCS for an image, deleting the previous WCS
+and set the diagonal elements of the cd matrix to 0.68. 0.68 is the
+scale of the 36 inch telescope at KPNO.
+
+.nf
+ cl> wcsedit image cd 1.5 1-2 wcs="kpno9m"
+.fi
+
+7. Interactively edit the WCS of an image. with an existing FITS header.
+
+.nf
+ cl> wcsedit image interactive+
+
+ ... summary of current WCS is printed on terminal
+
+ wcsedit: ?
+
+ ... user types in ? to see list of wcsedit commands
+
+ wcsedit: cd 2.0 1-2
+
+ ... user changes the scale of the WCS
+
+ wcsedit: format %0.3f 1-2
+
+ ... user changes format so the coordinates will be printed
+ out with 3 decimals of precision by any tasks which
+ can read the WCS format parameter such as rimcursor
+ and listpixels
+
+ wcsedit: show
+
+ ... user checks the new wcs
+
+ wcsedit: update
+
+ ... user quits editor and updates the image header
+.fi
+
+8. Open and edit a new WCS for an image. Any pre-existing WCS will
+be destroyed, assuming that the default wcs is not "newwcs".
+
+.nf
+ cl> wcsedit image wcs=newwcs intera+
+
+ wcsedit: ....
+ wcsedit: ....
+
+ ... edit in the desired values
+
+ wcsedit: update
+
+ ... update the image header.
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+The IRAF WCS code supports the dimensional reduction of images,
+for example creating an image with smaller dimensions than its parent, but
+may not be fully compatible with FITS when this occurs.
+In this case user may need to fix up an illegal or
+incorrect WCS with HEDIT or HFIX bypassing the WCS code used by WCSEDIT.
+
+WCSEDIT does not permit the user to edit any parameters encoded in the
+WATi_jjj keywords other than the five listed: wtype, axtype, units, label,
+and format. For example WCSEDIT cannot be used to edit the "speci" parameters
+used by the IRAF spectral reductions code "multispec" format. The spectral
+reduction code itself should be used to do this, although hfix can
+be used to fix a serious problem should it arise.
+.ih
+SEE ALSO
+wcsreset,hedit,hfix
+.endhelp
diff --git a/pkg/images/imcoords/doc/wcsreset.hlp b/pkg/images/imcoords/doc/wcsreset.hlp
new file mode 100644
index 00000000..401e0ae0
--- /dev/null
+++ b/pkg/images/imcoords/doc/wcsreset.hlp
@@ -0,0 +1,272 @@
+.help wcsreset Apr92 images.imcoords
+.ih
+NAME
+wcsreset -- reset the image coordinate system
+.ih
+USAGE
+wcsreset image wcs
+.ih
+PARAMETERS
+.ls image
+The list of images for which the coordinate system is to be reset. Image
+sections are ignored.
+.le
+.ls wcs
+The name of the coordinate system to be reset. The following systems are
+pre-defined:
+.ls physical
+Reset the physical coordinate system to the logical coordinate system, but
+leave the default world coordinate system unchanged. This operation removes
+the history of past image operations such as imcopy, imshift, magnify, etc
+from the definition of the physical coordinate system, but not from the
+definition of the world coordinate system.
+.le
+.ls world
+Reset the default world coordinate system to the logical coordinate system.
+This operation removes all world coordinate system information from the
+image header.
+.le
+
+In addition to these two reserved world coordinate systems, the name of any
+other defined world coordinate system, for example "multispec" may be given.
+In this case WCSRESET resets the named coordinate system to the logical
+coordinate system only if it is present in the image header.
+.le
+.ls verbose = yes
+Print messages about actions taken by the task?
+.le
+.ih
+DESCRIPTION
+
+WCSRESET resets the coordinate system \fIwcs\fR in the images specified by
+\fIimage\fR to the logical coordinate system, and prints messages about the
+actions taken if \fIverbose\fR = "yes". Since WCSRESET modifies the
+image headers it should be used with caution.
+
+Logical coordinates are coordinates relative to the current image. The
+logical coordinate system is the one used by the image input/output routines
+to access the image on disk. In an image raster logical coordinate system,
+the coordinates of the pixel centers must lie within the following
+range: 1.0 <= x[i] <= nx[i], where x[i] is the coordinate in dimension i,
+nx[i] is the size of the image in dimension i, and the current maximum
+number of image dimensions is 7. In the case of an image section of an image
+raster, the nx[i] refer to the dimensions of the section, not the dimensions
+of the full image. The logical coordinate system cannot by definition be
+reset.
+
+The physical coordinate system is the coordinate system in which the
+coordinates of an object are invariant to successive linear transformations
+of the image. In this coordinate system, the pixel coordinates of an object
+in an image raster remain the same, regardless of any imcopy, imshift,
+rotate, etc operations on the image. The most common reason for desiring to
+reset the physical coordinate system to the logical coordinate system is to
+make the new image independent of its history by removing the effects of
+these linear transformation operations from its physical coordinate system.
+Resetting the physical coordinate system to the logical coordinate system,
+does not alter the default world coordinate system. If for example the input
+image is a spectrum, with a defined dispersion solution, resetting the
+physical coordinate system will not alter the dispersion solution.
+Similarly if the input image is a direct CCD image with a defined sky
+projection world coordinate system, resetting the physical coordinate system
+will not alter the sky projection.
+
+The world coordinate system is the default coordinate system for the
+image. The default world coordinate system is the one named by the
+environment variable "defwcs" if defined in the user environment (initially
+it is undefined) and present in the image header; else it is the first
+world coordinate system
+defined for the image (the .imh and .hhh image format support only one wcs
+but the .qp format can support more); else it is the physical coordinate
+system. Resetting the default coordinate system to the logical
+coordinate system will destroy all coordinate information for that system,
+for that image.
+
+If the user sets the parameter wcs to a specific system, for example
+to "multispec", only images with the coordinate system "multispec"
+will have their coordinate system reset.
+
+.ih
+REFERENCES
+
+Detailed documentation for the IRAF world coordinate system interface MWCS
+can be found in the file "iraf$sys/mwcs/MWCS.hlp". This file can be
+formatted and printed with the command "help iraf$sys/mwcs/MWCS.hlp fi+ |
+lprint". Details of the FITS header world coordinate system interface can
+be found in the document "World Coordinate Systems Representations Within the
+FITS Format" by Hanisch and Wells, available from our anonymous ftp
+archive.
+
+.ih
+EXAMPLES
+
+1. The user runs implot on a section of the spectrum outspec with the
+wcs parameter set to "physical".
+
+.nf
+ implot outsec[30:50] wcs=physical
+.fi
+
+To his/her surprise the range of the plot in x produced by implot is
+[129,149] not [30:50] as expected. The user lists the image header with the
+imheader task and sees the following.
+
+.nf
+ WCSDIM = 1
+ CTYPE1 = 'LINEAR '
+ CRVAL1 = 4953.94775390626
+ CRPIX1 = -98.
+ CDELT1 = 0.0714096948504449
+ CD1_1 = 0.0714096948504449
+ WAT0_001= 'system=linear
+ WAT1_001= 'wtype=linear label=Wavelength units=Angstroms
+ LTV1 = -99.
+ LTM1_1 = 1.
+.fi
+
+The standard FITS keywords CTYPE1, CRVAL1, CRPIX1, and CDELT1 are present.
+The CD1_1 keyword is part of the new FITS CD matrix notation and in this
+example duplicates the function of CDELT1. The remaining keywords WCSDIM,
+WAT0_001, WAT1_001, LTV1, and LTM1_1 are IRAF specific keywords. The
+user notes that the LTV1 keyword is -99. not 0. and suddenly remembers that
+outspec was created by extracting a piece of a larger spectrum using the
+imcopy task as shown below.
+
+.nf
+ cl> imcopy inspec[100:200] outspec
+.fi
+
+The section [30:50] in outspec actually corresponds to the section [129:149]
+in inspec and it is this coordinate system that implot is plotting when
+wcs = "physical". The user decides has he/she does not want to know
+about the pixel coordinate system of the original image and runs wcsreset
+to reset the physical coordinate system to the logical coordinate system.
+
+.nf
+ wcsreset outspec physical
+.fi
+
+The new header of outspec looks like the following.
+
+.nf
+ WCSDIM = 1
+ CTYPE1 = 'LINEAR '
+ CRVAL1 = 4953.94775390626
+ CRPIX1 = -98.
+ CDELT1 = 0.0714096948504449
+ CD1_1 = 0.0714096948504449
+ WAT0_001= 'system=linear
+ WAT1_001= 'wtype=linear label=Wavelength units=Angstroms
+ LTM1_1 = 1.
+.fi
+
+It is identical to the header listed above except that the
+LTV1 keyword is not defined and is therefore 0. The user runs
+implot with wcs = "physical" as before and sees a plot which extends
+from 30 to 50 as expected.
+
+2. Reset the physical coordinate system of the direct CCD image skypix
+which has a defined sky projection system. Skypix was created by
+copying the central [129:384,129:384] of a 512 square image into a 256
+square image.
+
+The image header is the following.
+
+.nf
+ CRPIX1 = 129.75
+ CRPIX2 = 130.93
+ CRVAL1 = 201.94541667302
+ CRVAL2 = 47.45444
+ CTYPE1 = 'RA---TAN'
+ CTYPE2 = 'DEC--TAN'
+ CDELT1 = -2.1277777E-4
+ CDELT2 = 2.1277777E-4
+ WCSDIM = 2
+ CD1_1 = -2.1277777000000E-4
+ CD2_2 = 2.12777770000000E-4
+ LTV1 = -128.
+ LTV2 = -128.
+ LTM1_1 = 1.
+ LTM2_2 = 1.
+ WAT0_001= 'system=image
+ WAT1_001= 'wtype=tan axtype=ra
+ WAT2_001= 'wtype=tan axtype=dec
+.fi
+
+The user runs implot on skypix wcs = "physical"
+
+.nf
+ implot skypix wcs=physical
+.fi
+
+and sees a plot in x which extends from 129 to 384 which are the coordinates
+of skypix in the original image.
+The user resets the physical coordinate system to the logical coordinate
+system.
+
+.nf
+ cl> wcsreset m51 physical
+.fi
+
+The new header looks like the following. Note that the LTV1 and LTV2 keywords
+have disappeared, they are 0. but everything else is the same.
+
+.nf
+ CRPIX1 = 129.75
+ CRPIX2 = 130.93
+ CRVAL1 = 201.94541667302
+ CRVAL2 = 47.45444
+ CTYPE1 = 'RA---TAN'
+ CTYPE2 = 'DEC--TAN'
+ CDELT1 = -2.1277777E-4
+ CDELT2 = 2.1277777E-4
+ WCSDIM = 2
+ CD1_1 = -2.1277777000000E-4
+ CD2_2 = 2.12777770000000E-4
+ LTM1_1 = 1.
+ LTM2_2 = 1.
+ WAT0_001= 'system=image
+ WAT1_001= 'wtype=tan axtype=ra
+ WAT2_001= 'wtype=tan axtype=dec
+.fi
+
+When the user runs implot with wcs = "physical" he/she sees a plot which
+extends from 1 to 256 as expected.
+
+3. Initialize the world coordinate system of the previous image.
+
+.nf
+ cl> wcsreset skypix world
+.fi
+
+The header now looks like the following.
+
+.nf
+ WCSDIM = 2
+ LTM1_1 = 1.
+ LTM2_2 = 1.
+ WAT0_001= 'system=physical
+ WAT1_001= 'wtype=linear
+ WAT2_001= 'wtype=linear
+.fi
+
+The world system defaults to the physical coordinates system and the
+physical coordinate system is identical to the logical coordinate system.
+All coordinate information has been destroyed.
+
+4. Initialize the world coordinate system "spec1". If the default world
+coordinate
+system "spec1" cannot be found in the image header a warning message
+will be issued and nothing will be changed.
+
+.nf
+ cl> wcsreset spectrum spec1
+.fi
+
+.ih
+TIME REQUIREMENTS
+.ih
+BUGS
+.ih
+SEE ALSO
+rimcursor,listpixels,wcsedit,hedit,hfix
+.endhelp
diff --git a/pkg/images/imcoords/hpctran.par b/pkg/images/imcoords/hpctran.par
new file mode 100644
index 00000000..7e58ee94
--- /dev/null
+++ b/pkg/images/imcoords/hpctran.par
@@ -0,0 +1,9 @@
+# HEALPIXWCS
+
+row,i,h,,,,Map row
+lng,r,h,,,,Longitude
+lat,r,h,,,,Latitude
+nside,i,h,512,,,Resolution parameter
+cunits,s,h,"degrees","hourdegree|degrees|radians",,Coordinate units
+maptype,s,h,"nest","nest|ring",,Map type
+direction,s,h,"ang2row","ang2row|row2ang",,Conversion direction
diff --git a/pkg/images/imcoords/imcctran.par b/pkg/images/imcoords/imcctran.par
new file mode 100644
index 00000000..13e9638e
--- /dev/null
+++ b/pkg/images/imcoords/imcctran.par
@@ -0,0 +1,9 @@
+# Parameter file for the IMCCTRAN task
+
+image,f,a,,,,"List of input images"
+outsystem,s,a,,,,"The new image coordinate system"
+nx,i,h,10,,,"The coordinate grid size in x"
+ny,i,h,10,,,"The coordinate grid size in y"
+longpole,b,h,no,,,"Update longpole rather than the cd matrix where appropriate ?"
+verbose,b,h,yes,,,"Print messages about actions taken ?"
+update,b,h,yes,,,"Update the image header ?"
diff --git a/pkg/images/imcoords/imcoords.cl b/pkg/images/imcoords/imcoords.cl
new file mode 100644
index 00000000..5f756aee
--- /dev/null
+++ b/pkg/images/imcoords/imcoords.cl
@@ -0,0 +1,27 @@
+#{ IMCOORDS -- The Image Coordinates Package.
+
+set imcoords = "images$imcoords/"
+
+package imcoords
+
+# Tasks.
+
+task ccfind,
+ ccget,
+ ccmap,
+ ccsetwcs,
+ ccstd,
+ cctran,
+ ccxymatch,
+ hpctran,
+ imcctran,
+ skyctran,
+ starfind,
+ wcsctran,
+ wcsedit,
+ wcsreset = "imcoords$x_images.e"
+
+task mkcwcs = "imcoords$src/mkcwcs.cl"
+task mkcwwcs = "imcoords$src/mkcwwcs.cl"
+
+clbye()
diff --git a/pkg/images/imcoords/imcoords.hd b/pkg/images/imcoords/imcoords.hd
new file mode 100644
index 00000000..1f60d023
--- /dev/null
+++ b/pkg/images/imcoords/imcoords.hd
@@ -0,0 +1,23 @@
+# Help directory for the IMCOORDS package
+
+$doc = "images$imcoords/doc/"
+$src = "images$imcoords/src/"
+
+ccfind hlp=doc$ccfind.hlp, src=src$t_ccfind.x
+ccget hlp=doc$ccget.hlp, src=src$t_ccget.x
+ccmap hlp=doc$ccmap.hlp, src=src$t_ccmap.x
+ccsetwcs hlp=doc$ccsetwcs.hlp, src=src$t_ccsetwcs.x
+ccstd hlp=doc$ccstd.hlp, src=src$t_ccstd.x
+cctran hlp=doc$cctran.hlp, src=src$t_cctran.x
+ccxymatch hlp=doc$ccxymatch.hlp, src=src$t_ccxymatch.x
+hpctran hlp=doc$hpctran.hlp, src=src$t_hpctran.x
+imcctran hlp=doc$imcctran.hlp, src=src$t_imcctran.x
+mkcwcs hlp=doc$mkcwcs.hlp, src=src$mkcwcs.cl
+mkcwwcs hlp=doc$mkcwwcs.hlp, src=src$mkcwwcs.cl
+skyctran hlp=doc$skyctran.hlp, src=src$t_skyctran.x
+starfind hlp=doc$starfind.hlp, src=src$t_starfind.x
+wcsctran hlp=doc$wcsctran.hlp, src=src$t_wcsctran.x
+wcsedit hlp=doc$wcsedit.hlp, src=src$t_wcsedit.x
+wcsreset hlp=doc$wcsreset.hlp, src=src$t_wcsreset.x
+revisions sys=Revisions
+
diff --git a/pkg/images/imcoords/imcoords.men b/pkg/images/imcoords/imcoords.men
new file mode 100644
index 00000000..3a30ac9c
--- /dev/null
+++ b/pkg/images/imcoords/imcoords.men
@@ -0,0 +1,16 @@
+ ccfind - Find catalog sources in an image
+ ccget - Extract objects from a text file catalog
+ ccmap - Compute image plate solutions using matched coordinate lists
+ ccsetwcs - Create an image celestial wcs from the ccmap plate solution
+ ccstd - Transform to and from standard astrometric coordinates
+ cctran - Transform coordinate lists using the ccmap plate solution
+ ccxymatch - Match celestial and pixel coordinate lists
+ hpctran - Convert between HEALPix row and spherical coordinate
+ imcctran - Transform image header from one celestial wcs to another
+ mkcwcs - Make or update a simple celestial wcs
+ mkcwwcs - Make or update a simple celestial/wavelength 3D wcs
+ skyctran - Transform coordinates from one celestial wcs to another
+ starfind - Automatically detect stellar objects in a list of images
+ wcsctran - Transform coordinates from one iraf image wcs to another
+ wcsedit - Edit an image wcs parameter
+ wcsreset - Reset the specified image wcs
diff --git a/pkg/images/imcoords/imcoords.par b/pkg/images/imcoords/imcoords.par
new file mode 100644
index 00000000..cef3f3ff
--- /dev/null
+++ b/pkg/images/imcoords/imcoords.par
@@ -0,0 +1 @@
+version,s,h,"Jan97"
diff --git a/pkg/images/imcoords/mkpkg b/pkg/images/imcoords/mkpkg
new file mode 100644
index 00000000..e1cb9e6a
--- /dev/null
+++ b/pkg/images/imcoords/mkpkg
@@ -0,0 +1,5 @@
+# MKPKG for the IMCOORDS Package
+
+libpkg.a:
+ @src
+ ;
diff --git a/pkg/images/imcoords/skyctran.par b/pkg/images/imcoords/skyctran.par
new file mode 100644
index 00000000..d5658ffe
--- /dev/null
+++ b/pkg/images/imcoords/skyctran.par
@@ -0,0 +1,29 @@
+# Parameter file for the SKYCOORDS task.
+
+input,s,a,"STDIN",,,The input coordinate files(s)
+output,s,a,"STDOUT",,,The output coordinate file(s)
+insystem,s,a,"fk4",,,The input coordinate system
+outsystem,s,a,"fk5",,,The output coordinate system
+transform,s,h,no,,,Transform the input coordinate file ?
+lngcolumn,i,h,1,,,The input file column containing the x/ra/longitude
+latcolumn,i,h,2,,,The input file column containing the y/dec/latitude
+plngcolumn,i,h,INDEF,,,The input file column containing the x/ra/longitude pm
+platcolumn,i,h,INDEF,,,The input file column containing the y/dec/latitude pm
+pxcolumn,i,h,INDEF,,,The input file column contain the parallax
+rvcolumn,i,h,INDEF,,,The input file column contain the radial velocity
+ilngmin,r,h,INDEF,,,The input grid x/ra/longitude minimum
+ilngmax,r,h,INDEF,,,The input grid x/ra/longitude maximum
+ilatmin,r,h,INDEF,,,The input grid y/dec/latitude minimum
+ilatmax,r,h,INDEF,,,The input grid y/dec/latitude maximum
+nilng,i,h,10,1,,Number of grid points in x/ra/longitude
+nilat,i,h,10,1,,Number of grid points in y/dec/latitude
+ilngunits,s,h,"",,,The input ra/longitude units
+ilatunits,s,h,"",,,The input dec/latitude units
+ilngformat,s,h,"",,,The input grid x/ra/longitude format
+ilatformat,s,h,"",,,The input grid y/dec/latitude format
+olngunits,s,h,"",,,The output ra/longitude units
+olatunits,s,h,"",,,The output dec/latitude units
+olngformat,s,h,"",,,The output x/ra/longitude format
+olatformat,s,h,"",,,The output y/dec/latitude format
+icommands,*imcur,h,"",,,The image display cursor
+verbose,b,h,yes,,,Print messages about actions taken by the task ?
diff --git a/pkg/images/imcoords/src/ccfunc.x b/pkg/images/imcoords/src/ccfunc.x
new file mode 100644
index 00000000..9f60498a
--- /dev/null
+++ b/pkg/images/imcoords/src/ccfunc.x
@@ -0,0 +1,639 @@
+include <imhdr.h>
+include <math.h>
+include <math/gsurfit.h>
+include <mwset.h>
+include <pkg/skywcs.h>
+
+
+# CC_RPROJ -- Read the projection parameters from a file into an IRAF string
+# containing the projection type followed by an MWCS WAT string, e.g
+# "zpn projp1=value projp2=value" .
+
+int procedure cc_rdproj (fd, projstr, maxch)
+
+int fd #I the input file containing the projection parameters
+char projstr[ARB] #O the output projection parameters string
+int maxch #I the maximum size of the output projection string
+
+int projection, op
+pointer sp, keyword, value, param
+int fscan(), nscan(), strdic(), gstrcpy()
+
+begin
+ projstr[1] = EOS
+ if (fscan (fd) == EOF)
+ return (0)
+
+ call smark (sp)
+ call salloc (keyword, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+ call salloc (param, SZ_FNAME, TY_CHAR)
+
+ call gargwrd (Memc[keyword], SZ_FNAME)
+ projection = strdic (Memc[keyword], Memc[keyword], SZ_FNAME,
+ WTYPE_LIST)
+ if (projection <= 0 || projection == WTYPE_LIN || nscan() == 0) {
+ call sfree (sp)
+ return (0)
+ }
+
+ # Copy the projection function into the projection string.
+ op = 1
+ op = op + gstrcpy (Memc[keyword], projstr[op], maxch)
+
+ # Copy the keyword value pairs into the projection string.
+ while (fscan(fd) != EOF) {
+ call gargwrd (Memc[keyword], SZ_FNAME)
+ call gargwrd (Memc[value], SZ_FNAME)
+ if (nscan() != 2)
+ next
+ call sprintf (Memc[param], SZ_FNAME, " %s = %s")
+ call pargstr (Memc[keyword])
+ call pargstr (Memc[value])
+ op = op + gstrcpy (Memc[param], projstr[op], maxch - op + 1)
+ }
+
+ call sfree (sp)
+
+ return (projection)
+end
+
+
+define NEWCD Memd[ncd+(($2)-1)*ndim+($1)-1]
+
+# CC_WCSIM -- Update the image world coordinate system.
+
+procedure cc_wcsim (im, coo, projection, lngref, latref, sx1, sy1, transpose)
+
+pointer im #I the pointer to the input image
+pointer coo #I the pointer to the coordinate structure
+char projection[ARB] #I the sky projection geometry
+double lngref, latref #I the position of the reference point.
+pointer sx1, sy1 #I pointer to linear surfaces
+bool transpose #I transpose the wcs
+
+int ndim, naxes, ax1, ax2, axmap, wtype
+double xshift, yshift, a, b, c, d, denom, xpix, ypix, tlngref, tlatref
+pointer mw, sp, str, r, w, cd, ltm, ltv, iltm, nr, ncd, axes, axno, axval
+int mw_stati(), sk_stati(), strdic()
+pointer mw_openim()
+
+begin
+ mw = mw_openim (im)
+ ndim = mw_stati (mw, MW_NPHYSDIM)
+
+ # Allocate working memory for the vectors and matrices.
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (axno, IM_MAXDIM, TY_INT)
+ call salloc (axval, IM_MAXDIM, TY_INT)
+ call salloc (axes, IM_MAXDIM, TY_INT)
+ 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)
+
+ # Compute the original logical to world transformation.
+ call mw_gaxmap (mw, Memi[axno], Memi[axval], ndim)
+ call mw_gltermd (mw, Memd[ltm], Memd[ltv], ndim)
+
+ # Get the axis map.
+ call mw_gaxlist (mw, 03B, Memi[axes], naxes)
+ axmap = mw_stati (mw, MW_USEAXMAP)
+ ax1 = Memi[axes]
+ ax2 = Memi[axes+1]
+
+ # Set the system.
+ iferr (call mw_newsystem (mw, "image", ndim))
+ ;
+
+ # Set the axes and projection type.
+ if (projection[1] == EOS) {
+ call mw_swtype (mw, Memi[axes], ndim, "linear", "")
+ } else {
+ call mw_swtype (mw, Memi[axes], ndim, projection,
+ "axis 1: axtype=ra axis 2: axtype=dec")
+ }
+
+ # Compute the new referemce point.
+ 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+ax1-1] = tlatref
+ Memd[w+ax2-1] = tlngref
+ }
+
+
+ # Fetch the linear coefficients of the fit.
+ call geo_gcoeffd (sx1, sy1, xshift, yshift, a, b, c, d)
+
+ # Compute the new reference pixel.
+ denom = a * d - c * b
+ if (denom == 0.0d0)
+ xpix = INDEFD
+ else
+ xpix = (b * yshift - d * xshift) / denom
+ if (denom == 0.0d0)
+ ypix = INDEFD
+ else
+ ypix = (c * xshift - a * yshift) / denom
+ Memd[nr+ax1-1] = xpix
+ Memd[nr+ax2-1] = ypix
+
+ # Compute the new CD matrix.
+ if (! transpose) {
+ NEWCD(ax1,ax1) = a / 3600.0d0
+ NEWCD(ax1,ax2) = c / 3600.0d0
+ NEWCD(ax2,ax1) = b / 3600.0d0
+ NEWCD(ax2,ax2) = d / 3600.0d0
+ } else {
+ NEWCD(ax1,ax1) = c / 3600.0d0
+ NEWCD(ax1,ax2) = a / 3600.0d0
+ NEWCD(ax2,ax1) = d / 3600.0d0
+ NEWCD(ax2,ax2) = b / 3600.0d0
+ }
+
+ # Reset the axis map.
+ call mw_seti (mw, MW_USEAXMAP, axmap)
+
+ # Recompute and store the new wcs if update is enabled.
+ call mw_saxmap (mw, Memi[axno], Memi[axval], ndim)
+ if (sk_stati (coo, S_PIXTYPE) == PIXTYPE_PHYSICAL) {
+ call mw_swtermd (mw, 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 (mw, 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)
+ }
+ call sk_saveim (coo, mw, im)
+ call mw_saveim (mw, im)
+ 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 (projection, Memc[str], 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
+
+
+# CC_NWCSIM -- Update the image world coordinate system.
+
+procedure cc_nwcsim (im, coo, projection, lngref, latref, sx1, sy1, sx2, sy2,
+ transpose)
+
+pointer im #I the pointer to the input image
+pointer coo #I the pointer to the coordinate structure
+char projection[ARB] #I the sky projection geometry
+double lngref, latref #I the position of the reference point.
+pointer sx1, sy1 #I pointer to linear surfaces
+pointer sx2, sy2 #I pointer to distortion surfaces
+bool transpose #I transpose the wcs
+
+int l, i, ndim, naxes, ax1, ax2, axmap, wtype, szatstr
+double xshift, yshift, a, b, c, d, denom, xpix, ypix, tlngref, tlatref
+pointer mw, sp, r, w, cd, ltm, ltv, iltm, nr, ncd, axes, axno, axval
+pointer projstr, projpars, wpars, mwnew, atstr
+bool streq()
+int mw_stati(), sk_stati(), strdic(), strlen(), itoc()
+pointer mw_openim(), mw_open()
+errchk mw_gwattrs(), mw_newsystem()
+
+begin
+ # Open the image wcs and determine its size.
+ mw = mw_openim (im)
+ ndim = mw_stati (mw, MW_NPHYSDIM)
+
+ # Allocate working memory for the wcs attributes, 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 (axno, IM_MAXDIM, TY_INT)
+ call salloc (axval, IM_MAXDIM, TY_INT)
+ call salloc (axes, IM_MAXDIM, TY_INT)
+ 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)
+
+ # Open the new wcs and set the system type.
+ 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 celestial coordinate axes list.
+ 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 for the celestial coordinate
+ # axes. Don't worry about the fact that the axes may in fact be
+ # glon and glat, elon and elat, or slon and slat, instead of
+ # ra and dec. This will be fixed up later.
+ 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])
+ if (streq (Memc[projstr], "tnx") && sx2 == NULL && sy2 == NULL)
+ call strcpy ("tan", Memc[projstr], SZ_FNAME)
+ call mw_swtype (mwnew, Memi[axes], ndim, Memc[projstr], Memc[wpars])
+ }
+
+ # Copy the attributes of the remaining axes to the new wcs.
+ 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[projpars] = 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, l, Memc[projpars], Memc[atstr])
+ }
+ }
+ call mfree (atstr, TY_CHAR)
+
+ # Compute the new referemce point.
+ 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+ax1-1] = tlatref
+ Memd[w+ax2-1] = tlngref
+ }
+ # Fetch the linear coefficients of the fit.
+ call geo_gcoeffd (sx1, sy1, xshift, yshift, a, b, c, d)
+
+ # Compute the new reference pixel.
+ denom = a * d - c * b
+ if (denom == 0.0d0)
+ xpix = INDEFD
+ else
+ xpix = (b * yshift - d * xshift) / denom
+ if (denom == 0.0d0)
+ ypix = INDEFD
+ else
+ ypix = (c * xshift - a * yshift) / denom
+ Memd[nr+ax1-1] = xpix
+ Memd[nr+ax2-1] = ypix
+
+ # Compute the new CD matrix.
+ if (! transpose) {
+ NEWCD(ax1,ax1) = a / 3600.0d0
+ NEWCD(ax1,ax2) = c / 3600.0d0
+ NEWCD(ax2,ax1) = b / 3600.0d0
+ NEWCD(ax2,ax2) = d / 3600.0d0
+ } else {
+ NEWCD(ax1,ax1) = c / 3600.0d0
+ NEWCD(ax1,ax2) = a / 3600.0d0
+ NEWCD(ax2,ax1) = d / 3600.0d0
+ NEWCD(ax2,ax2) = b / 3600.0d0
+ }
+
+ # Recompute and store the new wcs.
+ 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)
+ }
+
+ # Add the second order terms in the form of the wcs attributes
+ # lngcor and latcor. These are not FITS standard and can currently
+ # be understood only by IRAF.
+ if ((streq(Memc[projstr], "zpx") || streq (Memc[projstr], "tnx")) &&
+ (sx2 != NULL || sy2 != NULL)) {
+ if (! transpose)
+ call cc_wcscor (im, mwnew, sx1, sx2, sy1, sy2, "lngcor",
+ "latcor", ax1, ax2)
+ else
+ call cc_wcscor (im, mwnew, sx1, sx2, sy1, sy2, "lngcor",
+ "latcor", ax2, ax1)
+ }
+
+ # 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)
+ }
+ call sk_saveim (coo, mwnew, im)
+ call mw_saveim (mwnew, im)
+ call mw_close (mwnew)
+ call mw_close (mw)
+
+ # Force the CTYPE 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.
+ 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
+
+
+# CC_WCSCOR -- Reformulate the higher order surface fit into a correction
+# term in degrees that can be written into the header as a wcs attribute.
+# This attribute will be written as string containing the surface definition.
+
+procedure cc_wcscor (im, mw, sx1, sx2, sy1, sy2, xiname, etaname, xiaxis,
+ etaaxis)
+
+pointer im #I pointer to the input image
+pointer mw #I pointer to the wcs structure
+pointer sx1, sx2 #I pointer to the linear and distortion xi surfaces
+pointer sy1, sy2 #I pointer to the linear and distortion eta surfaces
+char xiname[ARB] #I the wcs xi correction attribute name
+char etaname[ARB] #I the wcs eta correction attribute name
+int xiaxis #I the xi axis number
+int etaaxis #I the eta axis number
+
+int i, j, function, xxorder, xyorder, xxterms, yxorder, yyorder, yxterms
+int nx, ny, npix, ier
+double sxmin, sxmax, symin, symax, ratio, x, y, xstep, ystep, ximin, ximax
+double etamin, etamax
+pointer sp, xpix, ypix, xilin, etalin, dxi, deta, wgt, nsx2, nsy2
+int dgsgeti()
+double dgsgetd()
+begin
+ if (sx2 == NULL && sy2 == NULL)
+ return
+ if (dgsgeti (sx1, GSTYPE) != dgsgeti (sy1, GSTYPE))
+ return
+
+ # Get the function, xmin, xmax, ymin, and ymax parameters for the
+ # surfaces.
+ function = min (dgsgeti (sx1, GSTYPE), dgsgeti (sy1, GSTYPE))
+ sxmin = max (dgsgetd (sx1, GSXMIN), dgsgetd (sy1, GSXMIN))
+ sxmax = min (dgsgetd (sx1, GSXMAX), dgsgetd (sy1, GSXMAX))
+ symin = max (dgsgetd (sx1, GSYMIN), dgsgetd (sy1, GSYMIN))
+ symax = min (dgsgetd (sx1, GSYMAX), dgsgetd (sy1, GSYMAX))
+
+ # Get the order and cross-terms parameters from the higher order
+ # functions.
+ if (sx2 != NULL) {
+ xxorder = dgsgeti (sx2, GSXORDER)
+ xyorder = dgsgeti (sx2, GSYORDER)
+ xxterms = dgsgeti (sx2, GSXTERMS)
+ } else {
+ xxorder = dgsgeti (sx1, GSXORDER)
+ xyorder = dgsgeti (sx1, GSYORDER)
+ xxterms = dgsgeti (sx1, GSXTERMS)
+ }
+ if (sy2 != NULL) {
+ yxorder = dgsgeti (sy2, GSXORDER)
+ yyorder = dgsgeti (sy2, GSYORDER)
+ yxterms = dgsgeti (sy2, GSXTERMS)
+ } else {
+ yxorder = dgsgeti (sy1, GSXORDER)
+ yyorder = dgsgeti (sy1, GSYORDER)
+ yxterms = dgsgeti (sy1, GSXTERMS)
+ }
+
+ # Choose a reasonable coordinate grid size based on the x and y order
+ # of the fit and the number of rows and columns in the image.
+ ratio = double (IM_LEN(im,2)) / double (IM_LEN(im,1))
+ nx = max (xxorder + 3, yxorder + 3, 10)
+ ny = max (yyorder + 3, xyorder + 3, nint (ratio * 10))
+ npix = nx * ny
+
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (xpix, npix, TY_DOUBLE)
+ call salloc (ypix, npix, TY_DOUBLE)
+ call salloc (xilin, npix, TY_DOUBLE)
+ call salloc (etalin, npix, TY_DOUBLE)
+ call salloc (dxi, npix, TY_DOUBLE)
+ call salloc (deta, npix, TY_DOUBLE)
+ call salloc (wgt, npix, TY_DOUBLE)
+
+ # Compute the grid of x and y points.
+ xstep = (sxmax - sxmin) / (nx - 1)
+ ystep = (symax - symin) / (ny - 1)
+ y = symin
+ npix = 0
+ do j = 1, ny {
+ x = sxmin
+ do i = 1, nx {
+ Memd[xpix+npix] = x
+ Memd[ypix+npix] = y
+ x = x + xstep
+ npix = npix + 1
+ }
+ y = y + ystep
+ }
+
+
+ # Compute the weights
+ call amovkd (1.0d0, Memd[wgt], npix)
+
+ # Evalute the linear surfaces and convert the results from arcseconds
+ # to degrees.
+ call dgsvector (sx1, Memd[xpix], Memd[ypix], Memd[xilin], npix)
+ call adivkd (Memd[xilin], 3600.0d0, Memd[xilin], npix)
+ call alimd (Memd[xilin], npix, ximin, ximax)
+ call dgsvector (sy1, Memd[xpix], Memd[ypix], Memd[etalin], npix)
+ call adivkd (Memd[etalin], 3600.0d0, Memd[etalin], npix)
+ call alimd (Memd[etalin], npix, etamin, etamax)
+
+ # Evalute the distortion surfaces, convert the results from arcseconds
+ # to degrees, and compute new distortion surfaces.
+ if (sx2 != NULL) {
+ call dgsvector (sx2, Memd[xpix], Memd[ypix], Memd[dxi], npix)
+ call adivkd (Memd[dxi], 3600.0d0, Memd[dxi], npix)
+ call dgsinit (nsx2, function, xxorder, xyorder, xxterms,
+ ximin, ximax, etamin, etamax)
+ call dgsfit (nsx2, Memd[xilin], Memd[etalin], Memd[dxi],
+ Memd[wgt], npix, WTS_UNIFORM, ier)
+ call cc_gsencode (mw, nsx2, xiname, xiaxis)
+ } else
+ nsx2 = NULL
+ if (sy2 != NULL) {
+ call dgsvector (sy2, Memd[xpix], Memd[ypix], Memd[deta], npix)
+ call adivkd (Memd[deta], 3600.0d0, Memd[deta], npix)
+ call dgsinit (nsy2, function, yxorder, yyorder, yxterms,
+ ximin, ximax, etamin, etamax)
+ call dgsfit (nsy2, Memd[xilin], Memd[etalin], Memd[deta],
+ Memd[wgt], npix, WTS_UNIFORM, ier)
+ call cc_gsencode (mw, nsy2, etaname, etaaxis)
+ } else
+ nsy2 = NULL
+
+ # Store the string in the mcs structure in the format of a wcs
+ # attribute.
+
+ # Free the new surfaces.
+ if (nsx2 != NULL)
+ call dgsfree (nsx2)
+ if (nsy2 != NULL)
+ call dgsfree (nsy2)
+
+ call sfree (sp)
+end
+
+
+# CC_GSENCODE -- Encode the surface in an mwcs attribute.
+
+procedure cc_gsencode (mw, gs, atname, axis)
+
+pointer mw #I pointer to the mwcs structure
+pointer gs #I pointer to the surface to be encoded
+char atname[ARB] #I attribute name for the encoded surface
+int axis #I axis for which the encode surface is encoded
+
+int i, op, nsave, szatstr, szpar
+pointer sp, coeff, par, atstr
+int dgsgeti(), strlen(), gstrcpy()
+
+begin
+ nsave = dgsgeti (gs, GSNSAVE)
+ call smark (sp)
+ call salloc (coeff, nsave, TY_DOUBLE)
+ call salloc (par, SZ_LINE, TY_CHAR)
+ call dgssave (gs, Memd[coeff])
+
+ szatstr = SZ_LINE
+ call malloc (atstr, szatstr, TY_CHAR)
+ op = 0
+ do i = 1, nsave {
+ call sprintf (Memc[par], SZ_LINE, "%g ")
+ call pargd (Memd[coeff+i-1])
+ szpar = strlen (Memc[par])
+ if (szpar > (szatstr - op)) {
+ szatstr = szatstr + SZ_LINE
+ call realloc (atstr, szatstr, TY_CHAR)
+ }
+ op = op + gstrcpy (Memc[par], Memc[atstr+op], SZ_LINE)
+
+ }
+
+ call mw_swattrs (mw, axis, atname, Memc[atstr])
+ call mfree (atstr, TY_CHAR)
+ call sfree (sp)
+end
+
+
+
diff --git a/pkg/images/imcoords/src/ccstd.x b/pkg/images/imcoords/src/ccstd.x
new file mode 100644
index 00000000..319d18ba
--- /dev/null
+++ b/pkg/images/imcoords/src/ccstd.x
@@ -0,0 +1,252 @@
+include <mach.h>
+include <math.h>
+include <math/gsurfit.h>
+include <pkg/skywcs.h>
+
+# CC_INIT_STD -- Get the parameter values relevant to the transformation from
+# the cl or the database file.
+#
+procedure cc_init_std (dt, record, geometry, lngunits, latunits, sx1,
+ sy1, sx2, sy2, mw, coo)
+
+pointer dt #I pointer to database file produced by geomap
+char record[ARB] #I the name of the database record
+int geometry #I the type of geometry to be computed
+int lngunits #I the input ra / longitude units
+int latunits #I the input dec / latitude units
+pointer sx1, sy1 #O pointers to the linear x and y surfaces
+pointer sx2, sy2 #O pointers to the x and y distortion surfaces
+pointer mw #O pointer to the mwcs structure
+pointer coo #O pointer to the coordinate structure
+
+double lngref, latref
+int recstat, proj
+pointer sp, projstr, projpars
+int cc_dtrecord(), strdic()
+pointer cc_celwcs()
+
+begin
+ call smark (sp)
+ call salloc (projstr, SZ_FNAME, TY_CHAR)
+ call salloc (projpars, SZ_LINE, TY_CHAR)
+
+ if (dt == NULL) {
+
+ call cc_rinit (lngunits, latunits, sx1, sy1, mw, coo)
+ sx2 = NULL
+ sy2 = NULL
+
+ } else {
+
+ recstat = cc_dtrecord (dt, record, geometry, coo, Memc[projpars],
+ lngref, latref, sx1, sy1, sx2, sy2)
+ if (recstat == ERR) {
+ coo = NULL
+ sx1 = NULL
+ sy1 = NULL
+ sx2 = NULL
+ sy2 = NULL
+ mw = NULL
+ } else {
+ call sscan (Memc[projpars])
+ call gargwrd (Memc[projstr], SZ_FNAME)
+ proj = strdic (Memc[projstr], Memc[projstr], SZ_FNAME,
+ WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projpars] = EOS
+ mw = cc_celwcs (coo, Memc[projpars], lngref, latref)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# CC_FREE_STD -- Free the previously defined transformation.
+
+procedure cc_free_std (sx1, sy1, sx2, sy2, mw, coo)
+
+pointer sx1, sy1 #U pointers to the linear x and y surfaces
+pointer sx2, sy2 #U pointers to the x and y distortion surfaces
+pointer mw #U pointer to the mwcs structure
+pointer coo #U pointer to the celestial coordinate structure
+
+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)
+ if (mw != NULL)
+ call mw_close (mw)
+ if (coo != NULL)
+ call sk_close (coo)
+end
+
+
+# CC_RINIT -- Compute the required wcs structure from the input parameters.
+
+procedure cc_rinit (lngunits, latunits, sx1, sy1, mw, coo)
+
+int lngunits #I the input ra / longitude units
+int latunits #I the input dec / latitude units
+pointer sx1 #O pointer to the linear x coordinate surface
+pointer sy1 #O pointer to the linear y coordinate surface
+pointer mw #O pointer to the mwcs structure
+pointer coo #O pointer to the celestial coordinate structure
+
+double xref, yref, xscale, yscale, xrot, yrot, lngref, latref
+int coostat, proj, tlngunits, tlatunits, pfd
+pointer sp, projstr
+double clgetd()
+double dgseval()
+int sk_decwcs(), sk_stati(), strdic(), open()
+pointer cc_celwcs(), cc_rdproj()
+errchk open()
+
+begin
+ # Allocate some workin space.
+ call smark (sp)
+ call salloc (projstr, SZ_LINE, TY_CHAR)
+
+ # Get the reference point pixel coordinates.
+ xref = clgetd ("xref")
+ if (IS_INDEFD(xref))
+ xref = 0.0d0
+ yref = clgetd ("yref")
+ if (IS_INDEFD(yref))
+ yref = 0.0d0
+
+ # Get the scale factors.
+ xscale = clgetd ("xmag")
+ if (IS_INDEFD(xscale))
+ xscale = 1.0d0
+ yscale = clgetd ("ymag")
+ if (IS_INDEFD(yscale))
+ yscale = 1.0d0
+
+ # Get the rotation angles.
+ xrot = clgetd ("xrotation")
+ if (IS_INDEFD(xrot))
+ xrot = 0.0d0
+ xrot = -DEGTORAD(xrot)
+ yrot = clgetd ("yrotation")
+ if (IS_INDEFD(yrot))
+ yrot = 0.0d0
+ yrot = -DEGTORAD(yrot)
+
+ # Initialize the linear part of the solution.
+ call dgsinit (sx1, GS_POLYNOMIAL, 2, 2, NO, double (-MAX_REAL),
+ double (MAX_REAL), double (-MAX_REAL), double (MAX_REAL))
+ call dgsinit (sy1, GS_POLYNOMIAL, 2, 2, NO, double (-MAX_REAL),
+ double (MAX_REAL), double (-MAX_REAL), double (MAX_REAL))
+ call geo_rotmagd (sx1, sy1, xscale, yscale, xrot, yrot)
+ call geo_xyshiftd (sx1, sy1, -dgseval (sx1, xref, yref),
+ -dgseval (sy1, xref, yref))
+
+ lngref = clgetd ("lngref")
+ if (IS_INDEFD(lngref))
+ lngref = 0.0d0
+ latref = clgetd ("latref")
+ if (IS_INDEFD(latref))
+ latref = 0.0d0
+
+ coostat = sk_decwcs ("j2000", mw, coo, NULL)
+ if (coostat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ }
+ if (lngunits <= 0)
+ tlngunits = sk_stati (coo, S_NLNGUNITS)
+ else
+ tlngunits = lngunits
+ call sk_seti (coo, S_NLNGUNITS, tlngunits)
+ if (latunits <= 0)
+ tlatunits = sk_stati (coo, S_NLATUNITS)
+ else
+ tlatunits = latunits
+ call sk_seti (coo, S_NLATUNITS, tlatunits)
+
+ call clgstr ("projection", Memc[projstr], SZ_LINE)
+ iferr {
+ pfd = open (Memc[projstr], READ_ONLY, TEXT_FILE)
+ } then {
+ proj = strdic (Memc[projstr], Memc[projstr], SZ_LINE, WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projstr] = EOS
+ } else {
+ proj = cc_rdproj (pfd, Memc[projstr], SZ_LINE)
+ call close (pfd)
+ }
+ mw = cc_celwcs (coo, Memc[projstr], lngref, latref)
+
+ call sfree (sp)
+end
+
+
+define MAX_NITER 20
+
+# CC_DO_STD -- Transform the coordinates using the full transformation
+# computed by CCMAP.
+
+procedure cc_do_std (x, y, xt, yt, sx1, sy1, sx2, sy2, forward)
+
+double x, y #I initial positions
+double xt, yt #O transformed positions
+pointer sx1, sy1 #I pointer to linear surfaces
+pointer sx2, sy2 #I pointer to distortion surfaces
+bool forward #I forward transform
+
+double f, fx, fy, g, gx, gy, denom, dx, dy
+int niter
+pointer newsx, newsy
+double dgseval()
+
+begin
+
+ if (forward) {
+
+ xt = dgseval (sx1, x, y)
+ if (sx2 != NULL)
+ xt = xt + dgseval (sx2, x, y)
+ yt = dgseval (sy1, x, y)
+ if (sy2 != NULL)
+ yt = yt + dgseval (sy2, x, y)
+
+ } else {
+
+ xt = x / 1.0
+ yt = y / 1.0
+
+ call dgsadd (sx1, sx2, newsx)
+ call dgsadd (sy1, sy2, newsy)
+ niter = 0
+ repeat {
+
+ f = dgseval (newsx, xt, yt) - x
+ call dgsder (newsx, xt, yt, fx, 1, 1, 0)
+ call dgsder (newsx, xt, yt, fy, 1, 0, 1)
+
+ g = dgseval (newsy, xt, yt) - y
+ call dgsder (newsy, xt, yt, gx, 1, 1, 0)
+ call dgsder (newsy, xt, yt, gy, 1, 0, 1)
+
+ denom = fx * gy - fy * gx
+ dx = (-f * gy + g * fy) / denom
+ dy = (-g * fx + f * gx) / denom
+ xt = xt + dx
+ yt = yt + dy
+ if (max (abs (dx), abs (dy), abs(f), abs(g)) < 1.0e-5)
+ break
+
+ niter = niter + 1
+
+ } until (niter >= MAX_NITER)
+
+ call dgsfree (newsx)
+ call dgsfree (newsy)
+ }
+end
diff --git a/pkg/images/imcoords/src/ccxytran.x b/pkg/images/imcoords/src/ccxytran.x
new file mode 100644
index 00000000..537c28f6
--- /dev/null
+++ b/pkg/images/imcoords/src/ccxytran.x
@@ -0,0 +1,740 @@
+include <math.h>
+include <pkg/skywcs.h>
+
+# Define the transform geometries
+define GEO_LINEAR 1
+define GEO_DISTORTION 2
+define GEO_GEOMETRIC 3
+
+# CC_INIT_TRANSFORM -- Get the parameter values relevant to the
+# transformation from the cl.
+
+procedure cc_init_transform (dt, record, geometry, lngunits, latunits, sx1,
+ sy1, sx2, sy2, mw, coo)
+
+pointer dt #I pointer to database file produced by geomap
+char record[ARB] #I the name of the database record
+int geometry #I the type of geometry to be computed
+int lngunits #I the input ra / longitude units
+int latunits #I the input dec / latitude units
+pointer sx1, sy1 #O pointers to the linear x and y surfaces
+pointer sx2, sy2 #O pointers to the x and y distortion surfaces
+pointer mw #O pointer to the mwcs structure
+pointer coo #O pointer to the coordinate structure
+
+double lngref, latref
+int recstat, proj
+pointer sp, projstr, projpars
+int cc_dtrecord(), strdic()
+pointer cc_geowcs(), cc_celwcs()
+
+begin
+ call smark (sp)
+ call salloc (projstr, SZ_FNAME, TY_CHAR)
+ call salloc (projpars, SZ_LINE, TY_CHAR)
+
+ if (dt == NULL) {
+
+ sx1 = NULL
+ sy1 = NULL
+ sx2 = NULL
+ sy2 = NULL
+ call cc_linit (lngunits, latunits, mw, coo)
+
+ } else {
+
+ recstat = cc_dtrecord (dt, record, geometry, coo, Memc[projpars],
+ lngref, latref, sx1, sy1, sx2, sy2)
+ if (recstat == ERR) {
+ coo = NULL
+ sx1 = NULL
+ sy1 = NULL
+ sx2 = NULL
+ sy2 = NULL
+ mw = NULL
+ } else {
+ call sscan (Memc[projpars])
+ call gargwrd (Memc[projstr], SZ_FNAME)
+ proj = strdic (Memc[projstr], Memc[projstr], SZ_FNAME,
+ WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projpars] = EOS
+ if (sx2 == NULL && sy2 == NULL)
+ mw = cc_geowcs (coo, Memc[projpars], lngref, latref,
+ sx1, sy1, false)
+ else
+ mw = cc_celwcs (coo, Memc[projpars], lngref, latref)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# CC_FREE_TRANSFORM -- Free the previously defined transformation.
+
+procedure cc_free_transform (sx1, sy1, sx2, sy2, mw, coo)
+
+pointer sx1, sy1 #U pointers to the linear x and y surfaces
+pointer sx2, sy2 #U pointers to the x and y distortion surfaces
+pointer mw #U pointer to the mwcs structure
+pointer coo #U pointer to the celestial coordinate structure
+
+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)
+ if (mw != NULL)
+ call mw_close (mw)
+ if (coo != NULL)
+ call sk_close (coo)
+end
+
+
+# CC_LINIT -- Compute the required wcs structure from the input parameters.
+
+procedure cc_linit (lngunits, latunits, mw, coo)
+
+int lngunits #I the input ra / longitude units
+int latunits #I the input dec / latitude units
+pointer mw #O pointer to the mwcs structure
+pointer coo #O pointer to the celestial coordinate structure
+
+double xref, yref, xscale, yscale, xrot, yrot, lngref, latref
+int coostat, proj, tlngunits, tlatunits, pfd
+pointer sp, projstr
+double clgetd()
+int sk_decwcs(), sk_stati(), open(), strdic(), cc_rdproj()
+pointer cc_mkwcs()
+errchk open()
+
+begin
+ # Allocate some workin space.
+ call smark (sp)
+ call salloc (projstr, SZ_LINE, TY_CHAR)
+
+ # Get the reference point pixel coordinates.
+ xref = clgetd ("xref")
+ if (IS_INDEFD(xref))
+ xref = 0.0d0
+ yref = clgetd ("yref")
+ if (IS_INDEFD(yref))
+ yref = 0.0d0
+
+ xscale = clgetd ("xmag")
+ if (IS_INDEFD(xscale))
+ xscale = 1.0d0
+ yscale = clgetd ("ymag")
+ if (IS_INDEFD(yscale))
+ yscale = 1.0d0
+
+ xrot = clgetd ("xrotation")
+ if (IS_INDEFD(xrot))
+ xrot = 0.0d0
+ yrot = clgetd ("yrotation")
+ if (IS_INDEFD(yrot))
+ yrot = 0.0d0
+
+ lngref = clgetd ("lngref")
+ if (IS_INDEFD(lngref))
+ lngref = 0.0d0
+ latref = clgetd ("latref")
+ if (IS_INDEFD(latref))
+ latref = 0.0d0
+
+ coostat = sk_decwcs ("j2000", mw, coo, NULL)
+ if (coostat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ }
+ if (lngunits <= 0)
+ tlngunits = sk_stati (coo, S_NLNGUNITS)
+ else
+ tlngunits = lngunits
+ call sk_seti (coo, S_NLNGUNITS, tlngunits)
+ if (latunits <= 0)
+ tlatunits = sk_stati (coo, S_NLATUNITS)
+ else
+ tlatunits = latunits
+ call sk_seti (coo, S_NLATUNITS, tlatunits)
+
+ call clgstr ("projection", Memc[projstr], SZ_LINE)
+ iferr {
+ pfd = open (Memc[projstr], READ_ONLY, TEXT_FILE)
+ } then {
+ proj = strdic (Memc[projstr], Memc[projstr], SZ_LINE, WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projstr] = EOS
+ } else {
+ proj = cc_rdproj (pfd, Memc[projstr], SZ_LINE)
+ call close (pfd)
+ }
+
+
+ mw = cc_mkwcs (coo, Memc[projstr], lngref, latref, xref, yref,
+ xscale, yscale, xrot, yrot, false)
+
+ call sfree (sp)
+end
+
+
+# CC_DTRECORD -- Read the transform from the database records written by
+# CCMAP.
+
+int procedure cc_dtrecord (dt, record, geometry, coo, projection,
+ lngref, latref, sx1, sy1, sx2, sy2)
+
+pointer dt #I pointer to the database
+char record[ARB] #I the database records to be read
+int geometry #I the transform geometry
+pointer coo #O pointer to the coordinate structure
+char projection[ARB] #O the sky projection geometry
+double lngref, latref #O the reference point world coordinates
+pointer sx1, sy1 #O pointer to the linear x and y fits
+pointer sx2, sy2 #O pointer to the distortion x and y fits
+
+int i, op, ncoeff, junk, rec, coostat, lngunits, latunits
+pointer mw, xcoeff, ycoeff, sp, projpar, projvalue
+double dtgetd()
+int dtlocate(), dtgeti(), dtscan(), sk_decwcs(), strdic(), strlen()
+int gstrcpy()
+errchk dgsrestore(), dtgstr(), dtdgetd(), dtgeti()
+
+begin
+ # Locate the appropriate records.
+ iferr (rec = dtlocate (dt, record))
+ return (ERR)
+
+ # Open the coordinate structure.
+ iferr (call dtgstr (dt, rec, "coosystem", projection, SZ_FNAME))
+ return (ERR)
+ coostat = sk_decwcs (projection, mw, coo, NULL)
+ if (coostat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ projection[1] = EOS
+ return (ERR)
+ }
+
+ # Get the reference point units.
+ iferr (call dtgstr (dt, rec, "lngunits", projection, SZ_FNAME))
+ return (ERR)
+ lngunits = strdic (projection, projection, SZ_FNAME, SKY_LNG_UNITLIST)
+ if (lngunits > 0)
+ call sk_seti (coo, S_NLNGUNITS, lngunits)
+ iferr (call dtgstr (dt, rec, "latunits", projection, SZ_FNAME))
+ return (ERR)
+ latunits = strdic (projection, projection, SZ_FNAME, SKY_LAT_UNITLIST)
+ if (latunits > 0)
+ call sk_seti (coo, S_NLATUNITS, latunits)
+
+ # Get the reference point.
+ iferr (call dtgstr (dt, rec, "projection", projection, SZ_FNAME))
+ return (ERR)
+ iferr (lngref = dtgetd (dt, rec, "lngref"))
+ return (ERR)
+ iferr (latref = dtgetd (dt, rec, "latref"))
+ return (ERR)
+
+ # Read in the coefficients.
+ iferr (ncoeff = dtgeti (dt, rec, "surface1"))
+ return (ERR)
+ call malloc (xcoeff, ncoeff, TY_DOUBLE)
+ call malloc (ycoeff, ncoeff, TY_DOUBLE)
+ do i = 1, ncoeff {
+ junk = dtscan(dt)
+ call gargd (Memd[xcoeff+i-1])
+ call gargd (Memd[ycoeff+i-1])
+ }
+
+ # Restore the fit.
+ call dgsrestore (sx1, Memd[xcoeff])
+ call dgsrestore (sy1, Memd[ycoeff])
+
+ # Get distortion part of fit.
+ ncoeff = dtgeti (dt, rec, "surface2")
+ if (ncoeff > 0 && (geometry == GEO_GEOMETRIC ||
+ geometry == GEO_DISTORTION)) {
+ call realloc (xcoeff, ncoeff, TY_DOUBLE)
+ call realloc (ycoeff, ncoeff, TY_DOUBLE)
+ do i = 1, ncoeff {
+ junk = dtscan (dt)
+ call gargd (Memd[xcoeff+i-1])
+ call gargd (Memd[ycoeff+i-1])
+ }
+
+ # Restore distortion part of fit.
+ iferr {
+ call dgsrestore (sx2, Memd[xcoeff])
+ } then {
+ call mfree (sx2, TY_STRUCT)
+ sx2 = NULL
+ }
+ iferr {
+ call dgsrestore (sy2, Memd[ycoeff])
+ } then {
+ call mfree (sy2, TY_STRUCT)
+ sy2 = NULL
+ }
+
+ } else {
+ sx2 = NULL
+ sy2 = NULL
+ }
+
+ # Get the projection parameters if any.
+ call smark (sp)
+ call salloc (projpar, SZ_FNAME, TY_CHAR)
+ call salloc (projvalue, SZ_FNAME, TY_CHAR)
+ op = strlen (projection) + 1
+ do i = 0, 9 {
+ call sprintf (Memc[projpar], SZ_FNAME, "projp%d")
+ call pargi (i)
+ iferr (call dtgstr (dt, rec, Memc[projpar], Memc[projvalue],
+ SZ_FNAME))
+ next
+ op = op + gstrcpy (" ", projection[op], SZ_LINE - op + 1)
+ op = op + gstrcpy (Memc[projpar], projection[op],
+ SZ_LINE - op + 1)
+ op = op + gstrcpy (" = ", projection[op], SZ_LINE - op + 1)
+ op = op + gstrcpy (Memc[projvalue], projection[op],
+ SZ_LINE - op + 1)
+ }
+ call sfree (sp)
+
+
+ call mfree (xcoeff, TY_DOUBLE)
+ call mfree (ycoeff, TY_DOUBLE)
+
+ return (OK)
+end
+
+
+define MAX_NITER 20
+
+# CC_DO_TRANSFORM -- Transform the coordinates using the full transformation
+# computed by CCMAP and the MWCS celestial coordinate wcs.
+
+procedure cc_do_transform (x, y, xt, yt, ct, sx1, sy1, sx2, sy2, forward)
+
+double x, y #I initial positions
+double xt, yt #O transformed positions
+pointer ct #I pointer to the mwcs transform
+pointer sx1, sy1 #I pointer to linear surfaces
+pointer sx2, sy2 #I pointer to distortion surfaces
+bool forward #I forward transform
+
+double xm, ym, f, fx, fy, g, gx, gy, denom, dx, dy
+int niter
+pointer sumsx, sumsy, newsx, newsy
+double dgseval()
+
+begin
+
+ if (forward) {
+
+ xm = dgseval (sx1, x, y)
+ if (sx2 != NULL)
+ xm = xm + dgseval (sx2, x, y)
+ ym = dgseval (sy1, x, y)
+ if (sy2 != NULL)
+ ym = ym + dgseval (sy2, x, y)
+ xm = xm / 3600.0d0
+ ym = ym / 3600.0d0
+
+ call mw_c2trand (ct, xm, ym, xt, yt)
+
+ } else {
+
+ # Use a value of 1.0 for an initial guess at the plate scale.
+ call mw_c2trand (ct, x, y, xm, ym)
+ xm = xm * 3600.0d0
+ ym = ym * 3600.0d0
+
+ call dgsadd (sx1, sx2, sumsx)
+ call dgsadd (sy1, sy2, sumsy)
+
+ niter = 0
+ xt = xm
+ yt = ym
+ repeat {
+
+ if (niter == 0) {
+ newsx = sx1
+ newsy = sy1
+ } else if (niter == 1) {
+ newsx = sumsx
+ newsy = sumsy
+ }
+
+ f = dgseval (newsx, xt, yt) - xm
+ call dgsder (newsx, xt, yt, fx, 1, 1, 0)
+ call dgsder (newsx, xt, yt, fy, 1, 0, 1)
+
+ g = dgseval (newsy, xt, yt) - ym
+ call dgsder (newsy, xt, yt, gx, 1, 1, 0)
+ call dgsder (newsy, xt, yt, gy, 1, 0, 1)
+
+ denom = fx * gy - fy * gx
+ if (denom == 0.0d0)
+ break
+ dx = (-f * gy + g * fy) / denom
+ dy = (-g * fx + f * gx) / denom
+ xt = xt + dx
+ yt = yt + dy
+ if (max (abs (dx), abs (dy), abs(f), abs(g)) < 1.0e-5)
+ break
+
+ niter = niter + 1
+
+ } until (niter >= MAX_NITER)
+
+ call dgsfree (sumsx)
+ call dgsfree (sumsy)
+ }
+end
+
+define NEWCD Memd[cd+(($2)-1)*ndim+($1)-1]
+
+# CC_MKWCS -- Compute the wcs from the user parameters.
+
+pointer procedure cc_mkwcs (coo, projection, lngref, latref, xref, yref,
+ xscale, yscale, xrot, yrot, transpose)
+
+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
+
+int ndim
+double tlngref, tlatref
+pointer sp, axes, ltm, ltv, r, w, cd, mw, projstr, projpars, wpars
+int sk_stati()
+pointer mw_open()
+
+begin
+ # Open the wcs.
+ ndim = 2
+ mw = mw_open (NULL, ndim)
+
+ # Allocate working space.
+ 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 (axes, ndim, TY_INT)
+ call salloc (ltm, ndim * ndim, TY_DOUBLE)
+ call salloc (ltv, ndim, TY_DOUBLE)
+ call salloc (r, ndim, TY_DOUBLE)
+ call salloc (w, ndim, TY_DOUBLE)
+ call salloc (cd, ndim * ndim, TY_DOUBLE)
+
+ # Set the wcs.
+ iferr (call mw_newsystem (mw, "image", ndim))
+ ;
+
+ # Set the axes.
+ Memi[axes] = 1
+ Memi[axes+1] = 2
+
+ # Set the axes and projection type.
+ if (projection[1] == EOS) {
+ call mw_swtype (mw, 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 (mw, Memi[axes], ndim, Memc[projstr], Memc[wpars])
+ }
+
+ # 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] = tlngref
+ Memd[w+1] = tlatref
+ } else {
+ Memd[w+1] = tlngref
+ Memd[w] = tlatref
+ }
+
+ # Compute the reference point pixel coordinates.
+ Memd[r] = xref
+ Memd[r+1] = yref
+
+ # Compute the new CD matrix.
+ if (! transpose) {
+ NEWCD(1,1) = xscale * cos (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(2,1) = -yscale * sin (DEGTORAD(yrot)) / 3600.0d0
+ NEWCD(1,2) = xscale * sin (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(2,2) = yscale * cos (DEGTORAD(yrot)) / 3600.0d0
+ } else {
+ NEWCD(1,1) = xscale * sin (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(2,1) = yscale * cos (DEGTORAD(yrot)) / 3600.0d0
+ NEWCD(1,2) = xscale * cos (DEGTORAD(xrot)) / 3600.0d0
+ NEWCD(2,2) = -yscale * sin (DEGTORAD(yrot)) / 3600.0d0
+ }
+
+ # Compute the Lterm.
+ call aclrd (Memd[ltv], ndim)
+ call mw_mkidmd (Memd[ltm], ndim)
+
+ # Store the wcs.
+ call mw_sltermd (mw, Memd[ltm], Memd[ltv], ndim)
+ call mw_swtermd (mw, Memd[r], Memd[w], Memd[cd], ndim)
+
+ call sfree (sp)
+
+ return (mw)
+end
+
+# CC_GEOWCS -- Create the wcs from the geometric transformation computed
+# by CCMAP
+
+pointer procedure cc_geowcs (coo, projection, lngref, latref, sx1, sy1,
+ transpose)
+
+pointer coo #I the pointer to the coordinate structure
+char projection[ARB] #I the sky projection geometry
+double lngref, latref #I the coordinates of the reference point
+pointer sx1, sy1 #I pointer to linear surfaces
+bool transpose #I transpose the wcs
+
+int ndim
+double xshift, yshift, a, b, c, d, denom, xpix, ypix, tlngref, tlatref
+pointer mw, sp, projstr, projpars, wpars, r, w, cd, ltm, ltv, axes
+int sk_stati()
+pointer mw_open()
+
+begin
+ ndim = 2
+ mw = mw_open (NULL, ndim)
+
+ # 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 (axes, 2, TY_INT)
+ 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)
+
+ # Set the wcs.
+ iferr (call mw_newsystem (mw, "image", ndim))
+ ;
+
+ # Set the axes.
+ Memi[axes] = 1
+ Memi[axes+1] = 2
+
+ # Set the axes and projection type.
+ if (projection[1] == EOS) {
+ call mw_swtype (mw, 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 (mw, Memi[axes], ndim, Memc[projstr], Memc[wpars])
+ }
+
+ # Compute the new referemce point.
+ 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] = tlngref
+ Memd[w+1] = tlatref
+ } else {
+ Memd[w] = tlatref
+ Memd[w+1] = tlngref
+ }
+
+
+ # Fetch the linear coefficients of the fit.
+ call geo_gcoeffd (sx1, sy1, xshift, yshift, a, b, c, d)
+
+ # Compute the new reference pixel.
+ denom = a * d - c * b
+ if (denom == 0.0d0)
+ xpix = INDEFD
+ else
+ xpix = (b * yshift - d * xshift) / denom
+ if (denom == 0.0d0)
+ ypix = INDEFD
+ else
+ ypix = (c * xshift - a * yshift) / denom
+ Memd[r] = xpix
+ Memd[r+1] = ypix
+
+ # Compute the new CD matrix.
+ if (! transpose) {
+ NEWCD(1,1) = a / 3600.0d0
+ NEWCD(1,2) = c / 3600.0d0
+ NEWCD(2,1) = b / 3600.0d0
+ NEWCD(2,2) = d / 3600.0d0
+ } else {
+ NEWCD(1,1) = c / 3600.0d0
+ NEWCD(1,2) = a / 3600.0d0
+ NEWCD(2,1) = d / 3600.0d0
+ NEWCD(2,2) = b / 3600.0d0
+ }
+
+ # Compute the Lterm.
+ call aclrd (Memd[ltv], ndim)
+ call mw_mkidmd (Memd[ltm], ndim)
+
+ # Recompute and store the new wcs if update is enabled.
+ call mw_sltermd (mw, Memd[ltm], Memd[ltv], ndim)
+ call mw_swtermd (mw, Memd[r], Memd[w], Memd[cd], ndim)
+
+ call sfree (sp)
+
+ return (mw)
+end
+
+
+
+
+# CC_CELWCS -- Create a wcs which compute the projection part of the
+# transformation only
+
+pointer procedure cc_celwcs (coo, projection, lngref, latref)
+
+pointer coo #I the pointer to the coordinate structure
+char projection[ARB] #I the sky projection geometry
+double lngref, latref #I the position of the reference point.
+
+int ndim
+pointer sp, projstr, projpars, wpars, ltm, ltv, cd, r, w, axes, mw
+int sk_stati()
+pointer mw_open()
+
+begin
+ # Open the wcs.
+ ndim = 2
+ mw = mw_open (NULL, ndim)
+
+ # Allocate working space.
+ 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 (ltm, ndim * ndim, TY_DOUBLE)
+ call salloc (ltv, ndim, TY_DOUBLE)
+ call salloc (cd, ndim * ndim, TY_DOUBLE)
+ call salloc (r, ndim, TY_DOUBLE)
+ call salloc (w, ndim, TY_DOUBLE)
+ call salloc (axes, 2, TY_INT)
+
+
+ # Set the wcs.
+ iferr (call mw_newsystem (mw, "image", ndim))
+ ;
+
+ # Set the axes and projection type.
+ Memi[axes] = 1
+ Memi[axes+1] = 2
+ if (projection[1] == EOS) {
+ call mw_swtype (mw, 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 (mw, Memi[axes], ndim, Memc[projstr], Memc[wpars])
+ }
+
+ # Set the lterm.
+ call mw_mkidmd (Memd[ltm], ndim)
+ call aclrd (Memd[ltv], ndim)
+ call mw_sltermd (mw, Memd[ltm], Memd[ltv], ndim)
+
+ # Set the wterm.
+ call mw_mkidmd (Memd[cd], ndim)
+ call aclrd (Memd[r], ndim)
+ switch (sk_stati(coo, S_NLNGUNITS)) {
+ case SKY_DEGREES:
+ Memd[w] = lngref
+ case SKY_RADIANS:
+ Memd[w] = RADTODEG(lngref)
+ case SKY_HOURS:
+ Memd[w] = 15.0d0 * lngref
+ default:
+ Memd[w] = lngref
+ }
+ switch (sk_stati(coo, S_NLATUNITS)) {
+ case SKY_DEGREES:
+ Memd[w+1] = latref
+ case SKY_RADIANS:
+ Memd[w+1] = RADTODEG(latref)
+ case SKY_HOURS:
+ Memd[w+1] = 15.0d0 * latref
+ default:
+ Memd[w+1] = latref
+ }
+ call mw_swtermd (mw, Memd[r], Memd[w], Memd[cd], ndim)
+
+ call sfree (sp)
+
+ return (mw)
+end
+
+
diff --git a/pkg/images/imcoords/src/healpix.x b/pkg/images/imcoords/src/healpix.x
new file mode 100644
index 00000000..1156607c
--- /dev/null
+++ b/pkg/images/imcoords/src/healpix.x
@@ -0,0 +1,492 @@
+include <math.h>
+
+define MTYPES "|nest|ring|"
+define NEST 1
+define RING 2
+
+define NS_MAX 8192
+define TWOTHIRDS 0.66666666667
+
+
+# ANG2PIX -- Compute the HEALPix map row from a spherical coordinate.
+#
+# It is up to the caller to know the coordinate type, map type, and
+# resolution for the map.
+#
+# The returned row is 1 indexed.
+
+procedure ang2row (row, lng, lat, mtype, nside)
+
+int row #O Table row
+double lng #I Longitude (deg)
+double lat #I Latitude (deg)
+int mtype #I HEALPix map type
+int nside #I Resolution parameter
+
+int ipix
+double phi, theta
+errchk ang2pix_nest, ang2pix_ring
+
+begin
+ # Check parameters and call appropriate procedure.
+
+ if (nside < 1 || nside > NS_MAX)
+ call error (1, "nside out of range")
+
+ if (lat < -90D0 || lat > 90D0)
+ call error (2, "latitude out of range")
+
+ phi = DEGTORAD (lng)
+ theta = DEGTORAD (90D0 - lat)
+
+ switch (mtype) {
+ case NEST:
+ call ang2pix_nest (nside, theta, phi, ipix)
+ case RING:
+ call ang2pix_ring (nside, theta, phi, ipix)
+ default:
+ call error (3, "unknown HEALPix map type")
+ }
+
+ row = ipix + 1
+end
+
+
+# PIX2ANG -- Compute spherical coordinate from HEALPix map row.
+#
+# It is up to the caller to know the coordinate type, map type, and
+# resolution for the map.
+
+procedure row2ang (row, lng, lat, mtype, nside)
+
+int row #I Table row (1 indexed)
+double lng #O Longitude (deg)
+double lat #O Latitude (deg)
+int mtype #I HEALPix map type
+int nside #I Resolution parameter
+
+int ipix
+double phi, theta
+errchk pix2ang_nest, pix2ang_ring
+
+begin
+ # Check input parameters and call appropriate procedure.
+
+ if (nside < 1 || nside > NS_MAX)
+ call error (1, "nside out of range")
+
+ if (row < 1 || row > 12*nside*nside)
+ call error (1, "row out of range")
+
+ ipix = row - 1
+
+ switch (mtype) {
+ case NEST:
+ call pix2ang_nest (nside, ipix, theta, phi)
+ case RING:
+ call pix2ang_ring (nside, ipix, theta, phi)
+ default:
+ call error (3, "unknown HEALPix map type")
+ }
+
+ lng = RADTODEG (phi)
+ lat = 90D0 - RADTODEG (theta)
+end
+
+
+# The following routines are SPP translations of the HEALPix software from
+# the authors identified below. If it matters, the C version was used
+# though the translation is not necessarily exact. Comments were
+# largely removed.
+#
+# I'm not sure if the arguments to the floor function in the original
+# can be negative. Assuming not I just do an integer truncation.
+
+# -----------------------------------------------------------------------------
+#
+# Copyright (C) 1997-2008 Krzysztof M. Gorski, Eric Hivon,
+# Benjamin D. Wandelt, Anthony J. Banday,
+# Matthias Bartelmann,
+# Reza Ansari & Kenneth M. Ganga
+#
+#
+# This file is part of HEALPix.
+#
+# HEALPix is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# HEALPix is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with HEALPix; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+#
+# For more information about HEALPix see http://healpix.jpl.nasa.gov
+#
+#-----------------------------------------------------------------------------
+
+
+# ANG2PIX_NEST -- Compute HEALPix index for a nested map.
+
+procedure ang2pix_nest (nside, theta, phi, ipix)
+
+int nside #I Resolution parameter
+double theta #I Latitude (rad from pole)
+double phi #I Longitude (rad)
+int ipix #O HEALPix index
+
+double z, za, tt, tp, tmp
+int face_num, jp, jm
+long ifp, ifm
+int ix, iy, ix_low, ix_hi, iy_low, iy_hi, ipf, ntt
+int x2pix[128], y2pix[128]
+int setup_done
+
+errchk mk_xy2pix
+
+data setup_done/NO/
+
+begin
+ if (setup_done == NO) {
+ call mk_xy2pix (x2pix, y2pix)
+ setup_done = YES
+ }
+
+ z = cos (theta)
+ za = abs (z)
+ if (phi >= TWOPI)
+ phi = phi - TWOPI
+ if (phi < 0.)
+ phi = phi + TWOPI
+ tt = phi / HALFPI
+
+ if (za <= TWOTHIRDS) {
+ jp = int (NS_MAX * (0.5 + tt - z * 0.75))
+ jm = int (NS_MAX * (0.5 + tt + z * 0.75))
+
+ ifp = jp / NS_MAX
+ ifm = jm / NS_MAX
+
+ if (ifp==ifm)
+ face_num = mod (ifp, 4) + 4
+ else if (ifp<ifm)
+ face_num = mod (ifp, 4)
+ else
+ face_num = mod (ifm, 4) + 8
+
+ ix = mod (jm, NS_MAX)
+ iy = NS_MAX - mod (jp, NS_MAX) - 1
+ } else {
+ ntt = int (tt)
+ if (ntt >= 4)
+ ntt = 3
+ tp = tt - ntt
+ tmp = sqrt (3. * (1. - za))
+
+ jp = int (NS_MAX * tp * tmp)
+ jm = int (NS_MAX * (1. - tp) * tmp)
+ jp = min (jp, NS_MAX-1)
+ jm = min (jm, NS_MAX-1)
+
+ if (z >= 0) {
+ face_num = ntt
+ ix = NS_MAX - jm - 1
+ iy = NS_MAX - jp - 1
+ } else {
+ face_num = ntt + 8
+ ix = jp
+ iy = jm
+ }
+ }
+
+ ix_low = mod (ix, 128) + 1
+ ix_hi = ix / 128 + 1
+ iy_low = mod (iy, 128) + 1
+ iy_hi = iy / 128 + 1
+
+ ipf = (x2pix[ix_hi] + y2pix[iy_hi]) * (128 * 128) +
+ (x2pix[ix_low] + y2pix[iy_low])
+ ipf = ipf / (NS_MAX/nside)**2
+ ipix = ipf + face_num * nside**2
+end
+
+
+# ANG2PIX_RING -- Compute HEALPix index for a ring map.
+
+procedure ang2pix_ring (nside, theta, phi, ipix)
+
+int nside #I Resolution parameter
+double theta #I Latitude (rad from pole)
+double phi #I Longitude (rad)
+int ipix #O HEALPix index
+
+int nl2, nl4, ncap, npix, jp, jm, ipix1
+double z, za, tt, tp, tmp
+int ir, ip, kshift
+
+begin
+ z = cos (theta)
+ za = abs (z)
+ if ( phi >= TWOPI)
+ phi = phi - TWOPI
+ if (phi < 0.)
+ phi = phi + TWOPI
+ tt = phi / HALFPI
+
+ nl2 = 2 * nside
+ nl4 = 4 * nside
+ ncap = nl2 * (nside - 1)
+ npix = 12 * nside * nside
+
+ if (za <= TWOTHIRDS) {
+
+ jp = int (nside * (0.5 + tt - z * 0.75))
+ jm = int (nside * (0.5 + tt + z * 0.75))
+
+ ir = nside + 1 + jp - jm
+ kshift = 0
+ if (mod (ir,2) == 0)
+ kshift = 1
+
+ ip = int ((jp + jm - nside + kshift + 1) / 2) + 1
+ if (ip > nl4)
+ ip = ip - nl4
+
+ ipix1 = ncap + nl4 * (ir - 1) + ip
+ } else {
+
+ tp = tt - int (tt)
+ tmp = sqrt (3. * (1. - za))
+
+ jp = int (nside * tp * tmp)
+ jm = int (nside * (1. - tp) * tmp)
+
+ ir = jp + jm + 1
+ ip = int (tt * ir) + 1
+ if (ip > 4*ir)
+ ip = ip - 4 * ir
+
+ ipix1 = 2 * ir * (ir - 1) + ip
+ if (z<=0.) {
+ ipix1 = npix - 2 * ir * (ir + 1) + ip
+ }
+ }
+ ipix = ipix1 - 1
+end
+
+
+# PIX2ANG_NEST -- Translate HEALpix nested row to spherical coordinates.
+
+procedure pix2ang_nest (nside, ipix, theta, phi)
+
+int nside #I Resolution parameter
+int ipix #I HEALPix index
+double theta #O Latitude (rad from pole)
+double phi #O Longitude (rad)
+
+int npface, face_num
+int ipf, ip_low, ip_trunc, ip_med, ip_hi
+int ix, iy, jrt, jr, nr, jpt, jp, kshift, nl4
+double z, fn, fact1, fact2
+
+int pix2x[1024], pix2y[1024]
+
+int jrll[12], jpll[12], setup_done
+data jrll/2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4/
+data jpll/1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7/
+data setup_done/NO/
+
+begin
+ if (setup_done == NO) {
+ call mk_pix2xy (pix2x,pix2y)
+ setup_done = YES
+ }
+
+ fn = 1. * nside
+ fact1 = 1. / (3. * fn * fn)
+ fact2 = 2. / (3. * fn)
+ nl4 = 4 * nside
+
+ npface = nside * nside
+
+ face_num = ipix / npface + 1
+ ipf = mod (ipix, npface)
+
+ ip_low = mod (ipf, 1024) + 1
+ ip_trunc = ipf / 1024
+ ip_med = mod (ip_trunc, 1024) + 1
+ ip_hi = ip_trunc / 1024 + 1
+
+ ix = 1024*pix2x[ip_hi] + 32*pix2x[ip_med] + pix2x[ip_low]
+ iy = 1024*pix2y[ip_hi] + 32*pix2y[ip_med] + pix2y[ip_low]
+
+ jrt = ix + iy
+ jpt = ix - iy
+
+ jr = jrll[face_num] * nside - jrt - 1
+ nr = nside
+ z = (2 * nside - jr) * fact2
+ kshift = mod (jr - nside, 2)
+ if( jr < nside) {
+ nr = jr
+ z = 1. - nr * nr * fact1
+ kshift = 0
+ } else if (jr > 3*nside) {
+ nr = nl4 - jr
+ z = - 1. + nr * nr * fact1
+ kshift = 0
+ }
+
+ jp = (jpll[face_num] * nr + jpt + 1 + kshift)/2
+ if (jp > nl4)
+ jp = jp - nl4
+ if (jp < 1)
+ jp = jp + nl4
+
+ theta = acos(z)
+ phi = (jp - (kshift+1)*0.5) * (HALFPI / nr)
+end
+
+
+# PIX2ANG_RING -- Convert HEALpix pixel to spherical coordinates.
+
+procedure pix2ang_ring (nside, ipix, theta, phi)
+
+int nside #I Resolution parameter
+int ipix #I HEALPix index
+double theta #O Latitude (rad from pole)
+double phi #O Longitude (rad)
+
+int nl2, nl4, npix, ncap, iring, iphi, ip, ipix1
+double fact1, fact2, fodd, hip, fihip
+
+begin
+ npix = 12 * nside * nside
+ ipix1 = ipix + 1
+ nl2 = 2 * nside
+ nl4 = 4 * nside
+ ncap = 2 * nside * (nside - 1)
+ fact1 = 1.5 * nside
+ fact2 = 3.0 * nside * nside
+
+ if (ipix1 <= ncap) {
+
+ hip = ipix1 / 2.
+ fihip = int (hip)
+ iring = int (sqrt (hip - sqrt (fihip))) + 1
+ iphi = ipix1 - 2 * iring * (iring - 1)
+
+ theta = acos (1. - iring * iring / fact2)
+ phi = (iphi - 0.5) * PI / (2. * iring)
+
+ } else if (ipix1 <= nl2 * (5 * nside + 1)) {
+
+ ip = ipix1 - ncap - 1
+ iring = (ip / nl4) + nside
+ iphi = mod (ip, nl4) + 1
+
+ fodd = 0.5 * (1 + mod (iring + nside, 2))
+ theta = acos ((nl2 - iring) / fact1)
+ phi = (iphi - fodd) * PI / (2. * nside)
+
+ } else {
+
+ ip = npix - ipix1 + 1
+ hip = ip/2.
+
+ fihip = int (hip)
+ iring = int (sqrt (hip - sqrt (fihip))) + 1
+ iphi = 4. * iring + 1 - (ip - 2. * iring * (iring-1))
+
+ theta = acos (-1. + iring * iring / fact2)
+ phi = (iphi - 0.5) * PI / (2. * iring)
+
+ }
+end
+
+
+# MK_XY2PIX
+#
+# Sets the array giving the number of the pixel lying in (x,y)
+# x and y are in {1,128}
+# the pixel number is in {0,128**2-1}
+#
+# if i-1 = sum_p=0 b_p * 2^p
+# then ix = sum_p=0 b_p * 4^p
+# iy = 2*ix
+# ix + iy in {0, 128**2 -1}
+
+procedure mk_xy2pix (x2pix, y2pix)
+
+int x2pix[128], y2pix[128]
+
+int i, j, k, ip, id
+
+begin
+ do i = 1, 128
+ x2pix[i] = 0
+
+ do i = 1, 128 {
+ j = i - 1
+ k = 0
+ ip = 1
+ while (j != 0) {
+ id = mod (j, 2)
+ j = j / 2
+ k = ip * id + k
+ ip = ip * 4
+ }
+ x2pix[i] = k
+ y2pix[i] = 2 * k
+ }
+end
+
+
+# MK_PIX2XY
+#
+# Constructs the array giving x and y in the face from pixel number
+# for the nested (quad-cube like) ordering of pixels.
+#
+# The bits corresponding to x and y are interleaved in the pixel number.
+# One breaks up the pixel number by even and odd bits.
+
+procedure mk_pix2xy (pix2x, pix2y)
+
+int pix2x[1024], pix2y[1024]
+
+int kpix, jpix, ix, iy, ip, id
+
+begin
+
+ do kpix = 1, 1024
+ pix2x[kpix] = 0
+
+ do kpix = 1, 1024 {
+ jpix = kpix - 1
+ ix = 0
+ iy = 0
+ ip = 1
+ while (jpix != 0) {
+ id = mod (jpix, 2)
+ jpix = jpix / 2
+ ix = id * ip + ix
+
+ id = mod (jpix, 2)
+ jpix = jpix / 2
+ iy = id * ip + iy
+
+ ip = 2 * ip
+ }
+
+ pix2x[kpix] = ix
+ pix2y[kpix] = iy
+ }
+
+end
diff --git a/pkg/images/imcoords/src/mkcwcs.cl b/pkg/images/imcoords/src/mkcwcs.cl
new file mode 100644
index 00000000..fde777cd
--- /dev/null
+++ b/pkg/images/imcoords/src/mkcwcs.cl
@@ -0,0 +1,94 @@
+# MKCWCS -- Make celestial WCS.
+
+procedure mkcwcs (wcsname)
+
+file wcsname {prompt="WCS to create"}
+file wcsref = "" {prompt="WCS reference\n"}
+
+real equinox = INDEF {prompt="Equinox (years)"}
+real ra = INDEF {prompt="RA (hours)"}
+real dec = INDEF {prompt="DEC (degrees)"}
+real scale = INDEF {prompt="Celestial pixel scale (arcsec/pix)"}
+real pa = 0. {prompt="Position angle (deg)"}
+bool lefthanded = yes {prompt="Left-handed system?"}
+string projection = "tan" {prompt="Celestial projection\n",
+ enum="linear|tan|sin"}
+
+real rapix = INDEF {prompt="RA reference pixel"}
+real decpix = INDEF {prompt="DEC reference pixel"}
+
+begin
+ int wcsdim = 2
+ real c, s, lh
+ file name, ref, wcs
+
+ # Determine the input and reference images.
+ name = wcsname
+ if (fscan (wcsref, ref) > 0)
+ wcscopy (name, ref)
+
+ # Set the axes.
+ if (imaccess (name)) {
+ hedit (name, "ctype1", "RA---TAN",
+ add+, addonly-, verify-, show-, update+)
+ hedit (name, "ctype2", "DEC---TAN",
+ add+, addonly-, verify-, show-, update+)
+ }
+ wcsedit (name, "axtype", "ra", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "axtype", "dec", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "wtype", projection, "1,2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+
+ # Set the celestial equinox if desired. Note this is not WCS.
+ if (equinox != INDEF)
+ hedit (name, "equinox", equinox,
+ add+, addonly-, verify-, show-, update+)
+
+ # Set the reference point if desired.
+ if (ra != INDEF)
+ wcsedit (name, "crval", ra*15, "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ if (dec != INDEF)
+ wcsedit (name, "crval", dec, "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+
+ # Set the scales and celestial position angle.
+ if (scale != INDEF) {
+ if (pa != INDEF) {
+ c = cos (pa * 3.14159 / 180.) / 3600.
+ s = sin (pa * 3.14159 / 180.) / 3600.
+ } else {
+ c = 1.
+ s = 0.
+ }
+ if (lefthanded) {
+ wcsedit (name, "cd", -scale*c, "1", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", -scale*s, "1", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", -scale*s, "2", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", scale*c, "2", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ } else {
+ wcsedit (name, "cd", scale*c, "1", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", -scale*s, "1", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", scale*s, "2", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", scale*c, "2", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ }
+ }
+
+ # Set reference pixel if desired.
+ if (rapix != INDEF)
+ wcsedit (name, "crpix", rapix, "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ if (decpix != INDEF)
+ wcsedit (name, "crpix", decpix, "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+end
diff --git a/pkg/images/imcoords/src/mkcwwcs.cl b/pkg/images/imcoords/src/mkcwwcs.cl
new file mode 100644
index 00000000..30e26814
--- /dev/null
+++ b/pkg/images/imcoords/src/mkcwwcs.cl
@@ -0,0 +1,102 @@
+# MKCWWCS -- MaKe Celestial, Wavelength 3D World Coordinate System
+
+procedure mkcwwcs (wcsname)
+
+file wcsname {prompt="WCS to create"}
+file wcsref = "" {prompt="WCS reference\n"}
+
+real equinox = INDEF {prompt="Equinox (years)"}
+real ra = INDEF {prompt="RA (hours)"}
+real dec = INDEF {prompt="DEC (degrees)"}
+real scale = INDEF {prompt="Celestial pixel scale (arcsec/pix)"}
+real pa = 0. {prompt="Position angle (deg)"}
+bool lefthanded = yes {prompt="Left-handed system?"}
+string projection = "tan" {prompt="Celestial projection\n",
+ enum="linear|tan|sin"}
+
+real wave = INDEF {prompt="Wavelength"}
+real wscale = INDEF {prompt="Wavelength scale\n"}
+
+real rapix = INDEF {prompt="RA reference pixel"}
+real decpix = INDEF {prompt="DEC reference pixel"}
+real wpix = INDEF {prompt="Wavelength reference pixel"}
+
+begin
+ int wcsdim = 3
+ real c, s, lh
+ file name, ref, wcs
+
+ # Determine the input and reference images.
+ name = wcsname
+ if (fscan (wcsref, ref) > 0)
+ wcscopy (name, ref)
+
+ # Set the axes.
+ wcsedit (name, "axtype", "ra", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "axtype", "dec", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "wtype", projection, "1,2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+
+ # Set the celestial equinox if desired. Note this is not WCS.
+ if (equinox != INDEF)
+ hedit (name, "equinox", equinox,
+ add+, addonly-, verify-, show-, update+)
+
+ # Set the reference point if desired.
+ if (ra != INDEF)
+ wcsedit (name, "crval", ra*15, "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ if (dec != INDEF)
+ wcsedit (name, "crval", dec, "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ if (wave != INDEF)
+ wcsedit (name, "crval", wave, "3", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+
+ # Set the scales and celestial position angle.
+ if (scale != INDEF) {
+ if (pa != INDEF) {
+ c = cos (pa * 3.14159 / 180.) / 3600.
+ s = sin (pa * 3.14159 / 180.) / 3600.
+ } else {
+ c = 1.
+ s = 0.
+ }
+ if (lefthanded) {
+ wcsedit (name, "cd", -scale*c, "1", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", -scale*s, "1", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", -scale*s, "2", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", scale*c, "2", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ } else {
+ wcsedit (name, "cd", scale*c, "1", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", -scale*s, "1", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", scale*s, "2", "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ wcsedit (name, "cd", scale*c, "2", "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ }
+ }
+ if (wscale != INDEF)
+ wcsedit (name, "cd", wscale, "3", "3", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+
+ # Set reference pixel if desired.
+ if (rapix != INDEF)
+ wcsedit (name, "crpix", rapix, "1", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ if (decpix != INDEF)
+ wcsedit (name, "crpix", decpix, "2", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+ if (wpix != INDEF)
+ wcsedit (name, "crpix", wpix, "3", wcsdim=wcsdim,
+ wcs="world", interactive-, verbose-, update+)
+
+end
diff --git a/pkg/images/imcoords/src/mkpkg b/pkg/images/imcoords/src/mkpkg
new file mode 100644
index 00000000..6b1632ab
--- /dev/null
+++ b/pkg/images/imcoords/src/mkpkg
@@ -0,0 +1,47 @@
+# Library for the IMAGES IMCOORDS Subpackage Tasks
+
+$checkout libpkg.a ../../
+$update libpkg.a
+$checkin libpkg.a ../../
+$exit
+
+generic:
+ $set GEN = "$$generic -k"
+
+ $ifolder (rgstr.x, rgstr.gx)
+ $(GEN) rgstr.gx -o rgstr.x $endif
+ ;
+
+libpkg.a:
+ $ifeq (USE_GENERIC, yes) $call generic $endif
+
+ ccfunc.x <imhdr.h> <math.h> <mwset.h> <pkg/skywcs.h> \
+ <math/gsurfit.h>
+ ccstd.x <mach.h> <math.h> <math/gsurfit.h> <pkg/skywcs.h>
+ ccxytran.x <math.h> <pkg/skywcs.h>
+ healpix.x <math.h>
+ rgstr.x <ctype.h>
+ sfconvolve.x <imset.h> <math.h> starfind.h
+ sffind.x <error.h> <mach.h> <imhdr.h> <imset.h> <fset.h> \
+ <math.h> starfind.h
+ sftools.x <mach.h> starfind.h
+ skyctran.x <fset.h> <ctype.h> <math.h> <pkg/skywcs.h>
+ t_ccfind.x <fset.h> <ctype.h> <imhdr.h> <pkg/skywcs.h>
+ t_ccget.x <fset.h> <evvexpr.h> <math.h> <ctotok.h> <lexnum.h> \
+ <ctype.h> <pkg/skywcs.h>
+ t_ccmap.x <fset.h> <math/gsurfit.h> <ctype.h> <math.h> \
+ <imhdr.h> "../../lib/geomap.h" <pkg/skywcs.h>
+ t_ccsetwcs.x <imhdr.h> <math.h> <mwset.h> <pkg/skywcs.h>
+ t_ccstd.x <fset.h> <ctype.h> <math.h> <pkg/skywcs.h>
+ t_cctran.x <fset.h> <ctype.h> <math.h> <pkg/skywcs.h>
+ t_ccxymatch.x <fset.h> <pkg/skywcs.h> "../../lib/xyxymatch.h"
+ t_hpctran.x <math.h>
+ t_imcctran.x <fset.h> <imhdr.h> <mwset.h> <math.h> <math/gsurfit.h> \
+ <pkg/skywcs.h>
+ t_skyctran.x <fset.h> <pkg/skywcs.h>
+ t_starfind.x <fset.h>
+ t_wcsctran.x <imio.h> <fset.h> <ctype.h> <imhdr.h> <ctotok.h> \
+ <mwset.h>
+ t_wcsedit.x <fset.h> <imhdr.h> <mwset.h>
+ t_wcsreset.x <error.h> <imhdr.h> <mwset.h>
+ ;
diff --git a/pkg/images/imcoords/src/rgstr.gx b/pkg/images/imcoords/src/rgstr.gx
new file mode 100644
index 00000000..3647f80b
--- /dev/null
+++ b/pkg/images/imcoords/src/rgstr.gx
@@ -0,0 +1,109 @@
+include <ctype.h>
+
+$for (rd)
+
+# RG_APACK_LINE -- Fields are packed into the output buffer. Transformed
+# fields are converted to strings; other fields are copied from the input
+# line to the output buffer.
+
+procedure rg_apack_line$t (inbuf, outbuf, maxch, field_pos, nfields,
+ cinfields, ncin, coords, laxno, formats, nsdig, ncout, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int cinfields[ARB] #I fields to be replaced
+int ncin #I the number of input fields
+PIXEL coords[ARB] #I the transformed coordinates
+int laxno[ARB] #I the logical axis mapping
+pointer formats[ARB] #I array of format pointers
+int nsdig[ARB] #I array of numbers of significant digits
+int ncout #I the number of coordinates
+int min_sigdigits #I the minimum number of signficant digits
+
+int op, num_field, width, cf, cfptr
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ # Copy the file replacing fields as one goes.
+ do num_field = 1, nfields {
+
+ # Find the width of the field.
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ # Find the field to be replaced.
+ cfptr = 0
+ do cf = 1, ncin {
+ if (cinfields[cf] != num_field)
+ next
+ cfptr = cf
+ break
+ }
+
+ # Replace the field.
+ if (cfptr != 0) {
+ if (laxno[cfptr] == 0) {
+ Memc[field] = EOS
+ next
+ #call li_format_field$t ($INDEF$T, Memc[field], maxch,
+ #Memc[formats[cfptr]], nsdig[cfptr], width,
+ #min_sigdigits)
+ } else
+ call li_format_field$t (coords[laxno[cfptr]], Memc[field],
+ maxch, Memc[formats[laxno[cfptr]]], nsdig[laxno[cfptr]],
+ width, min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ do cfptr = ncin + 1, ncout {
+
+ # Copy out the extra fields if any.
+ if (laxno[cfptr] == 0) {
+ Memc[field] = EOS
+ next
+ #call li_format_field$t ($INDEF$T, Memc[field], maxch, "%g",
+ #min_sigdigits, width, min_sigdigits)
+ } else
+ call li_format_field$t (coords[laxno[cfptr]], Memc[field],
+ maxch, Memc[formats[laxno[cfptr]]], nsdig[laxno[cfptr]],
+ width, min_sigdigits)
+
+ # Fields must be delimited by at least one blank.
+ if (!IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+$endfor
diff --git a/pkg/images/imcoords/src/rgstr.x b/pkg/images/imcoords/src/rgstr.x
new file mode 100644
index 00000000..4e3d0836
--- /dev/null
+++ b/pkg/images/imcoords/src/rgstr.x
@@ -0,0 +1,215 @@
+include <ctype.h>
+
+
+
+# RG_APACK_LINE -- Fields are packed into the output buffer. Transformed
+# fields are converted to strings; other fields are copied from the input
+# line to the output buffer.
+
+procedure rg_apack_liner (inbuf, outbuf, maxch, field_pos, nfields,
+ cinfields, ncin, coords, laxno, formats, nsdig, ncout, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int cinfields[ARB] #I fields to be replaced
+int ncin #I the number of input fields
+real coords[ARB] #I the transformed coordinates
+int laxno[ARB] #I the logical axis mapping
+pointer formats[ARB] #I array of format pointers
+int nsdig[ARB] #I array of numbers of significant digits
+int ncout #I the number of coordinates
+int min_sigdigits #I the minimum number of signficant digits
+
+int op, num_field, width, cf, cfptr
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ # Copy the file replacing fields as one goes.
+ do num_field = 1, nfields {
+
+ # Find the width of the field.
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ # Find the field to be replaced.
+ cfptr = 0
+ do cf = 1, ncin {
+ if (cinfields[cf] != num_field)
+ next
+ cfptr = cf
+ break
+ }
+
+ # Replace the field.
+ if (cfptr != 0) {
+ if (laxno[cfptr] == 0) {
+ Memc[field] = EOS
+ next
+ #call li_format_field$t ($INDEF$T, Memc[field], maxch,
+ #Memc[formats[cfptr]], nsdig[cfptr], width,
+ #min_sigdigits)
+ } else
+ call li_format_fieldr (coords[laxno[cfptr]], Memc[field],
+ maxch, Memc[formats[laxno[cfptr]]], nsdig[laxno[cfptr]],
+ width, min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ do cfptr = ncin + 1, ncout {
+
+ # Copy out the extra fields if any.
+ if (laxno[cfptr] == 0) {
+ Memc[field] = EOS
+ next
+ #call li_format_field$t ($INDEF$T, Memc[field], maxch, "%g",
+ #min_sigdigits, width, min_sigdigits)
+ } else
+ call li_format_fieldr (coords[laxno[cfptr]], Memc[field],
+ maxch, Memc[formats[laxno[cfptr]]], nsdig[laxno[cfptr]],
+ width, min_sigdigits)
+
+ # Fields must be delimited by at least one blank.
+ if (!IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+
+
+# RG_APACK_LINE -- Fields are packed into the output buffer. Transformed
+# fields are converted to strings; other fields are copied from the input
+# line to the output buffer.
+
+procedure rg_apack_lined (inbuf, outbuf, maxch, field_pos, nfields,
+ cinfields, ncin, coords, laxno, formats, nsdig, ncout, min_sigdigits)
+
+char inbuf[ARB] #I the input string buffer
+char outbuf[maxch] #O the output string buffer
+int maxch #I the maximum size of the output buffer
+int field_pos[ARB] #I starting positions for the fields
+int nfields #I the number of fields
+int cinfields[ARB] #I fields to be replaced
+int ncin #I the number of input fields
+double coords[ARB] #I the transformed coordinates
+int laxno[ARB] #I the logical axis mapping
+pointer formats[ARB] #I array of format pointers
+int nsdig[ARB] #I array of numbers of significant digits
+int ncout #I the number of coordinates
+int min_sigdigits #I the minimum number of signficant digits
+
+int op, num_field, width, cf, cfptr
+pointer sp, field
+int gstrcpy()
+
+begin
+ call smark (sp)
+ call salloc (field, SZ_LINE, TY_CHAR)
+
+ # Initialize output pointer.
+ op = 1
+
+ # Copy the file replacing fields as one goes.
+ do num_field = 1, nfields {
+
+ # Find the width of the field.
+ width = field_pos[num_field + 1] - field_pos[num_field]
+
+ # Find the field to be replaced.
+ cfptr = 0
+ do cf = 1, ncin {
+ if (cinfields[cf] != num_field)
+ next
+ cfptr = cf
+ break
+ }
+
+ # Replace the field.
+ if (cfptr != 0) {
+ if (laxno[cfptr] == 0) {
+ Memc[field] = EOS
+ next
+ #call li_format_field$t ($INDEF$T, Memc[field], maxch,
+ #Memc[formats[cfptr]], nsdig[cfptr], width,
+ #min_sigdigits)
+ } else
+ call li_format_fieldd (coords[laxno[cfptr]], Memc[field],
+ maxch, Memc[formats[laxno[cfptr]]], nsdig[laxno[cfptr]],
+ width, min_sigdigits)
+ } else {
+ # Put "width" characters from inbuf into field
+ call strcpy (inbuf[field_pos[num_field]], Memc[field], width)
+ }
+
+ # Fields must be delimited by at least one blank.
+ if (num_field > 1 && !IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ do cfptr = ncin + 1, ncout {
+
+ # Copy out the extra fields if any.
+ if (laxno[cfptr] == 0) {
+ Memc[field] = EOS
+ next
+ #call li_format_field$t ($INDEF$T, Memc[field], maxch, "%g",
+ #min_sigdigits, width, min_sigdigits)
+ } else
+ call li_format_fieldd (coords[laxno[cfptr]], Memc[field],
+ maxch, Memc[formats[laxno[cfptr]]], nsdig[laxno[cfptr]],
+ width, min_sigdigits)
+
+ # Fields must be delimited by at least one blank.
+ if (!IS_WHITE (Memc[field])) {
+ outbuf[op] = ' '
+ op = op + 1
+ }
+
+ # Copy "field" to output buffer.
+ op = op + gstrcpy (Memc[field], outbuf[op], maxch)
+ }
+
+ outbuf[op] = '\n'
+ outbuf[op+1] = EOS
+
+ call sfree (sp)
+end
+
+
+
diff --git a/pkg/images/imcoords/src/sfconvolve.x b/pkg/images/imcoords/src/sfconvolve.x
new file mode 100644
index 00000000..39411c2d
--- /dev/null
+++ b/pkg/images/imcoords/src/sfconvolve.x
@@ -0,0 +1,398 @@
+include <imset.h>
+include <math.h>
+include "starfind.h"
+
+
+# SF_EGPARAMS -- Calculate the parameters of the elliptical Gaussian needed
+# to compute the Gaussian convolution kernel.
+
+procedure sf_egparams (sigma, ratio, theta, nsigma, a, b, c, f, nx, ny)
+
+real sigma #I sigma of Gaussian in x
+real ratio #I ratio of half-width in y to x
+real theta #I position angle of Gaussian
+real nsigma #I limit of convolution
+real a, b, c, f #O ellipse parameters
+int nx, ny #O dimensions of the kernel
+
+real sx2, sy2, cost, sint, discrim
+bool fp_equalr ()
+
+begin
+ # Define some temporary variables.
+ sx2 = sigma ** 2
+ sy2 = (ratio * sigma) ** 2
+ cost = cos (DEGTORAD (theta))
+ sint = sin (DEGTORAD (theta))
+
+ # Compute the ellipse parameters.
+ if (fp_equalr (ratio, 0.0)) {
+ if (fp_equalr (theta, 0.0) || fp_equalr (theta, 180.)) {
+ a = 1. / sx2
+ b = 0.0
+ c = 0.0
+ } else if (fp_equalr (theta, 90.0)) {
+ a = 0.0
+ b = 0.0
+ c = 1. / sx2
+ } else
+ call error (0, "SF_EGPARAMS: Cannot make 1D Gaussian.")
+ f = nsigma ** 2 / 2.
+ nx = 2 * int (max (sigma * nsigma * abs (cost), RMIN)) + 1
+ ny = 2 * int (max (sigma * nsigma * abs (sint), RMIN)) + 1
+ } else {
+ a = cost ** 2 / sx2 + sint ** 2 / sy2
+ b = 2. * (1.0 / sx2 - 1.0 / sy2) * cost * sint
+ c = sint ** 2 / sx2 + cost ** 2 / sy2
+ discrim = b ** 2 - 4. * a * c
+ f = nsigma ** 2 / 2.
+ nx = 2 * int (max (sqrt (-8. * c * f / discrim), RMIN)) + 1
+ ny = 2 * int (max (sqrt (-8. * a * f / discrim), RMIN)) + 1
+ }
+end
+
+
+# SF_EGKERNEL -- Compute the non-normalized and normalized elliptical
+# Gaussian kernel and the skip array.
+
+real procedure sf_egkernel (gkernel, ngkernel, skip, nx, ny, gsums, a, b, c, f)
+
+real gkernel[nx,ny] #O output Gaussian amplitude kernel
+real ngkernel[nx,ny] #O output normalized Gaussian amplitude kernel
+int skip[nx,ny] #O output skip subraster
+int nx, ny #I input dimensions of the kernel
+real gsums[ARB] #O output array of gsums
+real a, b, c, f #I ellipse parameters
+
+int i, j, x0, y0, x, y
+real rjsq, rsq, relerr, ef
+
+begin
+ # Initialize.
+ x0 = nx / 2 + 1
+ y0 = ny / 2 + 1
+ gsums[GAUSS_PIXELS] = 0.0
+ gsums[GAUSS_SUMG] = 0.0
+ gsums[GAUSS_SUMGSQ] = 0.0
+
+ # Compute the kernel and principal sums.
+ do j = 1, ny {
+ y = j - y0
+ rjsq = y ** 2
+ do i = 1, nx {
+ x = i - x0
+ rsq = sqrt (x ** 2 + rjsq)
+ ef = 0.5 * (a * x ** 2 + c * y ** 2 + b * x * y)
+ gkernel[i,j] = exp (-1.0 * ef)
+ if (ef <= f || rsq <= RMIN) {
+ ngkernel[i,j] = gkernel[i,j]
+ gsums[GAUSS_SUMG] = gsums[GAUSS_SUMG] + gkernel[i,j]
+ gsums[GAUSS_SUMGSQ] = gsums[GAUSS_SUMGSQ] +
+ gkernel[i,j] ** 2
+ skip[i,j] = NO
+ gsums[GAUSS_PIXELS] = gsums[GAUSS_PIXELS] + 1.0
+ } else {
+ ngkernel[i,j] = 0.0
+ skip[i,j] = YES
+ }
+ }
+ }
+
+ # Store the remaining sums.
+ gsums[GAUSS_DENOM] = gsums[GAUSS_SUMGSQ] - gsums[GAUSS_SUMG] ** 2 /
+ gsums[GAUSS_PIXELS]
+ gsums[GAUSS_SGOP] = gsums[GAUSS_SUMG] / gsums[GAUSS_PIXELS]
+
+ # Normalize the kernel.
+ do j = 1, ny {
+ do i = 1, nx {
+ if (skip[i,j] == NO)
+ ngkernel[i,j] = (gkernel[i,j] - gsums[GAUSS_SGOP]) /
+ gsums[GAUSS_DENOM]
+ }
+ }
+
+
+ relerr = 1.0 / gsums[GAUSS_DENOM]
+
+ return (sqrt (relerr))
+end
+
+
+# SF_FCONVOLVE -- Solve for the density enhancements in the case where
+# datamin and datamax are not defined.
+
+procedure sf_fconvolve (im, c1, c2, l1, l2, bwidth, imbuf, denbuf, ncols,
+ nlines, kernel, skip, nxk, nyk)
+
+pointer im #I pointer to the input image
+int c1, c2 #I column limits in the input image
+int l1, l2 #I line limits in the input image
+int bwidth #I width of pixel buffer
+real imbuf[ncols,nlines] #O the output data buffer
+real denbuf[ncols,nlines] #O the output density enhancement buffer
+int ncols, nlines #I dimensions of the output buffers
+real kernel[nxk,nyk] #I the convolution kernel
+int skip[nxk,nyk] #I the skip array
+int nxk, nyk #I dimensions of the kernel
+
+int i, col1, col2, inline, index, outline
+pointer sp, lineptrs
+pointer imgs2r()
+errchk imgs2r
+
+begin
+ # Set up an array of linepointers.
+ call smark (sp)
+ call salloc (lineptrs, nyk, TY_POINTER)
+
+ # Set the number of image buffers.
+ call imseti (im, IM_NBUFS, nyk)
+
+ # Set input image column limits.
+ col1 = c1 - nxk / 2 - bwidth
+ col2 = c2 + nxk / 2 + bwidth
+
+ # Initialise the line buffers at the same time copying the image
+ # input the data buffer.
+ inline = l1 - bwidth - nyk / 2
+ do index = 1 , nyk - 1 {
+ Memi[lineptrs+index] = imgs2r (im, col1, col2, inline, inline)
+ call amovr (Memr[Memi[lineptrs+index]], imbuf[1,index], ncols)
+ inline = inline + 1
+ }
+
+ # Zero the initial density enhancement buffers.
+ do i = 1, nyk / 2
+ call amovkr (0.0, denbuf[1,i], ncols)
+
+ # Generate the output image line by line.
+ do outline = 1, l2 - l1 + 2 * bwidth + 1 {
+
+ # Scroll the input buffers.
+ do i = 1, nyk - 1
+ Memi[lineptrs+i-1] = Memi[lineptrs+i]
+
+ # Read in new image line and copy it into the image buffer.
+ Memi[lineptrs+nyk-1] = imgs2r (im, col1, col2, inline,
+ inline)
+
+ # Compute the input image line into the data buffer.
+ call amovr (Memr[Memi[lineptrs+nyk-1]], imbuf[1,index], ncols)
+
+ # Generate first output image line.
+ call aclrr (denbuf[1,outline+nyk/2], ncols)
+ do i = 1, nyk
+ call sf_skcnvr (Memr[Memi[lineptrs+i-1]],
+ denbuf[1+nxk/2,outline+nyk/2], c2 - c1 + 2 * bwidth + 1,
+ kernel[1,i], skip[1,i], nxk)
+
+ inline = inline + 1
+ index = index + 1
+ }
+
+ # Zero the final density enhancement buffer lines.
+ do i = nlines - nyk / 2 + 1, nlines
+ call amovkr (0.0, denbuf[1,i], ncols)
+
+ # Free the image buffer pointers.
+ call sfree (sp)
+end
+
+
+# SF_GCONVOLVE -- Solve for the density enhancement image in the case where
+# datamin and datamax are defined.
+
+procedure sf_gconvolve (im, c1, c2, l1, l2, bwidth, imbuf, denbuf, ncols,
+ nlines, kernel, skip, nxk, nyk, gsums, datamin, datamax)
+
+pointer im # pointer to the input image
+int c1, c2 #I column limits in the input image
+int l1, l2 #I line limits in the input image
+int bwidth #I width of pixel buffer
+real imbuf[ncols,nlines] #O the output data buffer
+real denbuf[ncols,nlines] #O the output density enhancement buffer
+int ncols, nlines #I dimensions of the output buffers
+real kernel[nxk,nyk] #I the first convolution kernel
+int skip[nxk,nyk] #I the sky array
+int nxk, nyk #I dimensions of the kernel
+real gsums[ARB] #U array of kernel sums
+real datamin, datamax #I the good data minimum and maximum
+
+int i, nc, col1, col2, inline, index, outline
+pointer sp, lineptrs, sd, sgsq, sg, p
+pointer imgs2r()
+errchk imgs2r()
+
+begin
+ # Set up an array of linepointers.
+ call smark (sp)
+ call salloc (lineptrs, nyk, TY_POINTER)
+
+ # Set the number of image buffers.
+ call imseti (im, IM_NBUFS, nyk)
+
+ # Allocate some working space.
+ nc = c2 - c1 + 2 * bwidth + 1
+ call salloc (sd, nc, TY_REAL)
+ call salloc (sgsq, nc, TY_REAL)
+ call salloc (sg, nc, TY_REAL)
+ call salloc (p, nc, TY_REAL)
+
+ # Set input image column limits.
+ col1 = c1 - nxk / 2 - bwidth
+ col2 = c2 + nxk / 2 + bwidth
+
+ # Initialise the line buffers.
+ inline = l1 - bwidth - nyk / 2
+ do index = 1 , nyk - 1 {
+ Memi[lineptrs+index] = imgs2r (im, col1, col2, inline, inline)
+ call amovr (Memr[Memi[lineptrs+index]], imbuf[1,index], ncols)
+ inline = inline + 1
+ }
+
+ # Zero the initial density enhancement buffers.
+ do i = 1, nyk / 2
+ call amovkr (0.0, denbuf[1,i], ncols)
+
+ # Generate the output image line by line.
+ do outline = 1, l2 - l1 + 2 * bwidth + 1 {
+
+ # Scroll the input buffers.
+ do i = 1, nyk - 1
+ Memi[lineptrs+i-1] = Memi[lineptrs+i]
+
+ # Read in new image line.
+ Memi[lineptrs+nyk-1] = imgs2r (im, col1, col2, inline,
+ inline)
+
+ # Compute the input image line into the data buffer.
+ call amovr (Memr[Memi[lineptrs+nyk-1]], imbuf[1,index], ncols)
+
+ # Generate first output image line.
+ call aclrr (denbuf[1,outline+nyk/2], ncols)
+ call aclrr (Memr[sd], nc)
+ call amovkr (gsums[GAUSS_SUMG], Memr[sg], nc)
+ call amovkr (gsums[GAUSS_SUMGSQ], Memr[sgsq], nc)
+ call amovkr (gsums[GAUSS_PIXELS], Memr[p], nc)
+
+ do i = 1, nyk
+ call sf_gdsum (Memr[Memi[lineptrs+i-1]],
+ denbuf[1+nxk/2,outline+nyk/2], Memr[sd],
+ Memr[sg], Memr[sgsq], Memr[p], nc, kernel[1,i],
+ skip[1,i], nxk, datamin, datamax)
+ call sf_gdavg (denbuf[1+nxk/2,outline+nyk/2], Memr[sd], Memr[sg],
+ Memr[sgsq], Memr[p], nc, gsums[GAUSS_PIXELS],
+ gsums[GAUSS_DENOM], gsums[GAUSS_SGOP])
+
+ inline = inline + 1
+ index = index + 1
+ }
+
+ # Zero the final density enhancement buffer lines.
+ do i = nlines - nyk / 2 + 1, nlines
+ call amovkr (0.0, denbuf[1,i], ncols)
+
+ # Free the image buffer pointers.
+ call sfree (sp)
+end
+
+
+# SF_SKCNVR -- Compute the convolution kernel using a skip array.
+
+procedure sf_skcnvr (in, out, npix, kernel, skip, nk)
+
+real in[npix+nk-1] #I the input vector
+real out[npix] #O the output vector
+int npix #I the size of the vector
+real kernel[ARB] #I the convolution kernel
+int skip[ARB] #I the skip array
+int nk #I the size of the convolution kernel
+
+int i, j
+real sum
+
+begin
+ do i = 1, npix {
+ sum = out[i]
+ do j = 1, nk {
+ if (skip[j] == YES)
+ next
+ sum = sum + in[i+j-1] * kernel[j]
+ }
+ out[i] = sum
+ }
+end
+
+
+# SF_GDSUM -- Compute the vector sums required to do the convolution.
+
+procedure sf_gdsum (in, sgd, sd, sg, sgsq, p, npix, kernel, skip, nk,
+ datamin, datamax)
+
+real in[npix+nk-1] #I the input vector
+real sgd[ARB] #U the computed input/output convolution vector
+real sd[ARB] #U the computed input/output sum vector
+real sg[ARB] #U the input/ouput first normalization factor
+real sgsq[ARB] #U the input/ouput second normalization factor
+real p[ARB] #U the number of points vector
+int npix #I the size of the vector
+real kernel[ARB] #I the convolution kernel
+int skip[ARB] #I the skip array
+int nk #I the size of the convolution kernel
+real datamin, datamax #I the good data limits.
+
+int i, j
+real data
+
+begin
+ do i = 1, npix {
+ do j = 1, nk {
+ if (skip[j] == YES)
+ next
+ data = in[i+j-1]
+ if (data < datamin || data > datamax) {
+ sgsq[i] = sgsq[i] - kernel[j] ** 2
+ sg[i] = sg[i] - kernel[j]
+ p[i] = p[i] - 1.0
+ } else {
+ sgd[i] = sgd[i] + kernel[j] * data
+ sd[i] = sd[i] + data
+ }
+ }
+ }
+end
+
+
+# SF_GDAVG -- Compute the vector averages required to do the convolution.
+
+procedure sf_gdavg (sgd, sd, sg, sgsq, p, npix, pixels, denom, sgop)
+
+real sgd[ARB] #U the computed input/output convolution vector
+real sd[ARB] #I the computed input/output sum vector
+real sg[ARB] #I the input/ouput first normalization factor
+real sgsq[ARB] #U the input/ouput second normalization factor
+real p[ARB] #I the number of points vector
+int npix #I the size of the vector
+real pixels #I number of pixels
+real denom #I kernel normalization factor
+real sgop #I kernel normalization factor
+
+int i
+
+begin
+ do i = 1, npix {
+ if (p[i] > 1.5) {
+ if (p[i] < pixels) {
+ sgsq[i] = sgsq[i] - (sg[i] ** 2) / p[i]
+ if (sgsq[i] != 0.0)
+ sgd[i] = (sgd[i] - sg[i] * sd[i] / p[i]) / sgsq[i]
+ else
+ sgd[i] = 0.0
+ } else
+ sgd[i] = (sgd[i] - sgop * sd[i]) / denom
+ } else
+ sgd[i] = 0.0
+ }
+end
+
diff --git a/pkg/images/imcoords/src/sffind.x b/pkg/images/imcoords/src/sffind.x
new file mode 100644
index 00000000..367893e5
--- /dev/null
+++ b/pkg/images/imcoords/src/sffind.x
@@ -0,0 +1,739 @@
+include <error.h>
+include <mach.h>
+include <imhdr.h>
+include <imset.h>
+include <fset.h>
+include <math.h>
+include "starfind.h"
+
+
+# SF_FIND -- Find stars in an image using a pattern matching technique and
+# a circularly symmetric Gaussian pattern.
+
+procedure sf_find (im, out, sf, nxblock, nyblock, wcs, wxformat, wyformat,
+ boundary, constant, verbose)
+
+pointer im #I pointer to the input image
+int out #I the output file descriptor
+pointer sf #I pointer to the apphot structure
+int nxblock #I the x dimension blocking factor
+int nyblock #I the y dimension blocking factor
+char wcs[ARB] #I the world coordinate system
+char wxformat[ARB] #I the x axis world coordinate format
+char wyformat[ARB] #I the y axis world coordinate format
+int boundary #I type of boundary extension
+real constant #I constant for constant boundary extension
+int verbose #I verbose switch
+
+int i, j, fwidth, swidth, norm
+int l1, l2, c1, c2, ncols, nlines, nxb, nyb, nstars, stid
+pointer sp, gker2d, ngker2d, skip, fmtstr, twxformat, twyformat
+pointer imbuf, denbuf, str, mw, ct
+real sigma, nsigma, a, b, c, f, gsums[LEN_GAUSS], relerr, dmin, dmax
+real maglo, maghi
+
+bool streq()
+int sf_stfind()
+pointer mw_openim(), mw_sctran()
+real sf_egkernel()
+errchk mw_openim(), mw_sctran(), mw_gattrs()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (twxformat, SZ_FNAME, TY_CHAR)
+ call salloc (twyformat, SZ_FNAME, TY_CHAR)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Compute the parameters of the Gaussian kernel.
+ sigma = HWHM_TO_SIGMA * SF_HWHMPSF(sf)
+ nsigma = SF_FRADIUS(sf) / HWHM_TO_SIGMA
+ call sf_egparams (sigma, 1.0, 0.0, nsigma, a, b, c, f, fwidth, fwidth)
+
+ # Compute the separation parameter
+ swidth = max (2, int (SF_SEPMIN(sf) * SF_HWHMPSF(sf) + 0.5))
+
+ # Compute the minimum and maximum pixel values.
+ if (IS_INDEFR(SF_DATAMIN(sf)) && IS_INDEFR(SF_DATAMAX(sf))) {
+ norm = YES
+ dmin = -MAX_REAL
+ dmax = MAX_REAL
+ } else {
+ norm = NO
+ if (IS_INDEFR(SF_DATAMIN(sf)))
+ dmin = -MAX_REAL
+ else
+ dmin = SF_DATAMIN(sf)
+ if (IS_INDEFR(SF_DATAMAX(sf)))
+ dmax = MAX_REAL
+ else
+ dmax = SF_DATAMAX(sf)
+ }
+
+ # Compute the magnitude limits
+ if (IS_INDEFR(SF_MAGLO(sf)))
+ maglo = -MAX_REAL
+ else
+ maglo = SF_MAGLO(sf)
+ if (IS_INDEFR(SF_MAGHI(sf)))
+ maghi = MAX_REAL
+ else
+ maghi = SF_MAGHI(sf)
+
+ # Open the image WCS.
+ if (wcs[1] == EOS) {
+ mw = NULL
+ ct = NULL
+ } else {
+ iferr {
+ mw = mw_openim (im)
+ } then {
+ call erract (EA_WARN)
+ mw = NULL
+ ct = NULL
+ } else {
+ iferr {
+ ct = mw_sctran (mw, "logical", wcs, 03B)
+ } then {
+ call erract (EA_WARN)
+ ct = NULL
+ call mw_close (mw)
+ mw = NULL
+ }
+ }
+ }
+
+ # Set the WCS formats.
+ if (ct == NULL)
+ call strcpy (wxformat, Memc[twxformat], SZ_FNAME)
+ else if (wxformat[1] == EOS) {
+ if (mw != NULL) {
+ iferr (call mw_gwattrs (mw, 1, "format", Memc[twxformat],
+ SZ_FNAME)) {
+ if (streq (wcs, "world"))
+ call strcpy ("%11.8g", Memc[twxformat], SZ_FNAME)
+ else
+ call strcpy ("%9.3f", Memc[twxformat], SZ_FNAME)
+ }
+ } else
+ call strcpy ("%9.3f", Memc[twxformat], SZ_FNAME)
+ } else
+ call strcpy (wxformat, Memc[twxformat], SZ_FNAME)
+ if (ct == NULL)
+ call strcpy (wyformat, Memc[twyformat], SZ_FNAME)
+ else if (wyformat[1] == EOS) {
+ if (mw != NULL) {
+ iferr (call mw_gwattrs (mw, 2, "format", Memc[twyformat],
+ SZ_FNAME)) {
+ if (streq (wcs, "world"))
+ call strcpy ("%11.8g", Memc[twyformat], SZ_FNAME)
+ else
+ call strcpy ("%9.3f", Memc[twyformat], SZ_FNAME)
+ }
+ } else
+ call strcpy ("%9.3f", Memc[twyformat], SZ_FNAME)
+ } else
+ call strcpy (wyformat, Memc[twyformat], SZ_FNAME)
+
+ # Create the output format string.
+ call sprintf (Memc[fmtstr],
+ SZ_LINE, " %s %s %s %s %s %s %s %s %s %s %s\n")
+ call pargstr ("%9.3f")
+ call pargstr ("%9.3f")
+ call pargstr (Memc[twxformat])
+ call pargstr (Memc[twyformat])
+ call pargstr ("%7.2f")
+ call pargstr ("%6d")
+ call pargstr ("%6.2f")
+ call pargstr ("%6.3f")
+ call pargstr ("%6.1f")
+ call pargstr ("%7.3f")
+ call pargstr ("%6d")
+
+ # Set up the image boundary extension characteristics.
+ call imseti (im, IM_TYBNDRY, boundary)
+ call imseti (im, IM_NBNDRYPIX, 1 + fwidth / 2 + swidth)
+ if (boundary == BT_CONSTANT)
+ call imsetr (im, IM_BNDRYPIXVAL, constant)
+
+ # Set up the blocking factor.
+ # Compute the magnitude limits
+ if (IS_INDEFI(nxblock))
+ nxb = IM_LEN(im,1)
+ else
+ nxb = nxblock
+ if (IS_INDEFI(nyblock))
+ nyb = IM_LEN(im,2)
+ else
+ nyb = nyblock
+
+ # Print the detection criteria on the standard output.
+ if (verbose == YES) {
+ call fstats (out, F_FILENAME, Memc[str], SZ_LINE)
+ call printf ("\nImage: %s Output: %s\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[str])
+ call printf ("Detection Parameters\n")
+ call printf (
+ " Hwhmpsf: %0.3f (pixels) Threshold: %g (ADU) Npixmin: %d\n")
+ call pargr (SF_HWHMPSF(sf))
+ call pargr (SF_THRESHOLD(sf))
+ call pargi (SF_NPIXMIN(sf))
+ call printf (" Datamin: %g (ADU) Datamax: %g (ADU)\n")
+ call pargr (SF_DATAMIN(sf))
+ call pargr (SF_DATAMAX(sf))
+ call printf (" Fradius: %0.3f (HWHM) Sepmin: %0.3f (HWHM)\n\n")
+ call pargr (SF_FRADIUS(sf))
+ call pargr (SF_SEPMIN(sf))
+ }
+
+ if (out != NULL) {
+ call fstats (out, F_FILENAME, Memc[str], SZ_LINE)
+ call fprintf (out, "\n# Image: %s Output: %s\n")
+ call pargstr (IM_HDRFILE(im))
+ call pargstr (Memc[str])
+ call fprintf (out, "# Detection Parameters\n")
+ call fprintf (out,
+ "# Hwhmpsf: %0.3f (pixels) Threshold: %g (ADU) Npixmin: %d\n")
+ call pargr (SF_HWHMPSF(sf))
+ call pargr (SF_THRESHOLD(sf))
+ call pargi (SF_NPIXMIN(sf))
+ call fprintf (out, "# Datamin: %g (ADU) Datamax: %g (ADU)\n")
+ call pargr (SF_DATAMIN(sf))
+ call pargr (SF_DATAMAX(sf))
+ call fprintf (out, "# Fradius: %g (HWHM) Sepmin: %g (HWHM)\n")
+ call pargr (SF_FRADIUS(sf))
+ call pargr (SF_SEPMIN(sf))
+ call fprintf (out, "# Selection Parameters\n")
+ call pargi (SF_NPIXMIN(sf))
+ call fprintf (out, "# Maglo: %0.3f Maghi: %0.3f\n")
+ call pargr (SF_MAGLO(sf))
+ call pargr (SF_MAGHI(sf))
+ call fprintf (out, "# Roundlo: %0.3f Roundhi: %0.3f\n")
+ call pargr (SF_ROUNDLO(sf))
+ call pargr (SF_ROUNDHI(sf))
+ call fprintf (out, "# Sharplo: %0.3f Sharphi: %0.3f\n")
+ call pargr (SF_SHARPLO(sf))
+ call pargr (SF_SHARPHI(sf))
+ call fprintf (out, "# Columns\n")
+ call fprintf (out, "# 1: X 2: Y \n")
+ if (ct == NULL) {
+ call fprintf (out, "# 3: Mag 4: Area\n")
+ call fprintf (out, "# 5: Hwhm 6: Roundness\n")
+ call fprintf (out, "# 7: Pa 8: Sharpness\n\n")
+ } else {
+ call fprintf (out, "# 3: Wx 4: Wy \n")
+ call fprintf (out, "# 5: Mag 6: Area\n")
+ call fprintf (out, "# 7: Hwhm 8: Roundness\n")
+ call fprintf (out, "# 9: Pa 10: Sharpness\n\n")
+ }
+ }
+
+ # Process the image block by block.
+ stid = 1
+ nstars = 0
+ do j = 1, IM_LEN(im,2), nyb {
+
+ l1 = j
+ l2 = min (IM_LEN(im,2), j + nyb - 1)
+ nlines = l2 - l1 + 1 + 2 * (fwidth / 2 + swidth)
+
+ do i = 1, IM_LEN(im,1), nxb {
+
+ # Allocate space for the convolution kernel.
+ call malloc (gker2d, fwidth * fwidth, TY_REAL)
+ call malloc (ngker2d, fwidth * fwidth, TY_REAL)
+ call malloc (skip, fwidth * fwidth, TY_INT)
+
+ # Allocate space for the data and the convolution.
+ c1 = i
+ c2 = min (IM_LEN(im,1), i + nxb - 1)
+ ncols = c2 - c1 + 1 + 2 * (fwidth / 2 + swidth)
+ call malloc (imbuf, ncols * nlines, TY_REAL)
+ call malloc (denbuf, ncols * nlines, TY_REAL)
+
+ # Compute the convolution kernels.
+ relerr = sf_egkernel (Memr[gker2d], Memr[ngker2d], Memi[skip],
+ fwidth, fwidth, gsums, a, b, c, f)
+
+ # Do the convolution.
+ if (norm == YES)
+ call sf_fconvolve (im, c1, c2, l1, l2, swidth, Memr[imbuf],
+ Memr[denbuf], ncols, nlines, Memr[ngker2d], Memi[skip],
+ fwidth, fwidth)
+ else
+ call sf_gconvolve (im, c1, c2, l1, l2, swidth, Memr[imbuf],
+ Memr[denbuf], ncols, nlines, Memr[gker2d], Memi[skip],
+ fwidth, fwidth, gsums, dmin, dmax)
+
+ # Find the stars.
+ nstars = sf_stfind (out, Memr[imbuf], Memr[denbuf], ncols,
+ nlines, c1, c2, l1, l2, swidth, Memi[skip], fwidth,
+ fwidth, SF_HWHMPSF(sf), SF_THRESHOLD(sf), dmin, dmax,
+ ct, SF_NPIXMIN(sf), maglo, maghi, SF_ROUNDLO(sf),
+ SF_ROUNDHI(sf), SF_SHARPLO(sf), SF_SHARPHI(sf),
+ Memc[fmtstr], stid, verbose)
+
+ # Increment the sequence number.
+ stid = stid + nstars
+
+ # Free the memory.
+ call mfree (imbuf, TY_REAL)
+ call mfree (denbuf, TY_REAL)
+ call mfree (gker2d, TY_REAL)
+ call mfree (ngker2d, TY_REAL)
+ call mfree (skip, TY_INT)
+ }
+ }
+
+ # Print out the selection parameters.
+ if (verbose == YES) {
+ call printf ("\nSelection Parameters\n")
+ call printf ( " Maglo: %0.3f Maghi: %0.3f\n")
+ call pargr (SF_MAGLO(sf))
+ call pargr (SF_MAGHI(sf))
+ call printf ( " Roundlo: %0.3f Roundhi: %0.3f\n")
+ call pargr (SF_ROUNDLO(sf))
+ call pargr (SF_ROUNDHI(sf))
+ call printf ( " Sharplo: %0.3f Sharphi: %0.3f\n")
+ call pargr (SF_SHARPLO(sf))
+ call pargr (SF_SHARPHI(sf))
+ }
+
+ if (mw != NULL) {
+ call mw_ctfree (ct)
+ call mw_close (mw)
+ }
+ call sfree (sp)
+end
+
+
+# SF_STFIND -- Detect images in the convolved image and then compute image
+# characteristics using the original image.
+
+int procedure sf_stfind (out, imbuf, denbuf, ncols, nlines, c1, c2, l1, l2,
+ sepmin, skip, nxk, nyk, hwhmpsf, threshold, datamin, datamax,
+ ct, nmin, maglo, maghi, roundlo, roundhi, sharplo, sharphi,
+ fmtstr, stid, verbose)
+
+int out #I the output file descriptor
+real imbuf[ncols,nlines] #I the input data buffer
+real denbuf[ncols,nlines] #I the input density enhancements buffer
+int ncols, nlines #I the dimensions of the input buffers
+int c1, c2 #I the image columns limits
+int l1, l2 #I the image lines limits
+int sepmin #I the minimum object separation
+int skip[nxk,ARB] #I the pixel fitting array
+int nxk, nyk #I the dimensions of the fitting array
+real hwhmpsf #I the HWHM of the PSF in pixels
+real threshold #I the threshold for object detection
+real datamin, datamax #I the minimum and maximum good data values
+pointer ct #I the coordinate transformation pointer
+int nmin #I the minimum number of good object pixels
+real maglo,maghi #I the magnitude estimate limits
+real roundlo,roundhi #I the ellipticity estimate limits
+real sharplo, sharphi #I the sharpness estimate limits
+char fmtstr[ARB] #I the format string
+int stid #U the object sequence number
+int verbose #I verbose mode
+
+int line1, line2, inline, xmiddle, ymiddle, ntotal, nobjs, nstars
+pointer sp, cols, sharp, x, y, ellip, theta, npix, mag, size
+int sf_detect(), sf_test()
+
+begin
+ # Set up useful line and column limits.
+ line1 = 1 + sepmin + nyk / 2
+ line2 = nlines - sepmin - nyk / 2
+ xmiddle = 1 + nxk / 2
+ ymiddle = 1 + nyk / 2
+
+ # Set up a cylindrical buffers and some working space for
+ # the detected images.
+ call smark (sp)
+ call salloc (cols, ncols, TY_INT)
+ call salloc (x, ncols, TY_REAL)
+ call salloc (y, ncols, TY_REAL)
+ call salloc (mag, ncols, TY_REAL)
+ call salloc (npix, ncols, TY_INT)
+ call salloc (size, ncols, TY_REAL)
+ call salloc (ellip, ncols, TY_REAL)
+ call salloc (theta, ncols, TY_REAL)
+ call salloc (sharp, ncols, TY_REAL)
+
+ # Generate the starlist line by line.
+ ntotal = 0
+ do inline = line1, line2 {
+
+ # Detect local maximum in the density enhancement buffer.
+ nobjs = sf_detect (denbuf[1,inline-nyk/2-sepmin], ncols, sepmin,
+ nxk, nyk, threshold, Memi[cols])
+ if (nobjs <= 0)
+ next
+
+ # Do not skip the middle pixel in the moments computation.
+ call sf_moments (imbuf[1,inline-nyk/2], denbuf[1,inline-nyk/2],
+ ncols, skip, nxk, nyk, Memi[cols], Memr[x], Memr[y],
+ Memi[npix], Memr[mag], Memr[size], Memr[ellip], Memr[theta],
+ Memr[sharp], nobjs, datamin, datamax, threshold, hwhmpsf,
+ real (-sepmin - nxk / 2 + c1 - 1), real (inline - sepmin -
+ nyk + l1 - 1))
+
+ # Test the image characeteristics of detected objects.
+ nstars = sf_test (Memi[cols], Memr[x], Memr[y], Memi[npix],
+ Memr[mag], Memr[size], Memr[ellip], Memr[theta], Memr[sharp],
+ nobjs, real (c1 - 0.5), real (c2 + 0.5), real (l1 - 0.5),
+ real (l2 + 0.5), nmin, maglo, maghi, roundlo, roundhi,
+ sharplo, sharphi)
+
+ # Print results on the standard output.
+ if (verbose == YES)
+ call sf_write (STDOUT, Memi[cols], Memr[x], Memr[y],
+ Memr[mag], Memi[npix], Memr[size], Memr[ellip],
+ Memr[theta], Memr[sharp], nstars, ct, fmtstr,
+ ntotal + stid)
+
+ # Save the results in the file.
+ call sf_write (out, Memi[cols], Memr[x], Memr[y], Memr[mag],
+ Memi[npix], Memr[size], Memr[ellip], Memr[theta],
+ Memr[sharp], nstars, ct, fmtstr, ntotal + stid)
+
+ ntotal = ntotal + nstars
+
+ }
+
+ # Free space
+ call sfree (sp)
+
+ return (ntotal)
+end
+
+
+# SF_DETECT -- Detect stellar objects in an image line. In order to be
+# detected as a star the candidate object must be above threshold and have
+# a maximum pixel value greater than any pixels within sepmin pixels.
+
+int procedure sf_detect (density, ncols, sepmin, nxk, nyk, threshold, cols)
+
+real density[ncols, ARB] #I the input density enhancements array
+int ncols #I the x dimension of the input array
+int sepmin #I the minimum separation in pixels
+int nxk, nyk #I size of the fitting area
+real threshold #I density threshold
+int cols[ARB] #O column numbers of detected stars
+
+int i, j, k, ymiddle, nxhalf, nyhalf, ny, b2, nobjs, rj2, r2
+define nextpix_ 11
+
+begin
+ ymiddle = 1 + nyk / 2 + sepmin
+ nxhalf = nxk / 2
+ nyhalf = nyk / 2
+ ny = 2 * sepmin + 1
+ b2 = sepmin ** 2
+
+ # Loop over all the columns in an image line.
+ nobjs = 0
+ for (i = 1 + nxhalf + sepmin; i <= ncols - nxhalf - sepmin; ) {
+
+ # Test whether the density enhancement is above threshold.
+ if (density[i,ymiddle] < threshold)
+ goto nextpix_
+
+ # Test whether a given density enhancement satisfies the
+ # separation criterion.
+ do j = 1, ny {
+ rj2 = (j - sepmin - 1) ** 2
+ do k = i - sepmin, i + sepmin {
+ r2 = (i - k) ** 2 + rj2
+ if (r2 <= b2) {
+ if (density[i,ymiddle] < density[k,j+nyhalf])
+ goto nextpix_
+ }
+ }
+ }
+
+ # Add the detected object to the list.
+ nobjs = nobjs + 1
+ cols[nobjs] = i
+
+ # If a local maximum is detected there can be no need to
+ # check pixels in this row between i and i + sepmin.
+ i = i + sepmin
+nextpix_
+ # Work on the next pixel.
+ i = i + 1
+ }
+
+ return (nobjs)
+end
+
+
+# SF_MOMENTS -- Perform a moments analysis on the dectected objects.
+
+procedure sf_moments (data, den, ncols, skip, nxk, nyk, cols, x, y,
+ npix, mag, size, ellip, theta, sharp, nobjs, datamin, datamax,
+ threshold, hwhmpsf, xoff, yoff)
+
+real data[ncols,ARB] #I the input data array
+real den[ncols,ARB] #I the input density enhancements array
+int ncols #I the x dimension of the input buffer
+int skip[nxk,ARB] #I the input fitting array
+int nxk, nyk #I the dimensions of the fitting array
+int cols[ARB] #I the input initial positions
+real x[ARB] #O the output x coordinates
+real y[ARB] #O the output y coordinates
+int npix[ARB] #O the output area in number of pixels
+real mag[ARB] #O the output magnitude estimates
+real size[ARB] #O the output size estimates
+real ellip[ARB] #O the output ellipticity estimates
+real theta[ARB] #O the output position angle estimates
+real sharp[ARB] #O the output sharpness estimates
+int nobjs #I the number of objects
+real datamin, datamax #I the minium and maximum good data values
+real threshold #I threshold for moments computation
+real hwhmpsf #I the HWHM of the PSF
+real xoff, yoff #I the x and y coordinate offsets
+
+int i, j, k, xmiddle, ymiddle, sumn
+double pixval, sumix, sumiy, sumi, sumixx, sumixy, sumiyy, r2, dx, dy, diff
+double mean
+
+begin
+ # Initialize
+ xmiddle = 1 + nxk / 2
+ ymiddle = 1 + nyk / 2
+
+ # Compute the pixel sum, number of pixels, and the x and y centers.
+ do i = 1, nobjs {
+
+ # Estimate the background using the input data and the
+ # best fitting Gaussian amplitude
+ sumn = 0
+ sumi = 0.0
+ do j = 1, nyk {
+ do k = 1, nxk {
+ if (skip[k,j] == NO)
+ next
+ pixval = data[cols[i]-xmiddle+k,j]
+ if (pixval < datamin || pixval > datamax)
+ next
+ sumi = sumi + pixval
+ sumn = sumn + 1
+ }
+ }
+ if (sumn <= 0)
+ mean = data[cols[i],ymiddle] - den[cols[i],ymiddle]
+ else
+ mean = sumi / sumn
+
+ # Compute the first order moments.
+ sumi = 0.0
+ sumn = 0
+ sumix = 0.0d0
+ sumiy = 0.0d0
+ do j = 1, nyk {
+ do k = 1, nxk {
+ if (skip[k,j] == YES)
+ next
+ pixval = data[cols[i]-xmiddle+k,j]
+ if (pixval < datamin || pixval > datamax)
+ next
+ pixval = pixval - mean
+ if (pixval <= 0.0)
+ next
+ sumi = sumi + pixval
+ sumix = sumix + (cols[i] - xmiddle + k) * pixval
+ sumiy = sumiy + j * pixval
+ sumn = sumn + 1
+ }
+
+ }
+
+ # Use the first order moments to estimate the positions
+ # magnitude, area, and amplitude of the object.
+ if (sumi <= 0.0) {
+ x[i] = cols[i]
+ y[i] = (1.0 + nyk) / 2.0
+ mag[i] = INDEFR
+ npix[i] = 0
+ } else {
+ x[i] = sumix / sumi
+ y[i] = sumiy / sumi
+ mag[i] = -2.5 * log10 (sumi)
+ npix[i] = sumn
+ }
+
+ # Compute the second order central moments using the results of
+ # the first order moment analysis.
+ sumixx = 0.0d0
+ sumiyy = 0.0d0
+ sumixy = 0.0d0
+ do j = 1, nyk {
+ dy = j - y[i]
+ do k = 1, nxk {
+ if (skip[k,j] == YES)
+ next
+ pixval = data[cols[i]-xmiddle+k,j]
+ if (pixval < datamin || pixval > datamax)
+ next
+ pixval = pixval - mean
+ if (pixval <= 0.0)
+ next
+ dx = cols[i] - xmiddle + k - x[i]
+ sumixx = sumixx + pixval * dx ** 2
+ sumixy = sumixy + pixval * dx * dy
+ sumiyy = sumiyy + pixval * dy ** 2
+ }
+ }
+
+ # Use the second order central moments to estimate the size,
+ # ellipticity, position angle, and sharpness of the objects.
+ if (sumi <= 0.0) {
+ size[i] = 0.0
+ ellip[i] = 0.0
+ theta[i] = 0.0
+ sharp[i] = INDEFR
+ } else {
+ sumixx = sumixx / sumi
+ sumixy = sumixy / sumi
+ sumiyy = sumiyy / sumi
+ r2 = sumixx + sumiyy
+ if (r2 <= 0.0) {
+ size[i] = 0.0
+ ellip[i] = 0.0
+ theta[i] = 0.0
+ sharp[i] = INDEFR
+ } else {
+ size[i] = sqrt (LN_2 * r2)
+ sharp[i] = size[i] / hwhmpsf
+ diff = sumixx - sumiyy
+ ellip[i] = sqrt (diff ** 2 + 4.0d0 * sumixy ** 2) / r2
+ if (diff == 0.0d0 && sumixy == 0.0d0)
+ theta[i] = 0.0
+ else
+ theta[i] = RADTODEG (0.5d0 * atan2 (2.0d0 * sumixy,
+ diff))
+ if (theta[i] < 0.0)
+ theta[i] = theta[i] + 180.0
+ }
+ }
+
+ # Convert the computed coordinates to the image system.
+ x[i] = x[i] + xoff
+ y[i] = y[i] + yoff
+ }
+end
+
+
+# SF_TEST -- Check that the detected objects are in the image, contain
+# enough pixels above background to be measurable objects, and are within
+# the specified magnitude, roundness and sharpness range.
+
+int procedure sf_test (cols, x, y, npix, mag, size, ellip, theta, sharps,
+ nobjs, c1, c2, l1, l2, nmin, maglo, maghi, roundlo, roundhi,
+ sharplo, sharphi)
+
+int cols[ARB] #U the column ids of detected object
+real x[ARB] #U the x position estimates
+real y[ARB] #U the y positions estimates
+int npix[ARB] #U the area estimates
+real mag[ARB] #U the magnitude estimates
+real size[ARB] #U the size estimates
+real ellip[ARB] #U the ellipticity estimates
+real theta[ARB] #U the position angle estimates
+real sharps[ARB] #U sharpness estimates
+int nobjs #I the number of detected objects
+real c1, c2 #I the image column limits
+real l1, l2 #I the image line limits
+int nmin #I the minimum area
+real maglo, maghi #I the magnitude limits
+real roundlo, roundhi #I the roundness limits
+real sharplo, sharphi #I the sharpness limits
+
+int i, nstars
+
+begin
+ # Loop over the detected objects.
+ nstars = 0
+ do i = 1, nobjs {
+
+ if (x[i] < c1 || x[i] > c2)
+ next
+ if (y[i] < l1 || y[i] > l2)
+ next
+ if (npix[i] < nmin)
+ next
+ if (mag[i] < maglo || mag[i] > maghi)
+ next
+ if (ellip[i] < roundlo || ellip[i] > roundhi)
+ next
+ if (! IS_INDEFR(sharps[i]) && (sharps[i] < sharplo ||
+ sharps[i] > sharphi))
+ next
+
+ # Add object to the list.
+ nstars = nstars + 1
+ cols[nstars] = cols[i]
+ x[nstars] = x[i]
+ y[nstars] = y[i]
+ mag[nstars] = mag[i]
+ npix[nstars] = npix[i]
+ size[nstars] = size[i]
+ ellip[nstars] = ellip[i]
+ theta[nstars] = theta[i]
+ sharps[nstars] = sharps[i]
+ }
+
+ return (nstars)
+end
+
+
+# SF_WRITE -- Write the results to the output file.
+
+procedure sf_write (fd, cols, x, y, mag, npix, size, ellip, theta, sharp,
+ nstars, ct, fmtstr, stid)
+
+int fd #I the output file descriptor
+int cols[ARB] #I column numbers
+real x[ARB] #I xcoords
+real y[ARB] #I y coords
+real mag[ARB] #I magnitudes
+int npix[ARB] #I number of pixels
+real size[ARB] #I object sizes
+real ellip[ARB] #I ellipticities
+real theta[ARB] #I position angles
+real sharp[ARB] #I sharpnesses
+int nstars #I number of detected stars in the line
+pointer ct #I coordinate transformation
+char fmtstr[ARB] #I the output format string
+int stid #I output file sequence number
+
+double lx, ly, wx, wy
+int i
+
+begin
+ if (fd == NULL)
+ return
+
+ do i = 1, nstars {
+ call fprintf (fd, fmtstr)
+ call pargr (x[i])
+ call pargr (y[i])
+ if (ct != NULL) {
+ lx = x[i]
+ ly = y[i]
+ call mw_c2trand (ct, lx, ly, wx, wy)
+ call pargd (wx)
+ call pargd (wy)
+ }
+ call pargr (mag[i])
+ call pargi (npix[i])
+ call pargr (size[i])
+ call pargr (ellip[i])
+ call pargr (theta[i])
+ call pargr (sharp[i])
+ call pargi (stid + i - 1)
+ }
+end
diff --git a/pkg/images/imcoords/src/sftools.x b/pkg/images/imcoords/src/sftools.x
new file mode 100644
index 00000000..02bec379
--- /dev/null
+++ b/pkg/images/imcoords/src/sftools.x
@@ -0,0 +1,68 @@
+include <mach.h>
+include "starfind.h"
+
+# SF_GPARS-- Read in the star finding parameters from the datapars file.
+
+procedure sf_gpars (sf)
+
+pointer sf #I pointer to the star finding structure
+
+int clgeti()
+real clgetr()
+
+begin
+ # Initialize the data structure.
+ call sf_init (sf)
+
+ # Fetch the star finding parameters.
+ SF_HWHMPSF(sf) = clgetr ("hwhmpsf")
+ SF_FRADIUS(sf) = clgetr ("fradius")
+ SF_THRESHOLD(sf) = clgetr ("threshold")
+ SF_DATAMIN(sf) = clgetr ("datamin")
+ SF_DATAMAX(sf) = clgetr ("datamax")
+ SF_SEPMIN(sf) = clgetr ("sepmin")
+ SF_NPIXMIN(sf) = clgeti ("npixmin")
+ SF_MAGLO(sf) = clgetr ("maglo")
+ SF_MAGHI(sf) = clgetr ("maghi")
+ SF_ROUNDLO(sf) = clgetr ("roundlo")
+ SF_ROUNDHI(sf) = clgetr ("roundhi")
+ SF_SHARPLO(sf) = clgetr ("sharplo")
+ SF_SHARPHI(sf) = clgetr ("sharphi")
+end
+
+
+# SF_INIT -- Initialize the STARFIND task data structure and set the
+# star finding parameters to their default values.
+
+procedure sf_init (sf)
+
+pointer sf #U pointer to the star finding structure
+
+begin
+ call calloc (sf, LEN_STARFIND, TY_STRUCT)
+
+ SF_HWHMPSF(sf) = DEF_HWHMPSF
+ SF_FRADIUS(sf) = DEF_FRADIUS
+ SF_THRESHOLD(sf) = DEF_THRESHOLD
+ SF_DATAMIN(sf) = DEF_DATAMIN
+ SF_DATAMAX(sf) = DEF_DATAMAX
+ SF_SHARPLO(sf) = DEF_SHARPLO
+ SF_SHARPHI(sf) = DEF_SHARPHI
+ SF_ROUNDLO(sf) = DEF_ROUNDLO
+ SF_ROUNDHI(sf) = DEF_ROUNDHI
+ SF_MAGLO(sf) = DEF_MAGLO
+ SF_MAGHI(sf) = DEF_MAGHI
+ SF_SEPMIN(sf) = DEF_SEPMIN
+ SF_NPIXMIN(sf) = DEF_NPIXMIN
+end
+
+
+# SF_FREE -- Free the STARFIND task data structure.
+
+procedure sf_free (sf)
+
+pointer sf #U pointer to the star finding structure
+
+begin
+ call mfree (sf, TY_STRUCT)
+end
diff --git a/pkg/images/imcoords/src/skyctran.x b/pkg/images/imcoords/src/skyctran.x
new file mode 100644
index 00000000..22d182e6
--- /dev/null
+++ b/pkg/images/imcoords/src/skyctran.x
@@ -0,0 +1,2057 @@
+include <fset.h>
+include <ctype.h>
+include <math.h>
+include <pkg/skywcs.h>
+
+define HELPFILE1 "imcoords$src/skycur.key"
+define HELPFILE2 "imcoords$src/ttycur.key"
+
+define CURCMDS "|show|isystem|osystem||ounits|oformats|"
+define TYPECMDS "|show|isystem|osystem|iunits|ounits|oformats|"
+
+define CCMD_SHOW 1
+define CCMD_ISYSTEM 2
+define CCMD_OSYSTEM 3
+define CCMD_IUNITS 4
+define CCMD_OUNITS 5
+define CCMD_OFORMATS 6
+
+
+# SK_TTYTRAN -- Transform the typed coordinate list.
+
+procedure sk_ttytran (infd, outfd, mwin, mwout, cooin, cooout, ilngunits,
+ ilatunits, olngunits, olatunits, olngformat, olatformat)
+
+int infd #I the input file descriptor
+int outfd #I the input file descriptor
+pointer mwin #I the input image wcs
+pointer mwout #I the output image wcs
+pointer cooin #I the input coordinate descriptor
+pointer cooout #I the output coordinate descriptor
+int ilngunits #I the input ra/longitude units
+int ilatunits #I the input dec/latitude units
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+char olngformat[ARB] #I the output ra/longitude format
+char olatformat[ARB] #I the output dec/latitude format
+
+double ilng, ilat, pilng, pilat, px, rv, tlng, tlat, olng, olat
+int newsystem, newformat, newobject, tilngunits, tilatunits, tolngunits
+int tolatunits, ip, key
+pointer ctin, ctout, sp, cmd, fmtstr, tolngformat, tolatformat, str1, str2
+double sl_da1p()
+int scan(), nscan(), sk_stati(), ctod()
+pointer sk_ictran(), sk_octran()
+errchk sk_ictran(), sk_octran()
+
+begin
+ # Initialize.
+ newsystem = YES
+ newformat = YES
+ newobject = NO
+ ctin = NULL
+ ctout = NULL
+
+ # Get some working space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+ call salloc (tolngformat, SZ_FNAME, TY_CHAR)
+ call salloc (tolatformat, SZ_FNAME, TY_CHAR)
+ call salloc (str1, SZ_FNAME, TY_CHAR)
+ call salloc (str2, SZ_FNAME, TY_CHAR)
+
+ # Loop over the input.
+ while (scan() != EOF) {
+ call gargstr (Memc[cmd], SZ_LINE)
+ key = Memc[cmd]
+ switch (key) {
+
+ case '?':
+ call pagefile (HELPFILE2, "[space=cmhelp,q=quit,?=help]")
+
+ case 'q':
+ break
+
+ case ':':
+ call sk_ccolon (infd, outfd, cooin, cooout, mwin, mwout,
+ ilngunits, ilatunits, olngunits, olatunits, olngformat,
+ olatformat, Memc[cmd+1], TYPECMDS, newsystem, newformat)
+
+ default:
+ newobject = YES
+ }
+
+ if (newobject == NO)
+ next
+
+ # Decode the input coordinates.
+ call sscan (Memc[cmd])
+ call gargwrd (Memc[str1], SZ_FNAME)
+ call gargwrd (Memc[str2], SZ_FNAME)
+ if (nscan() < 2)
+ next
+ ip = 1
+ if (ctod (Memc[str1], ip, ilng) <= 0)
+ next
+ ip = 1
+ if (ctod (Memc[str2], ip, ilat) <= 0)
+ next
+ call gargwrd (Memc[str1], SZ_FNAME)
+ call gargwrd (Memc[str2], SZ_FNAME)
+
+
+ # Decode the proper motions.
+ if (nscan() < 4) {
+ pilng = INDEFD
+ pilat = INDEFD
+ } else {
+ ip = 1
+ if (ctod (Memc[str1], ip, pilng) <= 0)
+ next
+ ip = 1
+ if (ctod (Memc[str2], ip, pilat) <= 0)
+ next
+ if (IS_INDEFD(pilng) || IS_INDEFD(pilat)) {
+ pilng = INDEFD
+ pilat = INDEFD
+ }
+ }
+
+ # Decode the parallax and radial velocity
+ call gargwrd (Memc[str1], SZ_FNAME)
+ call gargwrd (Memc[str2], SZ_FNAME)
+ if (nscan() < 6) {
+ px = 0.0d0
+ rv = 0.0d0
+ } else {
+ ip = 1
+ if (ctod (Memc[str1], ip, px) <= 0)
+ next
+ ip = 1
+ if (ctod (Memc[str2], ip, rv) <= 0)
+ next
+ if (IS_INDEFD(px))
+ px = 0.0d0
+ if (IS_INDEFD(rv))
+ rv = 0.0d0
+ }
+
+ # Compile the mwcs transformation.
+ if (newsystem == YES) {
+ if (ctin != NULL)
+ call mw_ctfree (cooin)
+ if (ctout != NULL)
+ call mw_ctfree (cooout)
+ iferr {
+ ctin = sk_ictran (cooin, mwin)
+ ctout = sk_octran (cooout, mwout)
+ } then {
+ ctin = NULL
+ ctout = NULL
+ }
+ newsystem = NO
+ }
+
+ # Set the input and output coordinate units and the output format.
+ if (newformat == YES) {
+ if (ilngunits <= 0)
+ tilngunits = sk_stati (cooin, S_NLNGUNITS)
+ else
+ tilngunits = ilngunits
+ if (ilatunits <= 0)
+ tilatunits = sk_stati (cooin, S_NLATUNITS)
+ else
+ tilatunits = ilatunits
+ if (olngunits <= 0)
+ tolngunits = sk_stati (cooout, S_NLNGUNITS)
+ else
+ tolngunits = olngunits
+ if (olatunits <= 0)
+ tolatunits = sk_stati (cooout, S_NLATUNITS)
+ else
+ tolatunits = olatunits
+ call sk_oformats (cooin, cooout, olngformat, olatformat,
+ tolngunits, tolatunits, Memc[tolngformat],
+ Memc[tolatformat], SZ_FNAME)
+ call sk_iunits (cooin, mwin, tilngunits, tilatunits,
+ tilngunits, tilatunits)
+ call sk_ounits (cooout, mwout, tolngunits, tolatunits,
+ tolngunits, tolatunits)
+ call sprintf (Memc[fmtstr], SZ_LINE, "%%s %s %s\n")
+ call pargstr (Memc[tolngformat])
+ call pargstr (Memc[tolatformat])
+ newformat = NO
+ }
+
+ # Perform the coordinate transformation.
+ if (sk_stati(cooin, S_STATUS) == ERR || sk_stati (cooout,
+ S_STATUS) == ERR) {
+
+ olng = ilng
+ olat = ilat
+
+ } else {
+
+ # Compute the input coordinate to world coordinates in radians.
+ call sk_incc (cooin, mwin, ctin, tilngunits, tilatunits, ilng,
+ ilat, olng, olat)
+
+ # Convert the proper motions to the correct units.
+ if (!IS_INDEFD(pilng) && !IS_INDEFD(pilat)) {
+ pilng = DEGTORAD(pilng * 15.0d0 / 3600.0d0)
+ pilat = DEGTORAD(pilat / 3600.0d0)
+ call sl_dtps (pilng / 15.0d0, pilat, 0.0d0, olat, pilng,
+ pilat)
+ pilng = sl_da1p (pilng)
+ pilat = pilat - olat
+ } else {
+ pilng = INDEFD
+ pilat = INDEFD
+ }
+
+ # Perform the transformation.
+ call sk_lltran (cooin, cooout, olng, olat, pilng, pilat, px,
+ rv, tlng, tlat)
+
+ # Convert the celestial coordinates in radians to the output
+ # coordinates.
+ call sk_outcc (cooout, mwout, ctout, tolngunits, tolatunits,
+ tlng, tlat, olng, olat)
+ }
+
+ # Write the results.
+ call fprintf (outfd, Memc[fmtstr])
+ call pargstr (Memc[cmd])
+ call pargd (olng)
+ call pargd (olat)
+ if (outfd != STDOUT) {
+ call printf (Memc[fmtstr])
+ call pargstr (Memc[cmd])
+ call pargd (olng)
+ call pargd (olat)
+ }
+
+ newobject = NO
+ }
+
+ call sfree (sp)
+end
+
+
+define MAX_FIELDS 100 # Maximum number of fields in list
+define TABSIZE 8 # Spacing of tab stops
+
+# SK_LISTRAN -- Transform the coordinate list.
+
+procedure sk_listran (infd, outfd, mwin, mwout, cooin, cooout, lngcolumn,
+ latcolumn, plngcolumn, platcolumn, pxcolumn, rvcolumn, ilngunits,
+ ilatunits, olngunits, olatunits, olngformat, olatformat,
+ min_sigdigits, transform)
+
+int infd #I the input file descriptor
+int outfd #I the input file descriptor
+pointer mwin #I the input image wcs
+pointer mwout #I the output image wcs
+pointer cooin #I the input coordinate descriptor
+pointer cooout #I the output coordinate descriptor
+int lngcolumn #I the input ra/longitude column
+int latcolumn #I the input dec/latitude column
+int plngcolumn #I the input ra/longitude pm column
+int platcolumn #I the input dec/latitude pm column
+int pxcolumn #I the input parallax column
+int rvcolumn #I the input radial column
+int ilngunits #I the input ra/longitude units
+int ilatunits #I the input dec/latitude units
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+char olngformat[ARB] #I the output ra/longitude format
+char olatformat[ARB] #I the output dec/latitude format
+int min_sigdigits #I the minimum number of significant digits
+bool transform #I transform the input file
+
+double ilng, ilat, tlng, tlat, olng, olat, pilng, pilat, px, rv
+int nline, ip, max_fields, nfields, offset, nchars, nsdig_lng, nsdig_lat
+int tilngunits, tilatunits, tolngunits, tolatunits
+pointer sp, inbuf, linebuf, field_pos, outbuf, ctin, ctout
+pointer tolngformat, tolatformat
+double sl_da1p()
+int sk_stati(), li_get_numd(), getline()
+pointer sk_ictran(), sk_octran()
+errchk sk_ictran(), sk_octran()
+
+begin
+ # Compile the input abd output transformations.
+ # coordinate units.
+ iferr {
+ ctin = sk_ictran (cooin, mwin)
+ ctout = sk_octran (cooout, mwout)
+ } then
+ return
+
+ # Allocate some memory.
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (linebuf, SZ_LINE, TY_CHAR)
+ call salloc (field_pos, MAX_FIELDS, TY_INT)
+ call salloc (outbuf, SZ_LINE, TY_CHAR)
+ call salloc (tolngformat, SZ_FNAME, TY_CHAR)
+ call salloc (tolatformat, SZ_FNAME, TY_CHAR)
+
+ # Set the default input and output units.
+ if (ilngunits <= 0)
+ tilngunits = sk_stati (cooin, S_NLNGUNITS)
+ else
+ tilngunits = ilngunits
+ if (ilatunits <= 0)
+ tilatunits = sk_stati (cooin, S_NLATUNITS)
+ else
+ tilatunits = ilatunits
+ if (olngunits <= 0)
+ tolngunits = sk_stati (cooout, S_NLNGUNITS)
+ else
+ tolngunits = olngunits
+ if (olatunits <= 0)
+ tolatunits = sk_stati (cooout, S_NLATUNITS)
+ else
+ tolatunits = olatunits
+
+ # Set the output format.
+ call sk_oformats (cooin, cooout, olngformat, olatformat,
+ tolngunits, tolatunits, Memc[tolngformat], Memc[tolatformat],
+ SZ_FNAME)
+
+ # Check the input and output units.
+ call sk_iunits (cooin, mwin, tilngunits, tilatunits, tilngunits,
+ tilatunits)
+ call sk_ounits (cooout, mwout, tolngunits, tolatunits, tolngunits,
+ tolatunits)
+
+ # Loop over the input coordinates.
+ max_fields = MAX_FIELDS
+ for (nline = 1; getline (infd, Memc[inbuf]) != EOF; nline = nline + 1) {
+
+ # Check for blank lines and comment lines.
+ for (ip = inbuf; IS_WHITE(Memc[ip]); ip = ip + 1)
+ ;
+ if (Memc[ip] == '#') {
+ # Pass comment lines on to the output unchanged.
+ call putline (outfd, Memc[inbuf])
+ next
+ } else if (Memc[ip] == '\n' || Memc[ip] == EOS) {
+ # Blank lines too.
+ call putline (outfd, Memc[inbuf])
+ next
+ }
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[linebuf], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[linebuf], Memi[field_pos], max_fields,
+ nfields)
+
+ if (lngcolumn > nfields || latcolumn > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Not enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ offset = Memi[field_pos+lngcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], ilng, nsdig_lng)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad x value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ offset = Memi[field_pos+latcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], ilat, nsdig_lat)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad y value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ # Get the proper motions.
+ if (! IS_INDEFI(plngcolumn) && ! IS_INDEFI(platcolumn)) {
+ if (plngcolumn > nfields || platcolumn > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Not enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ offset = Memi[field_pos+plngcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], pilng, nsdig_lng)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad pm value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ offset = Memi[field_pos+platcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], pilat, nsdig_lat)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad pm value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ if (IS_INDEFD(pilng) || IS_INDEFD(pilat)) {
+ pilng = INDEFD
+ pilat = INDEFD
+ }
+ } else {
+ pilng = INDEFD
+ pilat = INDEFD
+ }
+
+ # Get the parallax value.
+ if (! IS_INDEFI(pxcolumn)) {
+ if (pxcolumn > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Not enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ offset = Memi[field_pos+pxcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], px, nsdig_lat)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf (
+ "Bad parallax value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ if (IS_INDEFD(px))
+ px = 0.0d0
+ } else
+ px = 0.0d0
+
+ # Get the parallax value.
+ if (! IS_INDEFI(rvcolumn)) {
+ if (rvcolumn > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Not enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ offset = Memi[field_pos+rvcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], rv, nsdig_lat)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf (
+ "Bad radial velocity value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ if (IS_INDEFD(rv))
+ rv = 0.0d0
+ } else
+ rv = 0.0d0
+
+ # Convert the input coordinates to world coordinates in radians.
+ call sk_incc (cooin, mwin, ctin, tilngunits, tilatunits, ilng,
+ ilat, olng, olat)
+
+ # Convert the proper motions to the correct units.
+ if (IS_INDEFD(pilng) || IS_INDEFD(pilat)) {
+ pilng = INDEFD
+ pilat = INDEFD
+ } else {
+ pilng = DEGTORAD(pilng * 15.0d0 / 3600.0d0)
+ pilat = DEGTORAD(pilat / 3600.0d0)
+ call sl_dtps (pilng / 15.0d0, pilat, 0.0d0, olat, pilng, pilat)
+ pilng = sl_da1p (pilng)
+ pilat = pilat - olat
+ }
+
+ # Perform the transformation.
+ call sk_lltran (cooin, cooout, olng, olat, pilng, pilat,
+ px, rv, tlng, tlat)
+
+ # Convert the output celestial coordinates from radians to output
+ # coordinates.
+ call sk_outcc (cooout, mwout, ctout, tolngunits, tolatunits,
+ tlng, tlat, olng, olat)
+
+ # Output the results.
+ if (transform) {
+ call li_pack_lined (Memc[linebuf], Memc[outbuf], SZ_LINE,
+ Memi[field_pos], nfields, lngcolumn, latcolumn, olng,
+ olat, Memc[tolngformat], Memc[tolatformat], nsdig_lng,
+ nsdig_lat, min_sigdigits)
+ } else {
+ call li_append_lined (Memc[linebuf], Memc[outbuf], SZ_LINE,
+ olng, olat, Memc[tolngformat], Memc[tolatformat],
+ nsdig_lng, nsdig_lat, min_sigdigits)
+ }
+ call putline (outfd, Memc[outbuf])
+ }
+
+ call sfree (sp)
+end
+
+
+# SK_COPYTRAN -- Copy the input coordinate file to the output coordinate file.
+
+procedure sk_copytran (infd, outfd, lngcolumn, latcolumn, transform)
+
+int infd #I the input file descriptor
+int outfd #I the output file descriptor
+int lngcolumn #I the input ra/longitude column
+int latcolumn #I the input dec/latitude column
+bool transform #I tranform the input file
+
+double ilng, ilat
+int ip, nline, max_fields, nfields, xoffset, yoffset, nchars
+int nsdig_lng, nsdig_lat, xwidth, ywidth
+pointer sp, inbuf, linebuf, outbuf, field_pos
+int getline(), li_get_numd()
+
+begin
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (linebuf, SZ_LINE, TY_CHAR)
+ call salloc (outbuf, SZ_LINE, TY_CHAR)
+ call salloc (field_pos, MAX_FIELDS, TY_INT)
+
+ if (transform) {
+ while (getline (infd, Memc[inbuf]) != EOF)
+ call putline (outfd, Memc[inbuf])
+ } else {
+ max_fields = MAX_FIELDS
+ for (nline = 1; getline (infd, Memc[inbuf]) != EOF;
+ nline = nline + 1) {
+
+ # Check for blank lines and comment lines.
+ for (ip = inbuf; IS_WHITE(Memc[ip]); ip = ip + 1)
+ ;
+ if (Memc[ip] == '#') {
+ # Pass comment lines on to the output unchanged.
+ call putline (outfd, Memc[inbuf])
+ next
+ } else if (Memc[ip] == '\n' || Memc[ip] == EOS) {
+ # Blank lines too.
+ call putline (outfd, Memc[inbuf])
+ next
+ }
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[linebuf], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[linebuf], Memi[field_pos],
+ max_fields, nfields)
+
+ if (lngcolumn > nfields || latcolumn > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Not enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ xoffset = Memi[field_pos+lngcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+xoffset-1], ilng, nsdig_lng)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad x value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ xwidth = Memi[field_pos+lngcolumn] - Memi[field_pos+lngcolumn-1]
+
+ yoffset = Memi[field_pos+latcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+yoffset-1], ilat, nsdig_lat)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad y value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ ywidth = Memi[field_pos+latcolumn] - Memi[field_pos+latcolumn-1]
+
+ call li_cappend_line (Memc[linebuf], Memc[outbuf], SZ_LINE,
+ xoffset, yoffset, xwidth, ywidth)
+ call putline (outfd, Memc[outbuf])
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# SK_CURTRAN -- Transform the cursor coordinate list.
+
+procedure sk_curtran (outfd, mwin, mwout, cooin, cooout, olngunits, olatunits,
+ olngformat, olatformat, transform)
+
+int outfd #I the input file descriptor
+pointer mwin #I the input image wcs
+pointer mwout #I the output image wcs
+pointer cooin #I the input coordinate descriptor
+pointer cooout #I the output coordinate descriptor
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+char olngformat[ARB] #I the output ra/longitude format
+char olatformat[ARB] #I the output dec/latitude format
+bool transform #I transform the input file
+
+double ilng, ilat, tlng, tlat, olng, olat
+int wcs, key, tolngunits, tolatunits, newsystem, newformat, newobject
+int ijunk
+pointer sp, cmd, fmtstr, ctin, ctout, tolngformat, tolatformat
+real wx, wy
+int clgcur(), sk_stati()
+pointer sk_ictran(), sk_octran()
+errchk sk_ictran(), sk_octran()
+
+begin
+ # Initialize.
+ newsystem = YES
+ newformat = YES
+ newobject = NO
+ ctin = NULL
+ ctout = NULL
+
+ # Get some working space.
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+ call salloc (tolngformat, SZ_FNAME, TY_CHAR)
+ call salloc (tolatformat, SZ_FNAME, TY_CHAR)
+
+ while (clgcur ("icommands", wx, wy, wcs, key, Memc[cmd],
+ SZ_LINE) != EOF) {
+
+ newobject = NO
+ ilng = wx
+ ilat = wy
+
+ switch (key) {
+
+ case '?':
+ call pagefile (HELPFILE1, "[space=cmhelp,q=quit,?=help]")
+
+ case 'q':
+ break
+
+ case ':':
+ call sk_ccolon (NULL, outfd, cooin, cooout, mwin, mwout,
+ ijunk, ijunk, olngunits, olatunits, olngformat,
+ olatformat, Memc[cmd], CURCMDS, newsystem, newformat)
+
+ case ' ':
+ newobject = YES
+
+ default:
+ ;
+ }
+
+ if (newobject == NO)
+ next
+
+ # Compile the mwcs transformation.
+ if (newsystem == YES) {
+ if (ctin != NULL)
+ call mw_ctfree (ctin)
+ if (ctout != NULL)
+ call mw_ctfree (ctout)
+ iferr {
+ ctin = sk_ictran (cooin, mwin)
+ ctout = sk_octran (cooout, mwout)
+ } then {
+ ctin = NULL
+ ctout = NULL
+ }
+ newsystem = NO
+ }
+
+ # Set the output coordinates units and format.
+ if (newformat == YES) {
+ if (olngunits <= 0)
+ tolngunits = sk_stati (cooout, S_NLNGUNITS)
+ else
+ tolngunits = olngunits
+ if (olatunits <= 0)
+ tolatunits = sk_stati (cooout, S_NLATUNITS)
+ else
+ tolatunits = olatunits
+ call sk_oformats (cooin, cooout, olngformat, olatformat,
+ tolngunits, tolatunits, Memc[tolngformat],
+ Memc[tolatformat], SZ_FNAME)
+ call sk_ounits (cooout, mwout, tolngunits, tolatunits,
+ tolngunits, tolatunits)
+ if (sk_stati(cooin, S_STATUS) == ERR || sk_stati(cooout,
+ S_STATUS) == ERR) {
+ if (transform)
+ call strcpy ("%10.3f %10.3f\n", Memc[fmtstr], SZ_LINE)
+ else
+ call strcpy ("%10.3f %10.3f %10.3f %10.3f\n",
+ Memc[fmtstr], SZ_LINE)
+ } else {
+ if (transform) {
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s\n")
+ call pargstr (Memc[tolngformat])
+ call pargstr (Memc[tolatformat])
+ } else {
+ call sprintf (Memc[fmtstr], SZ_LINE,
+ "%%10.3f %%10.3f %s %s\n")
+ call pargstr (Memc[tolngformat])
+ call pargstr (Memc[tolatformat])
+ }
+ }
+ newformat = NO
+ }
+
+ # Compute the transformation.
+ if (sk_stati(cooin, S_STATUS) == ERR || sk_stati(cooout,
+ S_STATUS) == ERR) {
+ olng = ilng
+ olat = ilat
+ } else {
+ call sk_incc (cooin, mwin, ctin, SKY_DEGREES, SKY_DEGREES,
+ ilng, ilat, olng, olat)
+ call sk_lltran (cooin, cooout, olng, olat, INDEFD, INDEFD,
+ 0.0d0, 0.0d0, tlng, tlat)
+ call sk_outcc (cooout, mwout, ctout, tolngunits,
+ tolatunits, tlng, tlat, olng, olat)
+ }
+
+ # Write out the results.
+ if (transform) {
+ call fprintf (outfd, Memc[fmtstr])
+ call pargd (olng)
+ call pargd (olat)
+ } else {
+ call fprintf (outfd, Memc[fmtstr])
+ call pargr (wx)
+ call pargr (wy)
+ call pargd (olng)
+ call pargd (olat)
+ }
+
+ newobject = NO
+
+ }
+
+ call sfree (sp)
+end
+
+# SKY_CCOLON -- Process image cursor colon commands.
+
+procedure sk_ccolon (infd, outfd, cooin, cooout, mwin, mwout, ilngunits,
+ ilatunits, olngunits, olatunits, olngformat, olatformat, cmdstr,
+ cmdlist, newsystem, newformat)
+
+int infd #I the input file descriptor
+int outfd #I the output file descriptor
+pointer cooin #U the input coordinate descriptor
+pointer cooout #U the output coordinate descriptor
+pointer mwin #U the input image wcs
+pointer mwout #U the output image wcs
+int ilngunits #U the input ra/longitude units
+int ilatunits #U the input dec/latitude units
+int olngunits #U the output ra/longitude units
+int olatunits #U the output dec/latitude units
+char olngformat[ARB] #U the output ra/longitude format
+char olatformat[ARB] #U the output dec/latitude format
+char cmdstr[ARB] #I the input command string
+char cmdlist[ARB] #I the input command list
+int newsystem #U new coordinate system ?
+int newformat #U new coordinate format ?
+
+int ncmd, stat
+pointer sp, cmd, str1, str2, str3, str4, tmw, tcoo
+int sk_stati(), strdic(), sk_decwcs()
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (str1, SZ_FNAME, TY_CHAR)
+ call salloc (str2, SZ_FNAME, TY_CHAR)
+ call salloc (str3, SZ_FNAME, TY_CHAR)
+ call salloc (str4, SZ_FNAME, TY_CHAR)
+
+ # Get the command.
+ call sscan (cmdstr)
+ call gargwrd (Memc[cmd], SZ_LINE)
+ if (Memc[cmd] == EOS) {
+ call sfree (sp)
+ return
+ }
+
+ # Process the command.
+ ncmd = strdic (Memc[cmd], Memc[cmd], SZ_LINE, cmdlist)
+ call gargstr (Memc[cmd], SZ_LINE)
+ switch (ncmd) {
+
+ case CCMD_SHOW:
+ call fprintf (outfd, "\n")
+ if (sk_stati (cooin, S_STATUS) == ERR)
+ call fprintf (outfd,
+ "# Error decoding the input coordinate system\n")
+ call sk_stats (cooin, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiwrite (outfd, "Insystem", Memc[str1], mwin,
+ cooin)
+ if (infd == NULL)
+ call sk_wiformats (cooin, ilngunits, ilatunits, "%10.3f",
+ "%10.3f", Memc[str1], Memc[str2], Memc[str3], Memc[str4],
+ SZ_FNAME)
+ else
+ call sk_wiformats (cooin, ilngunits, ilatunits, "INDEF",
+ "INDEF", Memc[str1], Memc[str2], Memc[str3], Memc[str4],
+ SZ_FNAME)
+ call fprintf (outfd, "# Units: %s %s Format: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call pargstr (Memc[str3])
+ call pargstr (Memc[str4])
+ if (sk_stati(cooout, S_STATUS) == ERR)
+ call fprintf (outfd,
+ "# Error decoding the output coordinate system\n")
+ call sk_stats (cooout, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiwrite (outfd, "Outsystem", Memc[str1], mwout,
+ cooout)
+ call sk_woformats (cooin, cooout, olngunits, olatunits,
+ olngformat, olatformat, Memc[str1], Memc[str2], Memc[str3],
+ Memc[str4], SZ_FNAME)
+ call fprintf (outfd, "# Units: %s %s Format: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call pargstr (Memc[str3])
+ call pargstr (Memc[str4])
+ call fprintf (outfd, "\n")
+
+ if (outfd != STDOUT) {
+ call printf ("\n")
+ if (sk_stati (cooin, S_STATUS) == ERR)
+ call printf (
+ "Error decoding the input coordinate system\n")
+ call sk_stats (cooin, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiprint ("Insystem", Memc[str1], mwin, cooin)
+ if (infd == NULL)
+ call sk_wiformats (cooin, ilngunits, ilatunits, "%10.3f",
+ "%10.3f", Memc[str1], Memc[str2], Memc[str3],
+ Memc[str4], SZ_FNAME)
+ else
+ call sk_wiformats (cooin, ilngunits, ilatunits, "INDEF",
+ "INDEF", Memc[str1], Memc[str2], Memc[str3], Memc[str4],
+ SZ_FNAME)
+ call printf ("# Units: %s %s Format: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call pargstr (Memc[str3])
+ call pargstr (Memc[str4])
+ if (sk_stati(cooout, S_STATUS) == ERR)
+ call printf (
+ "Error decoding the output coordinate system\n")
+ call sk_stats (cooout, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiprint ("Outsystem", Memc[str1], mwout, cooout)
+ call sk_woformats (cooin, cooout, olngunits, olatunits,
+ olngformat, olatformat, Memc[str1], Memc[str2], Memc[str3],
+ Memc[str4], SZ_FNAME)
+ call printf (" Units: %s %s Format: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call pargstr (Memc[str3])
+ call pargstr (Memc[str4])
+ call printf ("\n")
+ }
+
+ case CCMD_ISYSTEM:
+ stat = sk_decwcs (Memc[cmd], tmw, tcoo, NULL)
+ if (Memc[cmd] == EOS || stat == ERR || (infd == NULL &&
+ tmw == NULL)) {
+ if (tmw != NULL)
+ call mw_close (tmw)
+ call sk_close (tcoo)
+ call fprintf (outfd, "\n")
+ if (sk_stati(cooin, S_STATUS) == ERR)
+ call fprintf (outfd,
+ "# Error decoding the input coordinate system\n")
+ call sk_stats (cooin, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiwrite (outfd, "Insystem", Memc[str1], mwin, cooin)
+ call fprintf (outfd, "\n")
+ if (outfd != STDOUT) {
+ call printf ("\n")
+ if (sk_stati(cooin, S_STATUS) == ERR)
+ call printf (
+ "# Error decoding the input coordinate system\n")
+ call sk_stats (cooin, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiprint ("Insystem", Memc[str1], mwin, cooin)
+ call printf ("\n")
+ }
+ } else {
+ if (mwin != NULL)
+ call mw_close (mwin)
+ call sk_close (cooin)
+ mwin = tmw
+ cooin = tcoo
+ if (infd == NULL)
+ call sk_seti (cooin, S_PIXTYPE, PIXTYPE_TV)
+ newsystem = YES
+ newformat = YES
+ }
+
+ case CCMD_OSYSTEM:
+ stat = sk_decwcs (Memc[cmd], tmw, tcoo, NULL)
+ if (Memc[cmd] == EOS || stat == ERR) {
+ if (tmw != NULL)
+ call mw_close (tmw)
+ call sk_close (tcoo)
+ call fprintf (outfd, "\n")
+ if (sk_stati(cooout, S_STATUS) == ERR)
+ call fprintf (outfd,
+ "# Error decoding the output coordinate system\n")
+ call sk_stats (cooout, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiwrite (outfd, "Outsystem", Memc[str1], mwout, cooout)
+ call fprintf (outfd, "\n")
+ if (outfd != STDOUT) {
+ call printf ("\n")
+ if (sk_stati(cooout, S_STATUS) == ERR)
+ call printf (
+ "# Error decoding the output coordinate system\n")
+ call sk_stats (cooout, S_COOSYSTEM, Memc[str1], SZ_FNAME)
+ call sk_iiprint ("Outsystem", Memc[str1], mwout, cooout)
+ call printf ("\n")
+ }
+ } else {
+ if (mwout != NULL)
+ call mw_close (mwout)
+ call sk_close (cooout)
+ mwout = tmw
+ cooout = tcoo
+ newsystem = YES
+ newformat = YES
+ }
+
+ case CCMD_IUNITS:
+ call sscan (Memc[cmd])
+ call gargwrd (Memc[str1], SZ_FNAME)
+ call gargwrd (Memc[str2], SZ_FNAME)
+ if (Memc[cmd] == EOS) {
+ call sk_wiformats (cooin, ilngunits, ilatunits, "", "",
+ Memc[str1], Memc[str2], Memc[str3], Memc[str4], SZ_FNAME)
+ call fprintf (outfd, "\n")
+ call fprintf (outfd, "# Units: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call fprintf (outfd, "\n")
+ if (outfd != STDOUT) {
+ call printf ("\n")
+ call printf ("Units: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call printf ("\n")
+ }
+ } else {
+ ilngunits = strdic (Memc[str1], Memc[str1], SZ_FNAME,
+ SKY_LNG_UNITLIST)
+ ilatunits = strdic (Memc[str2], Memc[str2], SZ_FNAME,
+ SKY_LAT_UNITLIST)
+ newformat = YES
+ }
+
+ case CCMD_OUNITS:
+ call sscan (Memc[cmd])
+ call gargwrd (Memc[str1], SZ_FNAME)
+ call gargwrd (Memc[str2], SZ_FNAME)
+ if (Memc[cmd] == EOS) {
+ call sk_woformats (cooin, cooout, olngunits, olatunits,
+ olngformat, olatformat, Memc[str1], Memc[str2], Memc[str3],
+ Memc[str4], SZ_FNAME)
+ call fprintf (outfd, "\n")
+ call fprintf (outfd, "# Units: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call fprintf (outfd, "\n")
+ if (outfd != STDOUT) {
+ call printf ("\n")
+ call printf ("Units: %s %s\n")
+ call pargstr (Memc[str1])
+ call pargstr (Memc[str2])
+ call printf ("\n")
+ }
+ } else {
+ olngunits = strdic (Memc[str1], Memc[str1], SZ_FNAME,
+ SKY_LNG_UNITLIST)
+ olatunits = strdic (Memc[str2], Memc[str2], SZ_FNAME,
+ SKY_LAT_UNITLIST)
+ newformat = YES
+ }
+
+ case CCMD_OFORMATS:
+ call sscan (Memc[cmd])
+ call gargwrd (Memc[str1], SZ_FNAME)
+ call gargwrd (Memc[str2], SZ_FNAME)
+ if (Memc[cmd] == EOS) {
+ call sk_woformats (cooin, cooout, olngunits, olatunits,
+ olngformat, olatformat, Memc[str1], Memc[str2], Memc[str3],
+ Memc[str4], SZ_FNAME)
+ call fprintf (outfd, "\n")
+ call fprintf (outfd, "# Formats: %s %s\n")
+ call pargstr (Memc[str3])
+ call pargstr (Memc[str4])
+ call fprintf (outfd, "\n")
+ if (outfd != STDOUT) {
+ call printf ("\n")
+ call printf ("Formats: %s %s\n")
+ call pargstr (Memc[str3])
+ call pargstr (Memc[str4])
+ call printf ("\n")
+ }
+ } else {
+ call strcpy (Memc[str1], olngformat, SZ_FNAME)
+ call strcpy (Memc[str2], olatformat, SZ_FNAME)
+ newformat = YES
+ }
+
+ default:
+ ;
+ }
+
+ call sfree (sp)
+end
+
+
+# SK_GRTRAN -- Transform the grid coordinate list.
+
+procedure sk_grtran (outfd, mwin, mwout, cooin, cooout, ilngmin, ilngmax,
+ nilng, ilatmin, ilatmax, nilat, ilngunits, ilatunits, olngunits,
+ olatunits, ilngformat, ilatformat, olngformat, olatformat, transform)
+
+int outfd #I the input file descriptor
+pointer mwin #I the input image wcs
+pointer mwout #I the output image wcs
+pointer cooin #I the input coordinate descriptor
+pointer cooout #I the output coordinate descriptor
+double ilngmin #I the x/ra/longitude minimum
+double ilngmax #I the x/ra/longitude maximum
+int nilng #I the number of x/ra/longitude grid points
+double ilatmin #I the y/dec/longitude minimum
+double ilatmax #I the y/dec/longitude maximum
+int nilat #I the number of y/dec/latitude grid points
+int ilngunits #I the input ra/longitude units
+int ilatunits #I the input dec/latitude units
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+char ilngformat[ARB] #I the input ra/longitude format
+char ilatformat[ARB] #I the input dec/latitude format
+char olngformat[ARB] #I the output ra/longitude format
+char olatformat[ARB] #I the output dec/latitude format
+bool transform #I transform the input file
+
+double ilng1, ilng2, ilat1, ilat2, ilngstep, ilatstep, ilng, ilat, olng, olat
+double tlng, tlat
+int i, j, tilngunits, tilatunits, tolngunits, tolatunits
+pointer sp, fmtstr, ctin, ctout, tilngformat, tilatformat
+pointer tolngformat, tolatformat
+int sk_stati()
+pointer sk_ictran(), sk_octran()
+errchk sk_ictran(), sk_octran()
+
+begin
+ # Compile the input and output transformations.
+ iferr {
+ ctin = sk_ictran (cooin, mwin)
+ ctout = sk_octran (cooout, mwout)
+ } then
+ return
+
+ # Get some working space.
+ call smark (sp)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+ call salloc (tilngformat, SZ_FNAME, TY_CHAR)
+ call salloc (tilatformat, SZ_FNAME, TY_CHAR)
+ call salloc (tolngformat, SZ_FNAME, TY_CHAR)
+ call salloc (tolatformat, SZ_FNAME, TY_CHAR)
+
+ # Set the input and output units.
+ if (ilngunits <= 0)
+ tilngunits = sk_stati (cooin, S_NLNGUNITS)
+ else
+ tilngunits = ilngunits
+ if (ilatunits <= 0)
+ tilatunits = sk_stati (cooin, S_NLATUNITS)
+ else
+ tilatunits = ilatunits
+ if (olngunits <= 0)
+ tolngunits = sk_stati (cooout, S_NLNGUNITS)
+ else
+ tolngunits = olngunits
+ if (olatunits <= 0)
+ tolatunits = sk_stati (cooout, S_NLATUNITS)
+ else
+ tolatunits = olatunits
+
+ # Set the input and output formats.
+ call sk_iformats (cooin, ilngformat, ilatformat,
+ tilngunits, tilatunits, Memc[tilngformat], Memc[tilatformat],
+ SZ_FNAME)
+ call sk_oformats (cooin, cooout, olngformat, olatformat,
+ tolngunits, tolatunits, Memc[tolngformat], Memc[tolatformat],
+ SZ_FNAME)
+
+ # Check the input and output units.
+ call sk_iunits (cooin, mwin, tilngunits, tilatunits, tilngunits,
+ tilatunits)
+ call sk_ounits (cooout, mwout, tolngunits, tolatunits, tolngunits,
+ tolatunits)
+
+ # Create the format string.
+ if (transform) {
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s\n")
+ call pargstr (Memc[tolngformat])
+ call pargstr (Memc[tolatformat])
+ } else {
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s %s %s\n")
+ call pargstr (Memc[tilngformat])
+ call pargstr (Memc[tilatformat])
+ call pargstr (Memc[tolngformat])
+ call pargstr (Memc[tolatformat])
+ }
+
+ # Compute the grid parameters in x/ra/longitude.
+ if (IS_INDEFD(ilngmin)) {
+ switch (sk_stati(cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ ilng1 = 1.0d0
+ default:
+ switch (sk_stati(cooin, S_CTYPE)) {
+ case 0:
+ ilng1 = 1.0d0
+ default:
+ switch (tilngunits) {
+ case SKY_HOURS:
+ ilng1 = 0.0d0
+ case SKY_DEGREES:
+ ilng1 = 0.0d0
+ case SKY_RADIANS:
+ ilng1 = 0.0d0
+ }
+ }
+ }
+ } else
+ ilng1 = ilngmin
+
+ if (IS_INDEFD(ilngmax)) {
+ switch (sk_stati(cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ ilng2 = sk_stati (cooin, S_NLNGAX)
+ default:
+ switch (sk_stati (cooin, S_CTYPE)) {
+ case 0:
+ ilng2 = sk_stati(cooin, S_NLNGAX)
+ default:
+ switch (tilngunits) {
+ case SKY_HOURS:
+ ilng2 = 24.0d0
+ case SKY_DEGREES:
+ ilng2 = 360.0d0
+ case SKY_RADIANS:
+ ilng2 = TWOPI
+ }
+ }
+ }
+ } else
+ ilng2 = ilngmax
+ if (nilng == 1)
+ ilngstep = 0.0d0
+ else
+ ilngstep = (ilng2 - ilng1) / (nilng - 1)
+
+ # Compute the grid parameters in y/dec/latitude.
+ if (IS_INDEFD(ilatmin)) {
+ switch (sk_stati (cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ ilat1 = 1.0d0
+ default:
+ switch (sk_stati (cooin, S_CTYPE)) {
+ case 0:
+ ilat1 = 1.0d0
+ default:
+ switch (tilatunits) {
+ case SKY_HOURS:
+ ilat1 = 0.0d0
+ case SKY_DEGREES:
+ ilat1 = -90.0d0
+ case SKY_RADIANS:
+ ilat1 = -HALFPI
+ }
+ }
+ }
+ } else
+ ilat1 = ilatmin
+
+ if (IS_INDEFD(ilatmax)) {
+ switch (sk_stati (cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ ilat2 = sk_stati (cooin, S_NLATAX)
+ default:
+ switch (sk_stati (cooin, S_CTYPE)) {
+ case 0:
+ ilat2 = sk_stati(cooin, S_NLATAX)
+ default:
+ switch (tilatunits) {
+ case SKY_HOURS:
+ ilat2 = 24.0d0
+ case SKY_DEGREES:
+ ilat2 = 90.0d0
+ case SKY_RADIANS:
+ ilat2 = HALFPI
+ }
+ }
+ }
+ } else
+ ilat2 = ilatmax
+ if (nilat == 1)
+ ilatstep = 0.0d0
+ else
+ ilatstep = (ilat2 - ilat1) / (nilat - 1)
+
+ # Compute the grid of points.
+ do j = 1, nilat {
+
+ ilat = ilat1 + (j - 1) * ilatstep
+
+ do i = 1, nilng {
+
+ ilng = ilng1 + (i - 1) * ilngstep
+
+ # Convert the input coordinates to world coordinates in
+ # radians.
+ call sk_incc (cooin, mwin, ctin, tilngunits, tilatunits,
+ ilng, ilat, olng, olat)
+
+ # Perform the transformation.
+ call sk_lltran (cooin, cooout, olng, olat, INDEFD,
+ INDEFD, 0.0d0, 0.0d0, tlng, tlat)
+
+ # Convert the celestial coordinates to output coordinates.
+ call sk_outcc (cooout, mwout, ctout, tolngunits, tolatunits,
+ tlng, tlat, olng, olat)
+
+ # Write out the results
+ if (transform) {
+ call fprintf (outfd, Memc[fmtstr])
+ call pargd (olng)
+ call pargd (olat)
+ } else {
+ call fprintf (outfd, Memc[fmtstr])
+ call pargd (ilng)
+ call pargd (ilat)
+ call pargd (olng)
+ call pargd (olat)
+ }
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# SK_GRCOPY -- Copy the input logical pixel grid to the output logical
+# pixel grid.
+
+procedure sk_grcopy (outfd, cooin, cooout, ilngmin, ilngmax, nilng, ilatmin,
+ ilatmax, nilat, ilngunits, ilatunits, olngunits, olatunits, ilngformat,
+ ilatformat, olngformat, olatformat, transform)
+
+int outfd #I the output file descriptor
+pointer cooin #I the pointer to input coordinate structure
+pointer cooout #I the pointer to output coordinate structure
+double ilngmin #I the x/ra/longitude minimum
+double ilngmax #I the x/ra/longitude maximum
+int nilng #I the number of x/ra/longitude grid points
+double ilatmin #I the y/dec/longitude minimum
+double ilatmax #I the y/dec/longitude maximum
+int nilat #I the number of y/dec/latitude grid points
+int ilngunits #I the input x/ra/longitude units
+int ilatunits #I the input y/dec/latitude/units
+int olngunits #I the output x/ra/longitude units
+int olatunits #I the output y/dec/latitude/units
+char ilngformat[ARB] #I the input x format string
+char ilatformat[ARB] #I the intput y format string
+char olngformat[ARB] #I the output x format string
+char olatformat[ARB] #I the output y format string
+bool transform #I transform the input file
+
+double x1, x2, x, y1, y2, y, xstep, ystep
+int i, j, tilngunits, tilatunits, tolngunits, tolatunits
+pointer sp, tilngformat, tilatformat, tolngformat, tolatformat, fmtstr
+int sk_stati()
+
+begin
+ call smark (sp)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+ call salloc (tilngformat, SZ_FNAME, TY_CHAR)
+ call salloc (tilatformat, SZ_FNAME, TY_CHAR)
+ call salloc (tolngformat, SZ_FNAME, TY_CHAR)
+ call salloc (tolatformat, SZ_FNAME, TY_CHAR)
+
+ # Set the input units.
+ if (ilngunits <= 0)
+ tilngunits = sk_stati (cooin, S_NLNGUNITS)
+ else
+ tilngunits = ilngunits
+ if (ilatunits <= 0)
+ tilatunits = sk_stati (cooin, S_NLATUNITS)
+ else
+ tilatunits = ilatunits
+ if (olngunits <= 0)
+ tolngunits = sk_stati (cooout, S_NLNGUNITS)
+ else
+ tolngunits = olngunits
+ if (olatunits <= 0)
+ tolatunits = sk_stati (cooout, S_NLATUNITS)
+ else
+ tolatunits = olatunits
+
+ # Set the input and output formats.
+ call sk_iformats (cooin, ilngformat, ilatformat,
+ tilngunits, tilatunits, Memc[tilngformat], Memc[tilatformat],
+ SZ_FNAME)
+ call sk_oformats (cooin, cooout, olngformat, olatformat,
+ tolngunits, tolatunits, Memc[tolngformat], Memc[tolatformat],
+ SZ_FNAME)
+
+ # Create the format string.
+ if (transform) {
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s\n")
+ call pargstr (Memc[tolngformat])
+ call pargstr (Memc[tolatformat])
+ } else {
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s %s %s\n")
+ call pargstr (Memc[tilngformat])
+ call pargstr (Memc[tilatformat])
+ call pargstr (Memc[tolngformat])
+ call pargstr (Memc[tolatformat])
+ }
+
+ # Compute the grid parameters in x/ra/longitude.
+ if (IS_INDEFD(ilngmin)) {
+ switch (sk_stati (cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ x1 = 1.0d0
+ default:
+ switch (sk_stati (cooin, S_CTYPE)) {
+ case 0:
+ x1 = 1.0d0
+ default:
+ switch (tilngunits) {
+ case SKY_HOURS:
+ x1 = 0.0d0
+ case SKY_DEGREES:
+ x1 = 0.0d0
+ case SKY_RADIANS:
+ x1 = 0.0d0
+ }
+ }
+ }
+ } else
+ x1 = ilngmin
+ if (IS_INDEFD(ilngmax)) {
+ switch (sk_stati(cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ x2 = sk_stati(cooin, S_NLNGAX)
+ default:
+ switch (sk_stati (cooin, S_CTYPE)) {
+ case 0:
+ x2 = sk_stati (cooin, S_NLNGAX)
+ default:
+ switch (tilngunits) {
+ case SKY_HOURS:
+ x2 = 24.0d0
+ case SKY_DEGREES:
+ x2 = 360.0d0
+ case SKY_RADIANS:
+ x2 = TWOPI
+ }
+ }
+ }
+ } else
+ x2 = ilngmax
+ if (nilng == 1)
+ xstep = 0.0d0
+ else
+ xstep = (x2 - x1) / (nilng - 1)
+
+ # Compute the grid parameters in y/dec/latitude.
+ if (IS_INDEFD(ilatmin)) {
+ switch (sk_stati (cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ y1 = 1.0d0
+ default:
+ switch (sk_stati(cooin, S_CTYPE)) {
+ case 0:
+ y1 = 1.0d0
+ default:
+ switch (tilatunits) {
+ case SKY_HOURS:
+ y1 = 0.0d0
+ case SKY_DEGREES:
+ y1 = -90.0d0
+ case SKY_RADIANS:
+ y1 = -HALFPI
+ }
+ }
+ }
+ } else
+ y1 = ilatmin
+
+ if (IS_INDEFD(ilatmax)) {
+ switch (sk_stati (cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ y2 = sk_stati (cooin, S_NLATAX)
+ default:
+ switch (sk_stati(cooin, S_CTYPE)) {
+ case 0:
+ y2 = sk_stati (cooin, S_NLATAX)
+ default:
+ switch (tilatunits) {
+ case SKY_HOURS:
+ y2 = 24.0d0
+ case SKY_DEGREES:
+ y2 = 90.0d0
+ case SKY_RADIANS:
+ y2 = HALFPI
+ }
+ }
+ }
+ } else
+ y2 = ilatmax
+ if (nilat == 1)
+ ystep = 0.0d0
+ else
+ ystep = (y2 - y1) / (nilat - 1)
+
+ # Compute the points.
+ y = y1
+ do j = 1, nilat {
+ x = x1
+ do i = 1, nilng {
+ if (transform) {
+ call fprintf (outfd, Memc[fmtstr])
+ call pargd (x)
+ call pargd (y)
+ } else {
+ call fprintf (outfd, Memc[fmtstr])
+ call pargd (x)
+ call pargd (y)
+ call pargd (x)
+ call pargd (y)
+ }
+ x = x + xstep
+ }
+ y = y + ystep
+ }
+
+ call sfree (sp)
+end
+
+
+# SK_WIFORMATS -- Format the input units and format strings.
+
+procedure sk_wiformats (cooin, ilngunits, ilatunits, ilngformat,
+ ilatformat, ilngunitstr, ilatunitstr, oilngformat, oilatformat, maxch)
+
+pointer cooin #I the input coordinate structure
+int ilngunits #I the output ra/longitude units
+int ilatunits #I the output dec/latitude units
+char ilngformat[ARB] #I the output ra/longitude format string
+char ilatformat[ARB] #I the output dec/latitude format string
+char ilngunitstr[ARB] #O the output output ra/longitude format string
+char ilatunitstr[ARB] #O the output output dec/latitude format string
+char oilngformat[ARB] #O the output output ra/longitude format string
+char oilatformat[ARB] #O the output output dec/latitude format string
+int maxch #I the maximum length of the format strings
+
+int tilngunits, tilatunits
+int sk_stati()
+
+begin
+ # Determine the correct units.
+ if (ilngunits <= 0)
+ tilngunits = sk_stati (cooin, S_NLNGUNITS)
+ else
+ tilngunits = ilngunits
+ if (ilatunits <= 0)
+ tilatunits = sk_stati (cooin, S_NLATUNITS)
+ else
+ tilatunits = ilatunits
+
+ # Format the units strings.
+ if (sk_stati(cooin, S_PIXTYPE) != PIXTYPE_WORLD) {
+ call strcpy ("pixels", ilngunitstr, maxch)
+ call strcpy ("pixels", ilatunitstr, maxch)
+ } else {
+ switch (tilngunits) {
+ case SKY_HOURS:
+ call strcpy ("hours", ilngunitstr, maxch)
+ case SKY_DEGREES:
+ call strcpy ("degrees", ilngunitstr, maxch)
+ case SKY_RADIANS:
+ call strcpy ("radians", ilngunitstr, maxch)
+ }
+ switch (tilatunits) {
+ case SKY_HOURS:
+ call strcpy ("hours", ilatunitstr, maxch)
+ case SKY_DEGREES:
+ call strcpy ("degrees", ilatunitstr, maxch)
+ case SKY_RADIANS:
+ call strcpy ("radians", ilatunitstr, maxch)
+ }
+ }
+
+ # Format the format strings.
+ call sk_iformats (cooin, ilngformat, ilatformat,
+ tilngunits, tilatunits, oilngformat, oilatformat,
+ SZ_FNAME)
+end
+
+
+# SK_IFORMATS -- Set the input format strings.
+
+procedure sk_iformats (cooin, ilngformat, ilatformat, ilngunits, ilatunits,
+ oilngformat, oilatformat, maxch)
+
+pointer cooin #I the input coordinate structure
+char ilngformat[ARB] #I the input ra/longitude format string
+char ilatformat[ARB] #I the input dec/latitude format string
+int ilngunits #I the input ra/longitude units
+int ilatunits #I the input dec/latitude units
+char oilngformat[ARB] #O the input ra/longitude format string
+char oilatformat[ARB] #O the input dec/latitude format string
+int maxch #I the maximum length of the format strings
+
+int sk_stati()
+
+begin
+ if (ilngformat[1] == EOS) {
+ if (sk_stati(cooin, S_STATUS) == ERR)
+ call strcpy ("%10.3f", oilngformat, maxch)
+ else {
+ switch (sk_stati(cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ call strcpy ("%10.3f", oilngformat, maxch)
+ default:
+ switch (ilngunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.3h", oilngformat, maxch)
+ case SKY_DEGREES:
+ call strcpy ("%12.2h", oilngformat, maxch)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", oilngformat, maxch)
+ }
+ }
+ }
+ } else
+ call strcpy (ilngformat, oilngformat, maxch)
+
+ if (ilatformat[1] == EOS) {
+ if (sk_stati (cooin, S_STATUS) == ERR)
+ call strcpy ("%10.3f", oilatformat, maxch)
+ else {
+ switch (sk_stati(cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ call strcpy ("%10.3f", oilatformat, maxch)
+ default:
+ switch (ilatunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.3h", oilatformat, maxch)
+ case SKY_DEGREES:
+ call strcpy ("%12.2h", oilatformat, maxch)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", oilatformat, maxch)
+ }
+ }
+ }
+ } else
+ call strcpy (ilatformat, oilatformat, maxch)
+end
+
+
+# SK_WOFORMATS -- Format the units and format strings.
+
+procedure sk_woformats (cooin, cooout, olngunits, olatunits, olngformat,
+ olatformat, olngunitstr, olatunitstr, oolngformat, oolatformat, maxch)
+
+pointer cooin #I the input coordinate structure
+pointer cooout #I the output coordinate structure
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+char olngformat[ARB] #I the output ra/longitude format string
+char olatformat[ARB] #I the output dec/latitude format string
+char olngunitstr[ARB] #O the output output ra/longitude format string
+char olatunitstr[ARB] #O the output output dec/latitude format string
+char oolngformat[ARB] #O the output output ra/longitude format string
+char oolatformat[ARB] #O the output output dec/latitude format string
+int maxch #I the maximum length of the format strings
+
+int tolngunits, tolatunits
+int sk_stati()
+
+begin
+ # Determine the correct units.
+ if (olngunits <= 0)
+ tolngunits = sk_stati (cooout, S_NLNGUNITS)
+ else
+ tolngunits = olngunits
+ if (olatunits <= 0)
+ tolatunits = sk_stati (cooout, S_NLATUNITS)
+ else
+ tolatunits = olatunits
+
+ # Format the units strings.
+ if (sk_stati(cooout, S_PIXTYPE) != PIXTYPE_WORLD) {
+ call strcpy ("pixels", olngunitstr, maxch)
+ call strcpy ("pixels", olatunitstr, maxch)
+ } else {
+ switch (tolngunits) {
+ case SKY_HOURS:
+ call strcpy ("hours", olngunitstr, maxch)
+ case SKY_DEGREES:
+ call strcpy ("degrees", olngunitstr, maxch)
+ case SKY_RADIANS:
+ call strcpy ("radians", olngunitstr, maxch)
+ }
+ switch (tolatunits) {
+ case SKY_HOURS:
+ call strcpy ("hours", olatunitstr, maxch)
+ case SKY_DEGREES:
+ call strcpy ("degrees", olatunitstr, maxch)
+ case SKY_RADIANS:
+ call strcpy ("radians", olatunitstr, maxch)
+ }
+ }
+
+ # Format the format strings.
+ call sk_oformats (cooin, cooout, olngformat, olatformat,
+ tolngunits, tolatunits, oolngformat, oolatformat,
+ SZ_FNAME)
+end
+
+
+# SK_OFORMATS -- Set the output format strings.
+
+procedure sk_oformats (cooin, cooout, olngformat, olatformat, olngunits,
+ olatunits, oolngformat, oolatformat, maxch)
+
+pointer cooin #I the input coordinate structure
+pointer cooout #I the output coordinate structure
+char olngformat[ARB] #I the output ra/longitude format string
+char olatformat[ARB] #I the output dec/latitude format string
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+char oolngformat[ARB] #O the output output ra/longitude format string
+char oolatformat[ARB] #O the output output dec/latitude format string
+int maxch #I the maximum length of the format strings
+
+int sptype
+int sk_stati()
+
+begin
+ if (olngformat[1] == EOS) {
+ if (sk_stati(cooin, S_STATUS) == ERR)
+ call strcpy ("%10.3f", oolngformat, maxch)
+ else {
+ if (sk_stati(cooout, S_STATUS) == ERR)
+ sptype = sk_stati (cooin, S_PIXTYPE)
+ else
+ sptype = sk_stati (cooout, S_PIXTYPE)
+ switch (sptype) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ call strcpy ("%10.3f", oolngformat, maxch)
+ default:
+ switch (olngunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.3h", oolngformat, maxch)
+ case SKY_DEGREES:
+ call strcpy ("%12.2h", oolngformat, maxch)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", oolngformat, maxch)
+ }
+ }
+ }
+ } else
+ call strcpy (olngformat, oolngformat, maxch)
+
+ if (olatformat[1] == EOS) {
+ if (sk_stati (cooin, S_STATUS) == ERR)
+ call strcpy ("%10.3f", oolatformat, maxch)
+ else {
+ if (sk_stati(cooout, S_STATUS) == ERR)
+ sptype = sk_stati (cooin, S_PIXTYPE)
+ else
+ sptype = sk_stati (cooout, S_PIXTYPE)
+ switch (sptype) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ call strcpy ("%10.3f", oolatformat, maxch)
+ default:
+ switch (olatunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.3h", oolatformat, maxch)
+ case SKY_DEGREES:
+ call strcpy ("%12.2h", oolatformat, maxch)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", oolatformat, maxch)
+ }
+ }
+ }
+ } else
+ call strcpy (olatformat, oolatformat, maxch)
+end
+
+
+# SK_ICTRAN -- Compile the input mwcs transformation.
+
+pointer procedure sk_ictran (cooin, mwin)
+
+pointer cooin #I the input coordinate descriptor
+pointer mwin #I the input mwcs descriptor
+
+int axbits
+pointer ctin
+int sk_stati()
+pointer mw_sctran()
+errchk mw_sctran()
+
+begin
+ if (mwin != NULL) {
+ switch (sk_stati(cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ axbits = 2 ** (sk_stati(cooin, S_XLAX) - 1) +
+ 2 ** (sk_stati(cooin, S_YLAX) - 1)
+ iferr {
+ if (sk_stati(cooin, S_PIXTYPE) == PIXTYPE_PHYSICAL)
+ ctin = mw_sctran (mwin, "physical", "world", axbits)
+ else
+ ctin = mw_sctran (mwin, "logical", "world", axbits)
+ } then
+ call error (0, "Error compiling input mwcs transform")
+ default:
+ ctin = NULL
+ }
+ } else {
+ ctin = NULL
+ }
+
+ return (ctin)
+end
+
+
+# SK_IUNITS -- Set the input celestial coordinate units.
+
+procedure sk_iunits (cooin, mwin, ilngunits, ilatunits, oilngunits, oilatunits)
+
+pointer cooin #I the input coordinate descriptor
+pointer mwin #I the input mwcs descriptor
+int ilngunits #I the input ra/longitude units
+int ilatunits #I the input dec/latitude units
+int oilngunits #O the output input ra/longitude units
+int oilatunits #O the output input dec/latitude units
+
+int sk_stati()
+
+begin
+ if (mwin != NULL) {
+ switch (sk_stati(cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ oilngunits = SKY_DEGREES
+ oilatunits = SKY_DEGREES
+ default:
+ oilngunits = ilngunits
+ oilatunits = ilatunits
+ }
+ } else {
+ oilngunits = ilngunits
+ oilatunits = ilatunits
+ }
+end
+
+
+# SK_OCTRAN -- Compile the output mwcs transformation.
+
+pointer procedure sk_octran (cooout, mwout)
+
+pointer cooout #I the output coordinate descriptor
+pointer mwout #I the output mwcs descriptor
+
+int axbits
+pointer ctout
+int sk_stati()
+pointer mw_sctran()
+errchk mw_sctran()
+
+begin
+ if (mwout != NULL) {
+ switch (sk_stati(cooout, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ axbits = 2 ** (sk_stati (cooout, S_XLAX) - 1) +
+ 2 ** (sk_stati (cooout, S_YLAX) - 1)
+ iferr {
+ if (sk_stati (cooout, S_PIXTYPE) == PIXTYPE_PHYSICAL)
+ ctout = mw_sctran (mwout, "world", "physical", axbits)
+ else
+ ctout = mw_sctran (mwout, "world", "logical", axbits)
+ } then
+ call error (0, "Error compiling output mwcs transform")
+ default:
+ ctout = NULL
+ }
+ } else {
+ ctout = NULL
+ }
+
+ return (ctout)
+end
+
+
+# SK_OUNITS -- Compile the output mwcs transformation and set the output
+# celestial coordinate units.
+
+procedure sk_ounits (cooout, mwout, olngunits, olatunits, oolngunits,
+ oolatunits)
+
+pointer cooout #I the output coordinate descriptor
+pointer mwout #I the output mwcs descriptor
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+int oolngunits #O the output output ra/longitude units
+int oolatunits #O the output output dec/latitude units
+
+int sk_stati()
+
+begin
+ if (mwout != NULL) {
+ switch (sk_stati(cooout, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_TV, PIXTYPE_PHYSICAL:
+ oolngunits = SKY_RADIANS
+ oolatunits = SKY_RADIANS
+ default:
+ oolngunits = olngunits
+ oolatunits = olatunits
+ }
+ } else {
+ oolngunits = olngunits
+ oolatunits = olatunits
+ }
+end
+
+
+# SK_INCC -- Transform the input coordinates to the correct celestial
+# coordinates in radians.
+
+procedure sk_incc (cooin, mwin, ctin, ilngunits, ilatunits, ilng, ilat,
+ olng, olat)
+
+pointer cooin #I the input coordinate descriptor
+pointer mwin #I the input mwcs descriptor
+pointer ctin #I the mwcs transformation descriptor
+int ilngunits #I the input ra/longitude units
+int ilatunits #I the input dec/latitude units
+double ilng #I the input ra/longitude coordinates
+double ilat #I the input dec/latitude coordinates
+double olng #O the output ra/longitude coordinates
+double olat #O the output dec/latitude coordinates
+
+double tlng, tlat
+double sk_statd()
+int sk_stati()
+
+begin
+ # Convert the input image coordinates to world coordinates.
+ if (mwin != NULL) {
+ switch (sk_stati (cooin, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_PHYSICAL:
+ if (ctin == NULL) {
+ olng = ilng
+ olat = ilat
+ } else if (sk_stati (cooin, S_PLNGAX) < sk_stati (cooin,
+ S_PLATAX)) {
+ call mw_c2trand (ctin, ilng, ilat, olng, olat)
+ } else {
+ call mw_c2trand (ctin, ilng, ilat, olat, olng)
+ }
+ case PIXTYPE_TV:
+ tlng = (ilng - sk_statd(cooin, S_VXOFF)) /
+ sk_statd (cooin, S_VXSTEP)
+ tlat = (ilat - sk_statd (cooin, S_VYOFF)) /
+ sk_statd (cooin, S_VYSTEP)
+ if (ctin == NULL) {
+ olng = tlng
+ olat = tlat
+ } else if (sk_stati (cooin, S_PLNGAX) < sk_stati (cooin,
+ S_PLATAX)) {
+ call mw_c2trand (ctin, tlng, tlat, olng, olat)
+ } else {
+ call mw_c2trand (ctin, tlng, tlat, olat, olng)
+ }
+ case PIXTYPE_WORLD:
+ olng = ilng
+ olat = ilat
+ }
+ } else {
+ olng = ilng
+ olat = ilat
+ }
+
+ # Convert the input values to radians.
+ switch (ilngunits) {
+ case SKY_HOURS:
+ olng = DEGTORAD(15.0d0 * olng)
+ case SKY_DEGREES:
+ olng = DEGTORAD(olng)
+ case SKY_RADIANS:
+ ;
+ }
+ switch (ilatunits) {
+ case SKY_HOURS:
+ olat = DEGTORAD(15.0d0 * olat)
+ case SKY_DEGREES:
+ olat = DEGTORAD(olat)
+ case SKY_RADIANS:
+ ;
+ }
+end
+
+
+# SK_OUTCC -- Transform the output celestial coordinates to the correct
+# output coordinate system.
+
+procedure sk_outcc (cooout, mwout, ctout, olngunits, olatunits, ilng, ilat,
+ olng, olat)
+
+pointer cooout #I the output coordinate descriptor
+pointer mwout #I the output mwcs descriptor
+pointer ctout #I the output mwcs transformation descriptor
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+double ilng #I the output ra/longitude coordinates
+double ilat #I the output dec/latitude coordinates
+double olng #O the output coordinates
+double olat #O the output coordinates
+
+double tlng, tlat
+double sk_statd()
+int sk_stati()
+
+begin
+ # Convert the output image coordinates to image coordinates.
+ #if (mwout == NULL || (sk_stati(cooin, S_PIXTYPE) == PIXTYPE_WORLD &&
+ # sk_stati (cooout, S_PIXTYPE) == PIXTYPE_WORLD)) {
+ if (mwout == NULL || ctout == NULL) {
+ switch (olngunits) {
+ case SKY_HOURS:
+ olng = RADTODEG(ilng / 15.0d0)
+ case SKY_DEGREES:
+ olng = RADTODEG(ilng)
+ case SKY_RADIANS:
+ ;
+ }
+ switch (olatunits) {
+ case SKY_HOURS:
+ olat = RADTODEG(ilat / 15.0d0)
+ case SKY_DEGREES:
+ olat = RADTODEG(ilat)
+ case SKY_RADIANS:
+ ;
+ }
+ } else {
+ switch (sk_stati (cooout, S_PIXTYPE)) {
+ case PIXTYPE_LOGICAL, PIXTYPE_PHYSICAL:
+ tlng = RADTODEG(ilng)
+ tlat = RADTODEG(ilat)
+ if (ctout == NULL) {
+ olng = tlat
+ olat = tlng
+ } else if (sk_stati(cooout, S_PLNGAX) < sk_stati(cooout,
+ S_PLATAX)) {
+ call mw_c2trand (ctout, tlng, tlat, olng, olat)
+ } else {
+ call mw_c2trand (ctout, tlat, tlng, olng, olat)
+ }
+ case PIXTYPE_TV:
+ tlng = RADTODEG(ilng)
+ tlat = RADTODEG(ilat)
+ if (ctout == NULL) {
+ olng = tlat
+ olat = tlng
+ } else if (sk_stati(cooout, S_PLNGAX) < sk_stati(cooout,
+ S_PLATAX)) {
+ call mw_c2trand (ctout, tlng, tlat, olng, olat)
+ } else {
+ call mw_c2trand (ctout, tlat, tlng, olng, olat)
+ }
+ olng = olng * sk_statd(cooout, S_VXSTEP) +
+ sk_statd(cooout, S_VXOFF)
+ olat = olat * sk_statd (cooout, S_VYSTEP) +
+ sk_statd (cooout, S_VYOFF)
+ case PIXTYPE_WORLD:
+ if (sk_stati(cooout, S_PLNGAX) > sk_stati(cooout,
+ S_PLATAX)) {
+ olng = ilat
+ olat = ilng
+ switch (olngunits) {
+ case SKY_HOURS:
+ olat = RADTODEG(olat / 15.0d0)
+ case SKY_DEGREES:
+ olat = RADTODEG(olat)
+ case SKY_RADIANS:
+ ;
+ }
+ switch (olatunits) {
+ case SKY_HOURS:
+ olng = RADTODEG(olng / 15.0d0)
+ case SKY_DEGREES:
+ olng = RADTODEG(olng)
+ case SKY_RADIANS:
+ ;
+ }
+ } else {
+ switch (olngunits) {
+ case SKY_HOURS:
+ olng = RADTODEG(ilng / 15.0d0)
+ case SKY_DEGREES:
+ olng = RADTODEG(ilng)
+ case SKY_RADIANS:
+ ;
+ }
+ switch (olatunits) {
+ case SKY_HOURS:
+ olat = RADTODEG(ilat / 15.0d0)
+ case SKY_DEGREES:
+ olat = RADTODEG(ilat)
+ case SKY_RADIANS:
+ ;
+ }
+ }
+ }
+ }
+end
diff --git a/pkg/images/imcoords/src/skycur.key b/pkg/images/imcoords/src/skycur.key
new file mode 100644
index 00000000..2aa61fe1
--- /dev/null
+++ b/pkg/images/imcoords/src/skycur.key
@@ -0,0 +1,38 @@
+ INTERACTIVE KEYSTROKE COMMANDS
+
+? Print help
+: Execute colon command
+spbar Measure object
+q Exit task
+
+
+ COLON COMMANDS
+
+:show Show the input and output coordinate systems
+:isystem [string] Show / set the input coordinate system
+:osystem [string] Show / set the output coordinate system
+:ounits [string string] Show / set the output coordinate units
+:oformat [string string] Show / set the output coordinate format
+
+ VALID INPUT COORDINATE SYSTEMS
+
+image [tv]
+
+ VALID OUTPUT COORDINATE SYSTEMS
+
+image [logical/tv/physical/world]
+equinox [epoch]
+noefk4 [equinox [epoch]]
+fk4 [equinox [epoch]]
+fk5 [equinox [epoch]]
+icrs [equinox [epoch]]
+apparent epoch
+ecliptic epoch
+galactic [epoch]
+supergalactic [epoch]
+
+ VALID OUTPUT CELESTIAL COORDINATE UNITS AND THEIR DEFAULT FORMATS
+
+hours %12.3h
+degrees %12.2h
+radians %13.7g
diff --git a/pkg/images/imcoords/src/starfind.h b/pkg/images/imcoords/src/starfind.h
new file mode 100644
index 00000000..d535716a
--- /dev/null
+++ b/pkg/images/imcoords/src/starfind.h
@@ -0,0 +1,51 @@
+# STARFIND Structure
+
+define LEN_STARFIND (15)
+
+define SF_HWHMPSF Memr[P2R($1)] # HWHM of the PSF in pixels
+define SF_FRADIUS Memr[P2R($1+1)] # Fitting radius in HWHM
+define SF_DATAMIN Memr[P2R($1+2)] # Minimum good data limit in ADU
+define SF_DATAMAX Memr[P2R($1+3)] # Maximum good data limit in ADU
+define SF_THRESHOLD Memr[P2R($1+4)] # Detection threshold in ADU
+define SF_SEPMIN Memr[P2R($1+5)] # Minimum separation in HWHM
+define SF_SHARPLO Memr[P2R($1+6)] # Lower sharpness limit
+define SF_SHARPHI Memr[P2R($1+7)] # Upper sharpness limit
+define SF_ROUNDLO Memr[P2R($1+8)] # Lower roundness limit
+define SF_ROUNDHI Memr[P2R($1+9)] # Upper roundness limit
+define SF_MAGLO Memr[P2R($1+10)] # Lower magnitude limit
+define SF_MAGHI Memr[P2R($1+11)] # Upper magnitude limit
+define SF_NPIXMIN Memi[$1+12] # Minimum pixels above threshold
+
+
+# default values
+
+define DEF_HWHMPSF 1.0
+define DEF_FRADIUS 1.5
+define DEF_THRESHOLD 0.0
+define DEF_SEPMIN 1.5
+define DEF_DATAMIN -MAX_REAL
+define DEF_DATAMAX MAX_REAL
+define DEF_SHARPLO 0.2
+define DEF_SHARPHI 1.0
+define DEF_ROUNDLO -1.0
+define DEF_ROUNDHI 1.0
+define DEF_MAGLO -MAX_REAL
+define DEF_MAGHI MAX_REAL
+define DEF_NPIXMIN 5
+
+
+# define the gaussian sums structure
+
+define LEN_GAUSS 10
+
+define GAUSS_SUMG 1
+define GAUSS_SUMGSQ 2
+define GAUSS_PIXELS 3
+define GAUSS_DENOM 4
+define GAUSS_SGOP 5
+
+
+# miscellaneous constants
+
+define HWHM_TO_SIGMA 0.8493218
+define RMIN 2.001
diff --git a/pkg/images/imcoords/src/t_ccfind.x b/pkg/images/imcoords/src/t_ccfind.x
new file mode 100644
index 00000000..0a8bc9b8
--- /dev/null
+++ b/pkg/images/imcoords/src/t_ccfind.x
@@ -0,0 +1,782 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include <ctype.h>
+include <imhdr.h>
+include <pkg/skywcs.h>
+
+# T_CCFIND -- Locate objects with known celestial coordinates in an image
+# using the image WCS or a user supplied WCS. Write the matched celestial and
+# coordinates list to the output file.
+
+procedure t_ccfind ()
+
+bool usewcs, center, verbose
+double xref, yref, xmag, ymag, xrot, yrot, tlngref, tlatref, txref, tyref
+double txmag, tymag, txrot, tyrot
+int ip, nchars, sbox, cbox, min_sigdigits, ncenter, maxiter, tol
+int inlist, ninfiles, outlist, noutfiles, imlist, nimages, in, out
+int lngcolumn, latcolumn, lngunits, latunits, coostat, refstat
+int lngrefunits, latrefunits, proj, pfd
+pointer sp, insystem, refsystem, infile, outfile, image, projstr, str
+pointer slngref, slatref, xformat, yformat, coo, refcoo, im, mw
+real datamin, datamax, back
+
+bool clgetb()
+double clgetd(), imgetd()
+int clpopnu(), clplen(), imtopenp(), imtlen(), clgeti(), clgwrd(), strlen()
+int sk_decwcs(), sk_decim(), open(), clgfil(), imtgetim(), strncmp(), ctod()
+int cc_listran(), strdic(), cc_rdproj()
+real clgetr()
+pointer immap(), cc_mkwcs()
+errchk imgstr(), imgetd(), open()
+
+begin
+ # Get some working space.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (insystem, SZ_FNAME, TY_CHAR)
+ call salloc (refsystem, SZ_FNAME, TY_CHAR)
+ call salloc (slngref, SZ_FNAME, TY_CHAR)
+ call salloc (slatref, SZ_FNAME, TY_CHAR)
+ call salloc (xformat, SZ_FNAME, TY_CHAR)
+ call salloc (yformat, SZ_FNAME, TY_CHAR)
+ call salloc (projstr, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the input data file list.
+ inlist = clpopnu ("input")
+ ninfiles = clplen (inlist)
+ if (ninfiles <= 0) {
+ call eprintf ("Error: The input coordinate file list is empty\n")
+ call clpcls (inlist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the output results lists.
+ outlist = clpopnu ("output")
+ noutfiles = clplen (outlist)
+ if (noutfiles != ninfiles) {
+ call eprintf (
+ "Error: The number of input and output files must be the same\n")
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+ return
+ }
+
+
+ # Get the input image list.
+ imlist = imtopenp ("images")
+ nimages = imtlen (imlist)
+ if (nimages != ninfiles) {
+ call eprintf (
+ "Error: The number of input files and images must be the same\n")
+ call imtclose (imlist)
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the coordinates file format.
+ lngcolumn = clgeti ("lngcolumn")
+ latcolumn = clgeti ("latcolumn")
+ call clgstr ("insystem", Memc[insystem], SZ_FNAME)
+ iferr (lngunits = clgwrd ("lngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ lngunits = 0
+ iferr (latunits = clgwrd ("latunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ latunits = 0
+
+ # Get the user wcs if there is one.
+ usewcs = clgetb ("usewcs")
+ if (! usewcs) {
+ xref = clgetd ("xref")
+ yref = clgetd ("yref")
+ xmag = clgetd ("xmag")
+ ymag = clgetd ("ymag")
+ xrot = clgetd ("xrot")
+ yrot = clgetd ("yrot")
+ call clgstr ("lngref", Memc[slngref], SZ_FNAME)
+ call clgstr ("latref", Memc[slatref], SZ_FNAME)
+ call clgstr ("refsystem", Memc[refsystem], SZ_FNAME)
+ if (strncmp (Memc[refsystem], "INDEF", 5) == 0)
+ Memc[refsystem] = EOS
+ call clgstr ("projection", Memc[projstr], SZ_LINE)
+ iferr {
+ pfd = open (Memc[projstr], READ_ONLY, TEXT_FILE)
+ } then {
+ proj = strdic (Memc[projstr], Memc[projstr], SZ_LINE,
+ WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projstr] = EOS
+ } else {
+ proj = cc_rdproj (pfd, Memc[projstr], SZ_LINE)
+ call close (pfd)
+ }
+ }
+ iferr (lngrefunits = clgwrd ("lngrefunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ lngrefunits = 0
+ iferr (latrefunits = clgwrd ("latrefunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ latrefunits = 0
+
+ # Get the centering parameters.
+ center = clgetb ("center")
+ sbox = clgeti ("sbox")
+ cbox = clgeti ("cbox")
+ datamin = clgetr ("datamin")
+ datamax = clgetr ("datamax")
+ back = clgetr ("background")
+ maxiter = clgeti ("maxiter")
+ tol = clgeti ("tolerance")
+ if (mod (sbox,2) == 0)
+ sbox = sbox + 1
+ if (mod (cbox,2) == 0)
+ cbox = cbox + 1
+
+ # Get the output formatting parameters.
+ call clgstr ("xformat", Memc[xformat], SZ_FNAME)
+ call clgstr ("yformat", Memc[yformat], SZ_FNAME)
+ #min_sigdigits = clgeti ("min_sigdigits")
+ min_sigdigits = 7
+ verbose = clgetb ("verbose")
+
+ # Open the input coordinate system and determine its units.
+ coostat = sk_decwcs (Memc[insystem], mw, coo, NULL)
+ if (coostat == ERR || mw != NULL) {
+ call eprintf ("Error: Cannot decode the input coordinate system\n")
+ if (mw != NULL)
+ call mw_close (mw)
+ call imtclose (imlist)
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+ return
+ }
+ if (lngunits > 0)
+ call sk_seti (coo, S_NLNGUNITS, lngunits)
+ if (latunits > 0)
+ call sk_seti (coo, S_NLATUNITS, latunits)
+
+ # Flush standard output on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Loop over the files.
+ while (clgfil (inlist, Memc[infile], SZ_FNAME) != EOF &&
+ clgfil (outlist, Memc[outfile], SZ_FNAME) != EOF &&
+ imtgetim(imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the input file of celestial coordinates.
+ in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+
+ # Open the output file of matched coordinates.
+ out = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+
+ # Open the input image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ if (IM_NDIM(im) != 2) {
+ call printf ("Skipping file: %s Image: %s is not 2D\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[image])
+ call imunmap (im)
+ call close (in)
+ call close (out)
+ next
+ }
+
+ # Print the input and out file information.
+ if (verbose && out != STDOUT) {
+ call printf ("\nInput File: %s Output File: %s\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[outfile])
+ call printf (" Image: %s Wcs: %s\n")
+ call pargstr (Memc[image])
+ call pargstr ("")
+ }
+ call fprintf (out, "\n# Input File: %s Output File: %s\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[outfile])
+ call fprintf (out, "# Image: %s Wcs: %s\n")
+ call pargstr (Memc[image])
+ call pargstr ("")
+
+ # Open the wcs and compile the transformation.
+ if (usewcs) {
+
+ # Read the image wcs, skipping to the next image if the wcs
+ # is unreadable.
+ refstat = sk_decim (im, Memc[image], mw, refcoo)
+ if (refstat == ERR || mw == NULL) {
+ if (verbose && out != STDOUT)
+ call printf (
+ "Error: Cannot decode the image coordinate system\n")
+ call fprintf (out,
+ "Error: Cannot decode the image coordinate system\n")
+ if (mw != NULL)
+ call mw_close (mw)
+ call sk_close (refcoo)
+ call imunmap (im)
+ call close (out)
+ call close (in)
+ next
+ }
+
+ } else {
+
+ # Get the image pixel reference coordinates
+ if (IS_INDEFD(xref))
+ txref = (1.0d0 + IM_LEN(im,1)) / 2.0
+ else
+ txref = xref
+ if (IS_INDEFD(yref))
+ tyref = (1.0d0 + IM_LEN(im,2)) / 2.0
+ else
+ tyref = yref
+
+ # Get the image scale in arcsec / pixel.
+ if (IS_INDEFD(xmag))
+ txmag = 1.0d0
+ else
+ txmag = xmag
+ if (IS_INDEFD(ymag))
+ tymag = 1.0d0
+ else
+ tymag = ymag
+
+ # Get the coordinate axes rotation angles in degrees.
+ if (IS_INDEFD(xrot))
+ txrot = 0.0d0
+ else
+ txrot = xrot
+ if (IS_INDEFD(yrot))
+ tyrot = 0.0d0
+ else
+ tyrot = yrot
+
+ # Get the celestial coordinates of the tangent point from
+ # the image header or from the user.
+ iferr (tlngref = imgetd (im, Memc[slngref])) {
+ ip = 1
+ nchars = ctod (Memc[slngref], ip, tlngref)
+ if (nchars <= 0 || nchars != strlen (Memc[slngref]))
+ tlngref = 0.0d0
+ else if (IS_INDEFD(tlngref) || tlngref < 0.0d0 ||
+ tlngref > 360.0d0)
+ tlngref = 0.0d0
+ }
+ iferr (tlatref = imgetd (im, Memc[slatref])) {
+ ip = 1
+ nchars = ctod (Memc[slatref], ip, tlatref)
+ if (nchars <= 0 || nchars != strlen (Memc[slatref]))
+ tlatref = 0.0d0
+ else if (IS_INDEFD(tlatref) || tlatref < -90.0d0 ||
+ tlatref > 90.0d0)
+ tlatref = 0.0d0
+ }
+
+ # Get the image reference system from the image header
+ # or from the user.
+ if (Memc[refsystem] == EOS)
+ call strcpy (Memc[refsystem], Memc[str], SZ_FNAME)
+ else {
+ iferr (call imgstr (im, Memc[refsystem], Memc[str],
+ SZ_FNAME))
+ call strcpy (Memc[refsystem], Memc[str], SZ_FNAME)
+ }
+ refstat = sk_decwcs (Memc[str], mw, refcoo, NULL)
+ if (refstat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ call sk_close (refcoo)
+ refstat = sk_decwcs (Memc[insystem], mw, refcoo, NULL)
+ }
+
+ # Force the units of the tangent point.
+ if (lngrefunits > 0)
+ call sk_seti (refcoo, S_NLNGUNITS, lngrefunits)
+ if (latrefunits > 0)
+ call sk_seti (refcoo, S_NLATUNITS, latrefunits)
+
+ # Build the wcs.
+ mw = cc_mkwcs (refcoo, Memc[projstr], tlngref, tlatref,
+ txref, tyref, txmag, tymag, txrot, tyrot, false)
+
+ # Force the wcs to look like an image wcs.
+ call sk_seti (refcoo, S_PIXTYPE, PIXTYPE_LOGICAL)
+
+ }
+
+ # Print out a description of the input coordinate and image
+ # systems.
+ if (verbose && out != STDOUT)
+ call sk_iiprint ("Insystem", Memc[insystem], NULL, coo)
+ call sk_iiwrite (out, "Insystem", Memc[insystem], NULL, coo)
+ call sk_stats (refcoo, S_COOSYSTEM, Memc[str], SZ_FNAME)
+ if (usewcs) {
+ if (verbose && out != STDOUT) {
+ call sk_iiprint ("Refsystem", Memc[str], mw, refcoo)
+ }
+ call sk_iiwrite (out, "Refsystem", Memc[str], mw, refcoo)
+ call fprintf (out, "\n")
+ } else {
+ if (verbose && out != STDOUT) {
+ call sk_iiprint ("Refsystem", Memc[str], NULL, refcoo)
+ }
+ call sk_iiwrite (out, "Refsystem", Memc[str], NULL, refcoo)
+ call fprintf (out, "\n")
+ }
+
+ # Transform the coordinate lists.
+ ncenter = cc_listran (in, out, im, NULL, mw, coo, refcoo, lngcolumn,
+ latcolumn, lngunits, latunits, lngrefunits, latrefunits,
+ center, sbox / 2, cbox / 2, datamin, datamax, back,
+ maxiter, tol, Memc[xformat], Memc[yformat], min_sigdigits)
+
+ if (verbose && out != STDOUT) {
+ call printf ("Located %d objects in image %s\n")
+ call pargi (ncenter)
+ call pargstr (Memc[image])
+ call printf ("\n")
+ }
+ call sk_close (refcoo)
+ call mw_close (mw)
+ call imunmap (im)
+ call close (out)
+ call close (in)
+ }
+
+
+ call sk_close (coo)
+ call imtclose (imlist)
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+end
+
+
+define MAX_FIELDS 100 # Maximum number of fields in list
+define TABSIZE 8 # Spacing of tab stops
+
+# CC_LISTRAN -- Transform the coordinate list.
+
+int procedure cc_listran (infd, outfd, im, mwin, mwout, cooin, cooout,
+ lngcolumn, latcolumn, ilngunits, ilatunits, olngunits, olatunits,
+ center, sbox, cbox, datamin, datamax, back, maxiter, tol, oxformat,
+ oyformat, min_sigdigits)
+
+int infd #I the input file descriptor
+int outfd #I the output file descriptor
+pointer im #I the input image descriptor
+pointer mwin #I the input image wcs
+pointer mwout #I the output image wcs
+pointer cooin #I the input coordinate descriptor
+pointer cooout #I the output coordinate descriptor
+int lngcolumn #I the input ra/longitude column
+int latcolumn #I the input dec/latitude column
+int ilngunits #I the input ra/longitude units
+int ilatunits #I the input dec/latitude units
+int olngunits #I the output ra/longitude units
+int olatunits #I the output dec/latitude units
+bool center #I center the pixel coordinates
+int sbox #I the search box half-width in pixels
+int cbox #I the centering box half-width in pixels
+real datamin #I the minimum good data value
+real datamax #I the maximum good data value
+real back #I the background reference value
+int maxiter #I the maximum number of iterations
+int tol #I the fitting tolerance in pixels
+char oxformat[ARB] #I the output x format
+char oyformat[ARB] #I the output y format
+int min_sigdigits #I the minimum number of significant digits
+
+double ilng, ilat, tlng, tlat, olng, olat
+int nline, ip, max_fields, nfields, offset, nchars, nsdig_lng, nsdig_lat
+int tilngunits, tilatunits, tolngunits, tolatunits, cier, ncenter
+pointer sp, inbuf, linebuf, field_pos, outbuf, ctin, ctout
+pointer toxformat, toyformat
+int sk_stati(), li_get_numd(), getline(), cc_center()
+pointer sk_ictran(), sk_octran()
+errchk sk_ictran(), sk_octran()
+
+begin
+ # Compile the input and output transformations.
+ iferr {
+ ctin = sk_ictran (cooin, mwin)
+ ctout = sk_octran (cooout, mwout)
+ } then
+ return
+
+ # Allocate some memory.
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (linebuf, SZ_LINE, TY_CHAR)
+ call salloc (field_pos, MAX_FIELDS, TY_INT)
+ call salloc (outbuf, SZ_LINE, TY_CHAR)
+ call salloc (toxformat, SZ_FNAME, TY_CHAR)
+ call salloc (toyformat, SZ_FNAME, TY_CHAR)
+
+ # Set the default input and output units.
+ if (ilngunits <= 0)
+ tilngunits = sk_stati (cooin, S_NLNGUNITS)
+ else
+ tilngunits = ilngunits
+ if (ilatunits <= 0)
+ tilatunits = sk_stati (cooin, S_NLATUNITS)
+ else
+ tilatunits = ilatunits
+ if (olngunits <= 0)
+ tolngunits = sk_stati (cooout, S_NLNGUNITS)
+ else
+ tolngunits = olngunits
+ if (olatunits <= 0)
+ tolatunits = sk_stati (cooout, S_NLATUNITS)
+ else
+ tolatunits = olatunits
+
+ # Set the output format.
+ call sk_oformats (cooin, cooout, oxformat, oyformat,
+ tolngunits, tolatunits, Memc[toxformat], Memc[toyformat],
+ SZ_FNAME)
+
+ # Check the input and output units.
+ call sk_iunits (cooin, mwin, tilngunits, tilatunits, tilngunits,
+ tilatunits)
+ call sk_ounits (cooout, mwout, tolngunits, tolatunits, tolngunits,
+ tolatunits)
+
+ # Loop over the input coordinates.
+ max_fields = MAX_FIELDS
+ ncenter = 0
+ for (nline = 1; getline (infd, Memc[inbuf]) != EOF; nline = nline + 1) {
+
+ # Check for blank lines and comment lines.
+ for (ip = inbuf; IS_WHITE(Memc[ip]); ip = ip + 1)
+ ;
+ if (Memc[ip] == '#') {
+ # Pass comment lines on to the output unchanged.
+ call putline (outfd, Memc[inbuf])
+ next
+ } else if (Memc[ip] == '\n' || Memc[ip] == EOS) {
+ # Blank lines too.
+ call putline (outfd, Memc[inbuf])
+ next
+ }
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[linebuf], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[linebuf], Memi[field_pos], max_fields,
+ nfields)
+
+ if (lngcolumn > nfields || latcolumn > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Skipping object %d in file %s: too few fields\n")
+ call pargi (nline)
+ call pargstr (Memc[outbuf])
+ #call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ offset = Memi[field_pos+lngcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], ilng, nsdig_lng)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Skipping object %d in file %s: bad ra value\n")
+ call pargi (nline)
+ call pargstr (Memc[outbuf])
+ #call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ offset = Memi[field_pos+latcolumn-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], ilat, nsdig_lat)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Skipping object %d in file %s: bad dec value\n")
+ call pargi (nline)
+ call pargstr (Memc[outbuf])
+ #call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ # Convert the input coordinates to world coordinates in radians.
+ call sk_incc (cooin, mwin, ctin, tilngunits, tilatunits, ilng,
+ ilat, olng, olat)
+
+ # Perform the transformation.
+ call sk_lltran (cooin, cooout, olng, olat, INDEFD, INDEFD,
+ 0.0d0, 0.0d0, tlng, tlat)
+
+ # Convert the output celestial coordinates from radians to output
+ # coordinates.
+ call sk_outcc (cooout, mwout, ctout, tolngunits, tolatunits,
+ tlng, tlat, olng, olat)
+
+ # Is the object on the image ?
+ if (olng < 0.5d0 || olng > (IM_LEN(im,1) + 0.5d0) ||
+ olat < 0.5d0 || olat > (IM_LEN(im,2) + 0.5d0)) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Skipping object %d in file %s: off image %s\n")
+ call pargi (nline)
+ call pargstr (Memc[outbuf])
+ call pargstr (IM_HDRFILE(im))
+ #call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ # Center the coordinates.
+ if (center) {
+ cier = cc_center (im, sbox, cbox, datamin, datamax, back,
+ maxiter, tol, olng, olat, olng, olat)
+ if (cier == ERR) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf (
+ "Skipping object %d in file %s: cannot center in image %s\n")
+ call pargi (nline)
+ call pargstr (Memc[outbuf])
+ call pargstr (IM_HDRFILE(im))
+ #call putline (outfd, Memc[linebuf])
+ next
+ }
+ }
+
+ # Output the results.
+ call li_append_lined (Memc[linebuf], Memc[outbuf], SZ_LINE,
+ olng, olat, Memc[toxformat], Memc[toyformat], nsdig_lng,
+ nsdig_lat, min_sigdigits)
+ call putline (outfd, Memc[outbuf])
+ ncenter = ncenter + 1
+ }
+
+ call sfree (sp)
+
+ return (ncenter)
+end
+
+
+# CC_CENTER -- Given an initial x and y coordinate compute a more accurate
+# center using a centroiding technique.
+
+int procedure cc_center (im, sbox, cbox, datamin, datamax, back, maxiter,
+ tolerance, xinit, yinit, xcenter, ycenter)
+
+pointer im #I pointer to the input image
+int sbox #I the search box half-width in pixels
+int cbox #I the centering box half-width in pixels
+real datamin #I the minimum good data value
+real datamax #I the maximum good data value
+real back #I the background reference value
+int maxiter #I the maximum number of iterations.
+int tolerance #I the tolerance for convergence in pixels
+double xinit, yinit #I the initial x and y positions
+double xcenter, ycenter #I the final x and y positions
+
+bool converged
+double xold, yold, xnew, ynew
+int i, fbox, x1, x2, y1, y2, nx, ny
+real lo, hi, sky
+pointer buf, sp, xbuf, ybuf
+pointer imgs2r()
+real cc_ctr1d()
+errchk imgs2r(), cc_threshold(), cc_rowsum(), cc_colsum(), cc_ctr1d()
+
+
+begin
+ xold = xinit
+ yold = yinit
+ converged = false
+
+ do i = 1, maxiter {
+
+ if (i == 1)
+ fbox = sbox
+ else
+ fbox = cbox
+ x1 = max (nint (xold) - fbox, 1)
+ x2 = min (nint (xold) + fbox, IM_LEN(im,1))
+ y1 = max (nint (yold) - fbox, 1)
+ y2 = min (nint (yold) + fbox, IM_LEN(im,2))
+ nx = x2 - x1 + 1
+ ny = y2 - y1 + 1
+
+ call smark (sp)
+ call salloc (xbuf, nx, TY_REAL)
+ call salloc (ybuf, ny, TY_REAL)
+
+ iferr {
+ buf = imgs2r (im, x1, x2, y1, y2)
+ call cc_threshold (Memr[buf], nx * ny, datamin, datamax,
+ back, lo, hi, sky)
+ call cc_rowsum (Memr[buf], Memr[xbuf], nx, ny, lo, hi, sky)
+ call cc_colsum (Memr[buf], Memr[ybuf], nx, ny, lo, hi, sky)
+ xnew = x1 + cc_ctr1d (Memr[xbuf], nx)
+ ynew = y1 + cc_ctr1d (Memr[ybuf], ny)
+ } then {
+ call sfree (sp)
+ return (ERR)
+ }
+
+ call sfree (sp)
+
+ # Force at least one iteration.
+ if (i > 1) {
+ if (abs(nint(xnew) - nint(xold)) <= tolerance &&
+ abs(nint(ynew) - nint(yold)) <= tolerance) {
+ converged = true
+ break
+ }
+ }
+
+ xold = xnew
+ yold = ynew
+ }
+
+ if (converged) {
+ xcenter = xnew
+ ycenter = ynew
+ return (OK)
+ } else {
+ xcenter = xinit
+ ycenter = yinit
+ return (ERR)
+ }
+end
+
+
+# CC_THRESHOLD -- Find the low and high thresholds for the subraster.
+
+procedure cc_threshold (raster, npix, datamin, datamax, back, ldatamin,
+ ldatamax, lback)
+
+real raster[ARB] #I input data
+int npix #I length of input data
+real datamin #I minimum good data value
+real datamax #I maximum good data value
+real back #I background value
+real ldatamin #I local minimum good data value
+real ldatamax #I local maximum good data value
+real lback #I local background value
+
+real junk
+int awvgr()
+errchk alimr, awvgr
+
+begin
+ # use the local data min or max for thresholds that are INDEF.
+ if (IS_INDEFR(datamin) || IS_INDEFR(datamax))
+ call alimr (raster, npix, ldatamin, ldatamax)
+ if (! IS_INDEFR(datamin))
+ ldatamin = datamin
+ if (! IS_INDEFR(datamax))
+ ldatamax = datamax
+
+ if (IS_INDEFR(back)) {
+ if (awvgr (raster, npix, lback, junk, ldatamin,
+ ldatamax) <= 0)
+ call error (1, "No data in good data range")
+ } else
+ lback = back
+
+ ldatamin = max (ldatamin, lback)
+ ldatamax = ldatamax
+end
+
+
+# CC_ROWSUM -- Sum all rows in a raster, subject to the thresholds, the
+# background, and other parameters.
+
+procedure cc_rowsum (raster, row, nx, ny, lo, hi, back)
+
+real raster[nx,ny] #I the input 2-D subraster
+real row[ARB] #O the output averaged row vector
+int nx, ny #I dimensions of the subraster
+real lo, hi #I minimum and maximum good data values
+real back #I the background value
+
+int i, j
+real pix, minpix, maxpix
+
+begin
+ # Compute the x marginal.
+ call aclrr (row, nx)
+ do j = 1, ny
+ do i = 1, nx {
+ pix = raster[i,j]
+ if (lo <= pix && pix <= hi)
+ row[i] = row[i] + pix - back
+ }
+ call adivkr (row, real(ny), row, nx)
+
+ # Check for low values.
+ call alimr (row, nx, minpix, maxpix)
+ if (minpix < 0.0)
+ call error (1, "Negative value in marginal row")
+end
+
+
+# CC_COLSUM -- Sum all columns in a raster, subject to the thresholds, the
+# background, and other parameters.
+
+procedure cc_colsum (raster, col, nx, ny, lo, hi, back)
+
+real raster[nx,ny] #I 2-D subraster
+real col[ARB] #O 1-D squashed col vector
+int nx, ny #I dimensions of the subraster
+real lo, hi #I minimum and maximum good data values
+real back #I the background value
+
+
+int i, j
+real pix, minpix, maxpix
+
+begin
+ # Compute the y marginal.
+ call aclrr (col, ny)
+ do j = 1, ny
+ do i = 1, nx {
+ pix = raster[i,j]
+ if (lo <= pix && pix <= hi)
+ col[j] = col[j] + pix - back
+ }
+ call adivkr (col, real(nx), col, ny)
+
+ # Check for low values.
+ call alimr (col, ny, minpix, maxpix)
+ if (minpix < 0.)
+ call error (1, "Negative value in marginal column")
+end
+
+
+# CC_CNTR1D -- Compute the the first moment.
+
+real procedure cc_ctr1d (a, npix)
+
+real a[ARB] #I marginal vector
+int npix #I size of the vector
+
+real centroid, pix, sumi, sumix
+int i
+
+begin
+ sumi = 0.
+ sumix = 0.
+ do i = 1, npix {
+ pix = a[i]
+ sumi = sumi + pix
+ sumix = sumix + pix * (i-1)
+ }
+
+ if (sumi == 0.0)
+ call error (1, "The center is undefined\n")
+ else
+ centroid = sumix / sumi
+
+ return (centroid)
+end
+
diff --git a/pkg/images/imcoords/src/t_ccget.x b/pkg/images/imcoords/src/t_ccget.x
new file mode 100644
index 00000000..8955daf9
--- /dev/null
+++ b/pkg/images/imcoords/src/t_ccget.x
@@ -0,0 +1,1201 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include <evvexpr.h>
+include <math.h>
+include <ctotok.h>
+include <lexnum.h>
+include <ctype.h>
+include <pkg/skywcs.h>
+
+# Define the input data structure
+
+define DC_DLENGTH 10
+define DC_NCOLUMNS Memi[$1] # the number of columns in record
+define DC_LNGCOLUMN Memi[$1+1] # the ra / longitude column index
+define DC_LATCOLUMN Memi[$1+2] # the dec / latitude column index
+define DC_COLNAMES Memi[$1+3] # the column names pointer
+define DC_RECORD Memi[$1+4] # the record pointer
+define DC_COFFSETS Memi[$1+5] # the column offsets
+
+define MAX_NCOLUMNS 100 # the maximum number of columns
+define SZ_COLNAME 19 # the column name
+define TABSIZE 8 # the spacing of the tab stops
+
+# Define the output structure
+
+define EC_ELENGTH 10
+
+define EC_NEXPR Memi[$1] # the number of expressions
+define EC_ELIST Memi[$1+1] # the expression list pointer
+define EC_ERANGES Memi[$1+2] # the expression column ranges
+define EC_EFORMATS Memi[$1+3] # the expression formats
+define EC_ELNGFORMAT Memi[$1+4] # the expression formats
+define EC_ELATFORMAT Memi[$1+5] # the expression formats
+
+define MAX_NEXPR 20
+define MAX_NERANGES 100
+define SZ_EXPR SZ_LINE
+define SZ_EFORMATS 9
+
+# T_CCGET -- Given a field center, field width, and field epoch extract objects
+# within the rectangular field from a catalog.
+
+procedure t_ccget ()
+
+double dlngcenter, dlatcenter, dlngwidth, dlatwidth, tlngcenter, tlatcenter
+double dlng1, dlng2, dlat1, dlat2
+int ip, inlist, ninfiles, outlist, noutfiles, fclngunits, fclatunits
+int fldstat, catstat, outstat, catlngunits, catlatunits, olngunits
+int olatunits, in, out
+pointer sp, lngcenter, latcenter, fcsystem, catsystem, outsystem, olngformat
+pointer olatformat, lngcolumn, latcolumn, colnames, exprs, formats
+pointer infile, outfile, str
+pointer fldcoo, catcoo, outcoo, mw, dc, ec
+bool verbose
+double clgetd()
+pointer cc_dinit(), cc_einit()
+int clpopnu(), clplen(), ctod(), strncmp(), clgwrd(), sk_decwcs()
+int sk_stati(), clgfil(), open()
+bool clgetb(), streq()
+errchk clgwrd()
+
+begin
+ # Open the list of input catalogs. These catalogs must have the
+ # same format.
+ inlist = clpopnu ("input")
+ ninfiles = clplen (inlist)
+ if (ninfiles <= 0) {
+ call eprintf ("Error: The input catalog list is empty\n")
+ call clpcls (inlist)
+ return
+ }
+
+ # Open the list of output catalogs. The number of output catalogs
+ # must be 1 or equal to the number of input catalogs.
+ outlist = clpopnu ("output")
+ noutfiles = clplen (outlist)
+ if (noutfiles <= 0) {
+ call eprintf ("Error: The output catalog list is empty\n")
+ call clpcls (inlist)
+ call clpcls (outlist)
+ return
+ } else if (noutfiles > 1 && noutfiles != ninfiles) {
+ call eprintf (
+ "Error: The number of input and output catalogs are not the same\n")
+ call clpcls (inlist)
+ call clpcls (outlist)
+ return
+ }
+
+ # Get some working space.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (lngcenter, SZ_FNAME, TY_CHAR)
+ call salloc (latcenter, SZ_FNAME, TY_CHAR)
+ call salloc (fcsystem, SZ_FNAME, TY_CHAR)
+ call salloc (catsystem, SZ_FNAME, TY_CHAR)
+ call salloc (lngcolumn, SZ_FNAME, TY_CHAR)
+ call salloc (latcolumn, SZ_FNAME, TY_CHAR)
+ call salloc (colnames, SZ_LINE, TY_CHAR)
+ call salloc (outsystem, SZ_FNAME, TY_CHAR)
+ call salloc (olngformat, SZ_FNAME, TY_CHAR)
+ call salloc (olatformat, SZ_FNAME, TY_CHAR)
+ call salloc (exprs, SZ_LINE, TY_CHAR)
+ call salloc (formats, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the field center coordinates and make some preliminary checks.
+ call clgstr ("lngcenter", Memc[lngcenter], SZ_FNAME)
+ call clgstr ("latcenter", Memc[latcenter], SZ_FNAME)
+ ip = 1
+ if (ctod (Memc[lngcenter], ip, dlngcenter) <= 0)
+ dlngcenter = INDEFD
+ else if (dlngcenter < 0.0 || dlngcenter > 360.0)
+ dlngcenter = INDEFD
+ ip = 1
+ if (ctod (Memc[latcenter], ip, dlatcenter) <= 0)
+ dlatcenter = INDEFD
+ else if (dlatcenter < -90.0 || dlatcenter > 90.0)
+ dlatcenter = INDEFD
+ if (IS_INDEFD(dlngcenter) || IS_INDEFD(dlatcenter)) {
+ call eprintf ( "Error: Undefined field center\n")
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+ return
+ }
+
+ dlngwidth = clgetd ("lngwidth")
+ if (dlngwidth < 0.0 || dlngwidth > 360.0)
+ dlngwidth = INDEFD
+ dlatwidth = clgetd ("latwidth")
+ if (dlatwidth < 0.0 || dlatwidth > 180.0)
+ dlatwidth = INDEFD
+ if (IS_INDEFD(dlngwidth) || IS_INDEFD(dlatwidth)) {
+ call eprintf ( "Error: Undefined field width\n")
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the field coordinate system and convert INDEF to EOS
+ # to avoid passing the wcs decoding routine a large number.
+ call clgstr ("fcsystem", Memc[fcsystem], SZ_FNAME)
+ if (strncmp (Memc[fcsystem], "INDEF", 5) == 0)
+ Memc[fcsystem] = EOS
+
+ # Get the field center coordinate units.
+ iferr (fclngunits = clgwrd ("fclngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ fclngunits = 0
+ iferr (fclatunits = clgwrd ("fclatunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ fclatunits = 0
+
+ # Get the coordinates file format.
+ call clgstr ("lngcolumn", Memc[lngcolumn], SZ_FNAME)
+ call clgstr ("latcolumn", Memc[latcolumn], SZ_FNAME)
+
+ # Get the catalog coordinate system and convert INDEF to EOS
+ # to avoid passing the wcs decoding routine a large number.
+ call clgstr ("catsystem", Memc[catsystem], SZ_FNAME)
+ if (strncmp (Memc[catsystem], "INDEF", 5) == 0)
+ Memc[catsystem] = EOS
+
+ # Get the input catalog coordinate units.
+ iferr (catlngunits = clgwrd ("catlngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ catlngunits = 0
+ iferr (catlatunits = clgwrd ("catlatunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ catlatunits = 0
+
+ # Get the output catalog coordinates system.
+ call clgstr ("outsystem", Memc[outsystem], SZ_FNAME)
+ if (strncmp (Memc[outsystem], "INDEF", 5) == 0)
+ Memc[outsystem] = EOS
+
+ # Get the output catalog coordinate units.
+ iferr (olngunits = clgwrd ("olngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ olngunits = 0
+ iferr (olatunits = clgwrd ("olatunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ olatunits = 0
+ call clgstr ("olngformat", Memc[olngformat], SZ_LINE)
+ call clgstr ("olatformat", Memc[olatformat], SZ_LINE)
+
+ # Get the output catalog format.
+ call clgstr ("colaliases", Memc[colnames], SZ_LINE)
+ call clgstr ("exprs", Memc[exprs], SZ_LINE)
+ call clgstr ("formats", Memc[formats], SZ_LINE)
+
+ verbose = clgetb ("verbose")
+
+ # Open the reference coordinate system.
+ if (streq (Memc[catsystem], Memc[fcsystem]) &&
+ (fclngunits == catlngunits) &&
+ (fclatunits == catlatunits)) {
+ fldcoo = NULL
+ } else {
+ fldstat = sk_decwcs (Memc[fcsystem], mw, fldcoo, NULL)
+ if (fldstat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ fldcoo = NULL
+ }
+ }
+
+ # Open the catalog coordinate system.
+ catstat = sk_decwcs (Memc[catsystem], mw, catcoo, NULL)
+ if (catstat == ERR || mw != NULL) {
+ call eprintf ("Error: Cannot decode the input coordinate system\n")
+ if (mw != NULL)
+ call mw_close (mw)
+ if (fldcoo != NULL)
+ call sk_close (fldcoo)
+ call clpcls (inlist)
+ call clpcls (outlist)
+ call sfree (sp)
+ return
+ }
+
+ # Determine the units of the input coordinate system.
+ if (catlngunits <= 0)
+ catlngunits = sk_stati (catcoo, S_NLNGUNITS)
+ if (catlatunits <= 0)
+ catlatunits = sk_stati (catcoo, S_NLATUNITS)
+ call sk_seti (catcoo, S_NLNGUNITS, catlngunits)
+ call sk_seti (catcoo, S_NLATUNITS, catlatunits)
+ if (fldcoo == NULL) {
+ if (fclngunits <= 0)
+ fclngunits = sk_stati (catcoo, S_NLNGUNITS)
+ if (fclatunits <= 0)
+ fclatunits = sk_stati (catcoo, S_NLATUNITS)
+ } else {
+ if (fclngunits <= 0)
+ fclngunits = sk_stati (fldcoo, S_NLNGUNITS)
+ if (fclatunits <= 0)
+ fclatunits = sk_stati (fldcoo, S_NLATUNITS)
+ call sk_seti (fldcoo, S_NLNGUNITS, fclngunits)
+ call sk_seti (fldcoo, S_NLATUNITS, fclatunits)
+ }
+
+ # Open the output catalog coordinate system.
+ if (streq (Memc[outsystem], Memc[catsystem]) &&
+ (olngunits == catlngunits) &&
+ (olatunits == catlatunits)) {
+ outcoo = NULL
+ } else {
+ outstat = sk_decwcs (Memc[outsystem], mw, outcoo, NULL)
+ if (outstat == ERR || mw != NULL) {
+ call eprintf (
+ "Warning: Cannot decode the output coordinate system\n")
+ if (mw != NULL)
+ call mw_close (mw)
+ outcoo = NULL
+ }
+ }
+
+ # Set the output catalog units.
+ if (outcoo == NULL) {
+ if (olngunits <= 0)
+ olngunits = sk_stati (catcoo, S_NLNGUNITS)
+ if (olatunits <= 0)
+ olatunits = sk_stati (catcoo, S_NLATUNITS)
+ } else {
+ if (olngunits <= 0)
+ olngunits = sk_stati (outcoo, S_NLNGUNITS)
+ if (olatunits <= 0)
+ olatunits = sk_stati (outcoo, S_NLATUNITS)
+ call sk_seti (outcoo, S_NLNGUNITS, olngunits)
+ call sk_seti (outcoo, S_NLATUNITS, olatunits)
+ }
+
+ # Get default output coordinate formats.
+ if (outcoo != NULL) {
+ if (Memc[olngformat] == EOS || Memc[olngformat] == ' ') {
+ switch (sk_stati(outcoo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ call strcpy (" %010.1h", Memc[olngformat], SZ_EFORMATS)
+ case SKY_DEGREES:
+ call strcpy (" %9.0h", Memc[olngformat], SZ_EFORMATS)
+ case SKY_RADIANS:
+ call strcpy (" %9.7g", Memc[olngformat], SZ_EFORMATS)
+ }
+ }
+ if (Memc[olatformat] == EOS || Memc[olngformat] == ' ') {
+ switch (sk_stati(outcoo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ call strcpy (" %010.1h", Memc[olatformat], SZ_EFORMATS)
+ case SKY_DEGREES:
+ call strcpy (" %9.0h", Memc[olatformat], SZ_EFORMATS)
+ case SKY_RADIANS:
+ call strcpy (" %9.7g", Memc[olatformat], SZ_EFORMATS)
+ }
+ }
+ }
+
+ # Convert the field center coordinates to the catalog
+ # coordinate system.
+ if (fldcoo == NULL) {
+ tlngcenter = dlngcenter
+ tlatcenter = dlatcenter
+ } else {
+ call sk_ultran (fldcoo, catcoo, dlngcenter, dlatcenter,
+ tlngcenter, tlatcenter, 1)
+ }
+
+ # Determine the corners of the field in degrees. At present
+ # the maximum longitude width is actually 180 not 360 degrees
+ # and the maximum latitude width is 180 degrees.
+ call cc_limits (catcoo, tlngcenter, tlatcenter, dlngwidth,
+ dlatwidth, dlng1, dlng2, dlat1, dlat2)
+
+ # Flush standard output on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Initialize the data structure.
+ dc = cc_dinit (Memc[colnames], Memc[lngcolumn], Memc[latcolumn])
+
+ # Initialize the expressions structure.
+ ec = cc_einit (Memc[exprs], Memc[formats], Memc[olngformat],
+ Memc[olatformat])
+
+ # Decode the expressions using info in the data structure.
+ call cc_edecode (dc, ec)
+
+ # Loop over the catalog files.
+ while (clgfil (inlist, Memc[infile], SZ_FNAME) != EOF) {
+
+ # Open text file of coordinates.
+ in = open (Memc[infile], READ_ONLY, TEXT_FILE)
+
+ # Open the output file.
+ if (clgfil (outlist, Memc[outfile], SZ_FNAME) != EOF)
+ out = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+
+ # Print the input and output file information.
+ if (verbose && out != STDOUT) {
+ call printf ("\nCatalog File: %s Output File: %s\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[outfile])
+ }
+ if (out != NULL) {
+ call fprintf (out, "\n# Catalog File: %s Output File: %s\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[outfile])
+ }
+
+ # Print information about the field center coordinate system.
+ if (fldcoo == NULL) {
+ if (verbose && out != STDOUT)
+ call sk_iiprint ("Field System", Memc[catsystem], NULL,
+ catcoo)
+ if (out != NULL)
+ call sk_iiwrite (out, "Field System", Memc[catsystem],
+ NULL, catcoo)
+ } else {
+ if (verbose && out != STDOUT)
+ call sk_iiprint ("Field System", Memc[fcsystem], NULL,
+ fldcoo)
+ if (out != NULL)
+ call sk_iiwrite (out, "Field System", Memc[fcsystem], NULL,
+ fldcoo)
+ }
+
+ # Print information about the input coordinate system.
+ if (verbose && out != STDOUT)
+ call sk_iiprint (
+ "Catalog System", Memc[catsystem], NULL, catcoo)
+ if (out != NULL)
+ call sk_iiwrite (out, "Catalog System", Memc[catsystem], NULL,
+ catcoo)
+
+ # Print information about the output coordinate system.
+ if (outcoo == NULL) {
+ if (verbose && out != STDOUT)
+ call sk_iiprint ("Output System", Memc[catsystem], NULL,
+ catcoo)
+ if (out != NULL)
+ call sk_iiwrite (out, "Output System", Memc[catsystem],
+ NULL, catcoo)
+ } else {
+ if (verbose && out != STDOUT)
+ call sk_iiprint ("Output System", Memc[outsystem], NULL,
+ outcoo)
+ if (out != NULL)
+ call sk_iiwrite (out, "Output System", Memc[outsystem],
+ NULL, outcoo)
+ }
+
+ # Print the corners field parameters.
+ if (verbose && out != STDOUT) {
+ if (sk_stati (catcoo, S_NLNGUNITS) == SKY_HOURS)
+ call printf (
+ "#\n# Field Center: %10h %9h Width: %0.4f %0.4f\n")
+ else
+ call printf (
+ "#\n# Field Center: %11h %9h Width: %0.4f %0.4f\n")
+ call pargd (tlngcenter)
+ call pargd (tlatcenter)
+ call pargd (dlngwidth)
+ call pargd (dlatwidth)
+ if (sk_stati (catcoo, S_NLNGUNITS) == SKY_HOURS)
+ call printf ("# Field Limits: %9H %9H %9h %9h\n#\n")
+ else
+ call printf ("# Field Limits: %9h %9h %9h %9h\n#\n")
+ call pargd (dlng1)
+ call pargd (dlng2)
+ call pargd (dlat1)
+ call pargd (dlat2)
+ }
+
+ if (out != NULL) {
+ if (sk_stati (catcoo, S_NLNGUNITS) == SKY_HOURS)
+ call fprintf (out,
+ "#\n# Field Center: %10h %9h Width: %0.4f %0.4f\n")
+ else
+ call fprintf (out,
+ "#\n# Field Center: %11h %9h Width: %0.4f %0.4f\n")
+ call pargd (tlngcenter)
+ call pargd (tlatcenter)
+ call pargd (dlngwidth)
+ call pargd (dlatwidth)
+ if (sk_stati (catcoo, S_NLNGUNITS) == SKY_HOURS)
+ call fprintf (out, "# Field Limits: %9H %9H %9h %9h\n#\n")
+ else
+ call fprintf (out, "# Field Limits: %9h %9h %9h %9h\n#\n")
+ call pargd (dlng1)
+ call pargd (dlng2)
+ call pargd (dlat1)
+ call pargd (dlat2)
+ }
+
+ # Read in the data line by line, selecting the records of
+ # interest.
+ call cc_select (in, out, dc, ec, catcoo, outcoo, tlngcenter,
+ tlatcenter, dlngwidth, dlatwidth, dlng1, dlng2, dlat1,
+ dlat2, verbose)
+
+ call close (in)
+ if (noutfiles == ninfiles)
+ call close (out)
+ }
+
+ call cc_dfree (dc)
+ call cc_efree (ec)
+
+ if (noutfiles != ninfiles)
+ call close (out)
+ if (fldcoo != NULL)
+ call sk_close (fldcoo)
+ call sk_close (catcoo)
+ if (outcoo != NULL)
+ call sk_close (outcoo)
+ call clpcls (inlist)
+ call clpcls (outlist)
+
+ call sfree (sp)
+end
+
+
+# CC_LIMITS - Given the field center and field width compute the ra /
+# longitude and dec / latitude limits of the region of interest.
+
+procedure cc_limits (catcoo, dlngcenter, dlatcenter, dlngwidth, dlatwidth,
+ dlng1, dlng2, dlat1, dlat2)
+
+pointer catcoo #I the pointer to the catalog wcs
+double dlngcenter #I the field center ra / longtitude
+double dlatcenter #I the field center dec / latitude
+double dlngwidth #I the field ra / longitude width (degrees)
+double dlatwidth #I the field dec / latitude width (degrees)
+double dlng1 #O the lower field ra / longitude limit
+double dlng2 #O the upper field ra / longitude limit
+double dlat1 #O the lower field dec / latitude limit
+double dlat2 #O the upper field dec / longitude limit
+
+double tlngcenter, tlatcenter, cosdec, dhlngwidth
+int sk_stati()
+
+begin
+ # Convert the field center coordinates to degrees.
+ switch (sk_stati(catcoo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ tlngcenter = 15.0d0 * dlngcenter
+ case SKY_DEGREES:
+ tlngcenter = dlngcenter
+ case SKY_RADIANS:
+ tlngcenter = RADTODEG(dlngcenter)
+ default:
+ tlngcenter = dlngcenter
+ }
+ switch (sk_stati (catcoo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ tlatcenter = 15.0d0 * dlatcenter
+ case SKY_DEGREES:
+ tlatcenter = dlatcenter
+ case SKY_RADIANS:
+ tlatcenter = RADTODEG(dlatcenter)
+ default:
+ tlatcenter = dlatcenter
+ }
+
+ # Find the field corners.
+ dlat1 = tlatcenter - 0.5d0 * dlatwidth
+ if (dlat1 <= -90.0d0) {
+ dlat1 = -90.0d0
+ dlat2 = min (tlatcenter + 0.5d0 * dlatwidth, 90.0d0)
+ dlng1 = 0.0d0
+ dlng2 = 360.0d0
+ return
+ }
+
+ dlat2 = tlatcenter + 0.5d0 * dlatwidth
+ if (dlat2 >= 90.0d0) {
+ dlat2 = 90.0d0
+ dlat1 = max (tlatcenter - 0.5d0 * dlatwidth, -90.0d0)
+ dlng1 = 0.0d0
+ dlng2 = 360.0d0
+ return
+ }
+
+ if (tlatcenter > 0.0d0)
+ cosdec = cos (DEGTORAD(dlat2))
+ else
+ cosdec = cos (DEGTORAD(dlat1))
+ dhlngwidth = 0.5d0 * dlngwidth / cosdec
+ if (dhlngwidth >= 180.0d0) {
+ dlng1 = 0.0d0
+ dlng2 = 360.0d0
+ } else {
+ dlng1 = tlngcenter - dhlngwidth
+ if (dlng1 < 0.0d0)
+ dlng1 = dlng1 + 360.0d0
+ dlng2 = tlngcenter + dhlngwidth
+ if (dlng2 > 360.0d0)
+ dlng2 = dlng2 - 360.0d0
+ }
+end
+
+
+# CC_SELECT -- Select and print the records matching the field position
+# and size criteria.
+
+procedure cc_select (in, out, dc, ec, catcoo, outcoo, lngcenter, latcenter,
+ lngwidth, latwidth, dlng1, dlng2, dlat1, dlat2, verbose)
+
+int in #I the input file file descriptor
+int out #I the output file descriptor
+pointer dc #I the file data structure
+pointer ec #I the expression structure
+pointer catcoo #I the input catalog coordinate structure
+pointer outcoo #I the output catalog coordinate structure
+double lngcenter, latcenter #I the field center coordinates
+double lngwidth, latwidth #I the field widths in degrees
+double dlng1, dlng2 #I the ra / longitude limits in degrees
+double dlat1, dlat2 #I the dec / latitude limits in degrees
+bool verbose #I verbose mode
+
+double dlngcenter, dlatcenter, tlng, tlat, dlng, dlat, dist
+double tmplng, tlngcenter
+int ip, op, i, j, nline, lngoffset, latoffset, offset1, offset2, nsig
+pointer sp, inbuf, outbuf, newval, eptr, rptr, fptr, pexpr
+pointer evvexpr(), locpr()
+int getline(), li_get_numd(), sk_stati(), gstrcpy(), strlen()
+bool streq()
+extern cc_getop()
+
+begin
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (outbuf, SZ_LINE, TY_CHAR)
+ call salloc (newval, SZ_LINE, TY_CHAR)
+
+ # Convert the field center coordinates to degrees.
+ switch (sk_stati(catcoo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ dlngcenter = 15.0d0 * lngcenter
+ case SKY_RADIANS:
+ dlngcenter = RADTODEG(lngcenter)
+ default:
+ dlngcenter = lngcenter
+ }
+ switch (sk_stati (catcoo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ dlatcenter = 15.0d0 * latcenter
+ case SKY_RADIANS:
+ dlatcenter = RADTODEG(latcenter)
+ default:
+ dlatcenter = latcenter
+ }
+
+ for (nline = 1; getline (in, Memc[inbuf]) != EOF; nline = nline + 1) {
+
+ # Skip over leading white space.
+ for (ip = inbuf; IS_WHITE(Memc[ip]); ip = ip + 1)
+ ;
+
+ # Skip comment and blank lines.
+ if (Memc[ip] == '#')
+ next
+ else if (Memc[ip] == '\n' || Memc[ip] == EOS)
+ next
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[DC_RECORD(dc)], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[DC_RECORD(dc)], Memi[DC_COFFSETS(dc)],
+ MAX_NCOLUMNS, DC_NCOLUMNS(dc))
+
+ # Decode the longitude coordinate.
+ if (DC_LNGCOLUMN(dc) > DC_NCOLUMNS(dc))
+ next
+ lngoffset = Memi[DC_COFFSETS(dc)+DC_LNGCOLUMN(dc)-1]
+ if (li_get_numd (Memc[DC_RECORD(dc)+lngoffset-1], tlng, nsig) == 0)
+ next
+
+ # Decode the latitude coordinate.
+ if (DC_LATCOLUMN(dc) > DC_NCOLUMNS(dc))
+ next
+ latoffset = Memi[DC_COFFSETS(dc)+DC_LATCOLUMN(dc)-1]
+ if (li_get_numd (Memc[DC_RECORD(dc)+latoffset-1], tlat, nsig) == 0)
+ next
+
+ # Convert the catalog coordinates to degrees.
+ switch (sk_stati(catcoo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ dlng = 15.0d0 * tlng
+ case SKY_RADIANS:
+ dlng = RADTODEG(tlng)
+ default:
+ dlng = tlng
+ }
+ switch (sk_stati (catcoo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ dlat = 15.0d0 * tlat
+ case SKY_RADIANS:
+ dlat = RADTODEG(tlat)
+ default:
+ dlat = tlat
+ }
+
+ # Test the converted ra /dec or longitude / latitude value
+ # versus the user defined ra / longitude and dec / latitude
+ # limits.
+ if (dlat < dlat1 || dlat > dlat2)
+ next
+ if (dlng1 < dlng2) {
+ if (dlng >= dlng1 && dlng <= dlng2)
+ ;
+ else
+ next
+ } else {
+ if (dlng > dlng2 && dlng < dlng1)
+ next
+ else
+ ;
+ }
+
+ # Check the longitude coordinate distance to remove pathologies
+ # in longitude or latitude strips involving the pole. This is
+ # an extra test of my own.
+ if (dlng1 < dlng2) {
+ dist = abs (dlng - dlngcenter)
+ } else {
+ if (dlng > dlng1)
+ tmplng = dlng - 360.0d0
+ else
+ tmplng = dlng
+ if (dlngcenter > dlng1)
+ tlngcenter = dlngcenter - 360.0d0
+ else
+ tlngcenter = dlngcenter
+ dist = abs (tmplng - tlngcenter)
+ }
+ if (abs (2.0d0*dist*cos(DEGTORAD(dlat))) > lngwidth)
+ next
+
+ # If all the columns are selected and no column expressions have
+ # been defined dump the input records to the output.
+
+ if (outcoo == NULL && (streq (Memc[EC_ELIST(ec)], "*") ||
+ streq (Memc[EC_ELIST(ec)], "c[*]"))) {
+ if (verbose && out != STDOUT)
+ call putline (STDOUT, Memc[DC_RECORD(dc)])
+ if (out != NULL)
+ call putline (out, Memc[DC_RECORD(dc)])
+ next
+ }
+
+ # Otherwise loop through the user specified output fields
+ # and expressions.
+
+ # Initialize the expression list pointers.
+ rptr = EC_ERANGES(ec)
+ eptr = EC_ELIST(ec)
+ fptr = EC_EFORMATS(ec)
+
+ # Initiliaze the output buffer.
+ op = outbuf
+ Memc[op] = EOS
+
+ do i = 1, EC_NEXPR(ec) {
+
+ # The next user output field is an expression.
+ if (IS_INDEFI(Memi[rptr])) {
+
+ pexpr = evvexpr (Memc[eptr], locpr (cc_getop), dc, 0, dc, 0)
+ switch (O_TYPE(pexpr)) {
+ case TY_BOOL:
+ if (Memc[fptr] == '%')
+ call sprintf (Memc[newval], SZ_LINE, Memc[fptr])
+ else
+ call sprintf (Memc[newval], SZ_LINE, "%5b")
+ call pargi (O_VALI(pexpr))
+ case TY_CHAR:
+ if (Memc[fptr] == '%')
+ call sprintf (Memc[newval], SZ_LINE, Memc[fptr])
+ else
+ call sprintf (Memc[newval], SZ_LINE, " %s")
+ call pargstr (O_VALC(pexpr))
+ case TY_INT:
+ if (Memc[fptr] == '%')
+ call sprintf (Memc[newval], SZ_LINE, Memc[fptr])
+ else
+ call sprintf (Memc[newval], SZ_LINE, " %10d")
+ call pargi (O_VALI(pexpr))
+ case TY_REAL:
+ if (Memc[fptr] == '%')
+ call sprintf (Memc[newval], SZ_LINE, Memc[fptr])
+ else
+ call sprintf (Memc[newval], SZ_LINE, " %10g")
+ call pargr (O_VALR(pexpr))
+ case TY_DOUBLE:
+ if (Memc[fptr] == '%')
+ call sprintf (Memc[newval], SZ_LINE, Memc[fptr])
+ else
+ call sprintf (Memc[newval], SZ_LINE, " %10g")
+ call pargd (O_VALD(pexpr))
+ }
+ op = op + gstrcpy (Memc[newval], Memc[op],
+ min (SZ_LINE - op + outbuf, strlen (Memc[newval])))
+
+ # The next user fields are columns.
+ } else if (Memi[rptr] >= 1 && Memi[rptr+1] <= MAX_NCOLUMNS) {
+
+ # Transform the coordinates if necessary.
+ if (outcoo != NULL)
+ call sk_ultran (catcoo, outcoo, tlng, tlat, tlng,
+ tlat, 1)
+
+ pexpr = NULL
+ do j = max (1, Memi[rptr]), min (Memi[rptr+1],
+ DC_NCOLUMNS(dc)), Memi[rptr+2] {
+ offset1 = Memi[DC_COFFSETS(dc)+j-1]
+ offset2 = Memi[DC_COFFSETS(dc)+j]
+ if (outcoo != NULL && offset1 == lngoffset) {
+ call sprintf (Memc[newval], SZ_LINE,
+ Memc[EC_ELNGFORMAT(ec)])
+ call pargd (tlng)
+ op = op + gstrcpy (Memc[newval], Memc[op],
+ min (SZ_LINE - op + outbuf,
+ strlen (Memc[newval])))
+ } else if (outcoo != NULL && offset1 == latoffset) {
+ call sprintf (Memc[newval], SZ_LINE,
+ Memc[EC_ELATFORMAT(ec)])
+ call pargd (tlat)
+ op = op + gstrcpy (Memc[newval], Memc[op],
+ min (SZ_LINE - op + outbuf,
+ strlen (Memc[newval])))
+ } else
+ op = op + gstrcpy (Memc[DC_RECORD(dc)+offset1-1],
+ Memc[op], min (SZ_LINE - op + outbuf,
+ offset2 - offset1))
+ }
+ }
+
+ # Update the expression list pointers.
+ eptr = eptr + SZ_EXPR + 1
+ rptr = rptr + 3
+ fptr = fptr + SZ_EFORMATS + 1
+ if (pexpr != NULL)
+ call mfree (pexpr, TY_STRUCT)
+ }
+
+ # Attach a newline and EOS to the newly formatted line and output
+ # it.
+ if (Memc[outbuf] != EOS) {
+ Memc[op] = '\n'
+ Memc[op+1] = EOS
+ if (verbose && out != STDOUT)
+ call putline (STDOUT, Memc[outbuf])
+ if (out != NULL)
+ call putline (out, Memc[outbuf])
+ }
+
+ }
+
+ call sfree (sp)
+end
+
+
+# CC_DINIT -- Initialize the ccget data structure.
+
+pointer procedure cc_dinit (cnames, lngname, latname)
+
+char cnames[ARB] #I optional list of columm names
+char lngname[ARB] #I the ra / longitude column name or number
+char latname[ARB] #I the dec / latitude column name or number
+
+int i, ip, op
+pointer dc, cptr
+int cc_cnames(), ctotok(), ctoi()
+bool streq()
+
+begin
+ call calloc (dc, DC_DLENGTH, TY_STRUCT)
+
+ # Define the column names.
+ call calloc (DC_COLNAMES(dc), MAX_NCOLUMNS * (SZ_COLNAME + 1), TY_CHAR)
+ Memc[DC_COLNAMES(dc)] = EOS
+
+ ip = 1
+ cptr = DC_COLNAMES(dc)
+ do i = 1, MAX_NCOLUMNS {
+ op = 1
+ if (cc_cnames (cnames, ip, Memc[cptr], SZ_COLNAME) == EOF) {
+ call sprintf (Memc[cptr], SZ_COLNAME, "c%d")
+ call pargi (i)
+ } else if (ctotok (Memc[cptr], op, Memc[cptr], SZ_COLNAME) !=
+ TOK_IDENTIFIER) {
+ call sprintf (Memc[cptr], SZ_COLNAME, "c%d")
+ call pargi (i)
+ }
+ call strlwr (Memc[cptr])
+ cptr = cptr + SZ_COLNAME + 1
+ }
+
+ # Find the longitude and latitude columns.
+ ip = 1
+ DC_LNGCOLUMN(dc) = 0
+ if (ctoi (lngname, ip, DC_LNGCOLUMN(dc)) <= 0) {
+ cptr = DC_COLNAMES(dc)
+ do i = 1, MAX_NCOLUMNS {
+ if (streq (lngname, Memc[cptr])) {
+ DC_LNGCOLUMN(dc) = i
+ break
+ }
+ cptr = cptr + SZ_COLNAME + 1
+ }
+ }
+ if (DC_LNGCOLUMN(dc) <= 0)
+ DC_LNGCOLUMN(dc) = 2
+
+ ip = 1
+ DC_LATCOLUMN(dc) = 0
+ if (ctoi (latname, ip, DC_LATCOLUMN(dc)) <= 0) {
+ cptr = DC_COLNAMES(dc)
+ do i = 1, MAX_NCOLUMNS {
+ if (streq (latname, Memc[cptr])) {
+ DC_LATCOLUMN(dc) = i
+ break
+ }
+ cptr = cptr + SZ_COLNAME + 1
+ }
+ }
+ if (DC_LATCOLUMN(dc) <= 0)
+ DC_LATCOLUMN(dc) = DC_LNGCOLUMN(dc) + 1
+
+ call calloc (DC_RECORD(dc), SZ_LINE, TY_CHAR)
+ Memc[DC_RECORD(dc)) = EOS
+
+ call calloc (DC_COFFSETS(dc), MAX_NCOLUMNS + 1, TY_INT)
+
+ return (dc)
+end
+
+
+# CC_DFREE -- Free the ccget data structure.
+
+procedure cc_dfree (dc)
+
+pointer dc #U pointer to the data structure
+
+begin
+ call mfree (DC_COLNAMES(dc), TY_CHAR)
+ call mfree (DC_RECORD(dc), TY_CHAR)
+ call mfree (DC_COFFSETS(dc), TY_INT)
+ call mfree (dc, TY_STRUCT)
+end
+
+
+# CC_CNAMES -- Decode the list of column names into individual column names.
+
+int procedure cc_cnames (colnames, ip, name, maxch)
+
+char colnames[ARB] #I list of column names
+int ip #I pointer into the list of names
+char name[ARB] #O the output column name
+int maxch #I maximum length of a column name
+
+int op, token
+int ctotok(), strlen()
+
+begin
+ # Decode the column labels.
+ op = 1
+ while (colnames[ip] != EOS) {
+
+ token = ctotok (colnames, ip, name[op], maxch)
+ if (name[op] == EOS)
+ next
+
+ #if ((token == TOK_UNKNOWN) || (token == TOK_CHARCON))
+ #break
+
+ if ((token == TOK_PUNCTUATION) && (name[op] == ',')) {
+ if (op == 1)
+ next
+ else
+ break
+ }
+
+ if (token != TOK_IDENTIFIER) {
+ op = 1
+ next
+ }
+
+ op = op + strlen (name[op])
+ if (colnames[ip] == ' ') {
+ if (op == 1)
+ next
+ else
+ break
+ }
+ }
+
+ name[op] = EOS
+ if ((colnames[ip] == EOS) && (op == 1))
+ return (EOF)
+ else
+ return (op - 1)
+end
+
+
+# CC_EINIT -- Initialize the ccget expression structure.
+
+pointer procedure cc_einit (exprs, formats, lngformat, latformat)
+
+char exprs[ARB] #I the input expression list
+char formats[ARB] #I the input formats list
+char lngformat[ARB] #I the input output ra / longitude format
+char latformat[ARB] #I the input output dec / latitude format
+
+int i, ip, nexpr
+pointer ec, cptr, fptr
+int cc_enames()
+
+begin
+ call calloc (ec, EC_ELENGTH, TY_STRUCT)
+
+ # Define the column names.
+ call malloc (EC_ELIST(ec), MAX_NEXPR * (SZ_EXPR + 1), TY_CHAR)
+ Memc[EC_ELIST(ec)] = EOS
+
+ # Create list of expressions.
+ ip = 1
+ cptr = EC_ELIST(ec)
+ nexpr = 0
+ do i = 1, MAX_NEXPR {
+ if (cc_enames (exprs, ip, Memc[cptr], SZ_EXPR) == EOF)
+ break
+ call strlwr (Memc[cptr])
+ cptr = cptr + SZ_EXPR + 1
+ nexpr = nexpr + 1
+ }
+ EC_NEXPR(ec) = nexpr
+
+
+ # Decode the list of expressions into column names, column ranges,
+ # and column expressions.
+ call calloc (EC_ERANGES(ec), 3 * MAX_NERANGES + 1, TY_INT)
+
+ call calloc (EC_EFORMATS(ec), MAX_NEXPR * (SZ_EFORMATS + 1), TY_CHAR)
+ Memc[EC_EFORMATS(ec)] = EOS
+ ip = 1
+ fptr = EC_EFORMATS(ec)
+ cptr = EC_ELIST(ec)
+ do i = 1, EC_NEXPR(ec) {
+ if (cc_enames (formats, ip, Memc[fptr], SZ_EFORMATS) == EOF)
+ break
+ fptr = fptr + SZ_EFORMATS + 1
+ cptr = cptr + SZ_EXPR + 1
+ }
+
+ call calloc (EC_ELNGFORMAT(ec), SZ_EFORMATS, TY_CHAR)
+ call strcpy (lngformat, Memc[EC_ELNGFORMAT(ec)], SZ_EFORMATS)
+ call calloc (EC_ELATFORMAT(ec), SZ_EFORMATS, TY_CHAR)
+ call strcpy (latformat, Memc[EC_ELATFORMAT(ec)], SZ_EFORMATS)
+
+ return (ec)
+end
+
+
+# CC_EFREE -- Free the ccget expression structure.
+
+procedure cc_efree (ec)
+
+pointer ec #U pointer to the expression structure
+
+begin
+ call mfree (EC_ELIST(ec), TY_CHAR)
+ call mfree (EC_ERANGES(ec), TY_INT)
+ call mfree (EC_EFORMATS(ec), TY_CHAR)
+ call mfree (EC_ELNGFORMAT(ec), TY_CHAR)
+ call mfree (EC_ELATFORMAT(ec), TY_CHAR)
+ call mfree (ec, TY_STRUCT)
+end
+
+
+# CC_ENAMES -- Decode the list of expressions into individual expressions.
+
+int procedure cc_enames (exprs, ip, name, maxch)
+
+char exprs[ARB] #I list of expressions
+int ip #I pointer into the list of names
+char name[ARB] #O the output column name
+int maxch #I maximum length of a column name
+
+int op, token
+int ctotok(), strlen()
+
+begin
+ # Decode the column labels.
+ op = 1
+ while (exprs[ip] != EOS) {
+
+ token = ctotok (exprs, ip, name[op], maxch)
+ if (name[op] == EOS)
+ next
+
+ if ((token == TOK_PUNCTUATION) && (name[op] == ',')) {
+ if (op == 1)
+ next
+ else
+ break
+ }
+
+
+ op = op + strlen (name[op])
+ }
+
+ name[op] = EOS
+ if ((exprs[ip] == EOS) && (op == 1))
+ return (EOF)
+ else
+ return (op - 1)
+end
+
+
+# CC_EDECODE -- Decode the expression list.
+
+procedure cc_edecode (dc, ec)
+
+pointer dc #I the pointer to the data structure
+pointer ec #I the pointer to the expression structure
+
+int i, j, ip1, ip2, c1, c2, lindex, rindex, column
+pointer sp, ename, eptr, cptr, rptr
+char lbracket, rbracket
+int ctotok(), strldx(), ctoi()
+bool streq()
+
+begin
+ call smark (sp)
+ call salloc (ename, SZ_EXPR, TY_CHAR)
+
+ # Initialize.
+ lbracket = '['
+ rbracket = ']'
+ eptr = EC_ELIST(ec)
+ rptr = EC_ERANGES(ec)
+
+ do i = 1, EC_NEXPR(ec) {
+
+ ip1 = 1
+ lindex = strldx (lbracket, Memc[eptr])
+ rindex = strldx (rbracket, Memc[eptr])
+ ip2 = lindex + 1
+ if (Memc[eptr] == 'c' && lindex == 2 && rindex > lindex) {
+ if (Memc[eptr+lindex] == '*') {
+ c1 = 1
+ c2 = MAX_NCOLUMNS
+ } else {
+ if (ctoi (Memc[eptr], ip2, c1) <= 0)
+ c1 = 0
+ else if (c1 < 1 || c1 > MAX_NCOLUMNS)
+ c1 = 0
+ if (ctoi (Memc[eptr], ip2, c2) <= 0)
+ c2 = 0
+ else
+ c2 = -c2
+ if (c2 < 1 || c2 > MAX_NCOLUMNS)
+ c2 = 0
+ }
+
+ if (c1 > 0 && c2 > c1) {
+ Memi[rptr] = c1
+ Memi[rptr+1] = c2
+ Memi[rptr+2] = 1
+ }
+ } else if (ctotok (Memc[eptr], ip1, Memc[ename], SZ_EXPR) ==
+ TOK_IDENTIFIER) {
+ cptr = DC_COLNAMES(dc)
+ column = 0
+ do j = 1, MAX_NCOLUMNS {
+ if (streq (Memc[eptr], Memc[cptr])) {
+ column = j
+ break
+ }
+ cptr = cptr + SZ_COLNAME + 1
+ }
+ if (column > 0) {
+ Memi[rptr] = j
+ Memi[rptr+1] = j
+ Memi[rptr+2] = 1
+ } else if (ctotok (Memc[eptr], ip1, Memc[ename], SZ_EXPR) !=
+ EOS) {
+ Memi[rptr] = INDEFI
+ Memi[rptr+1] = INDEFI
+ Memi[rptr+2] = INDEFI
+ }
+ } else {
+ Memi[rptr] = INDEFI
+ Memi[rptr+1] = INDEFI
+ Memi[rptr+2] = INDEFI
+ }
+ eptr = eptr + SZ_EXPR + 1
+ rptr = rptr + 3
+ }
+
+ call sfree (sp)
+end
+
+
+# CC_GETOP -- Fetch an operand from the data structure.
+
+procedure cc_getop (dc, operand, o)
+
+pointer dc #I pointer to the data structure
+char operand[ARB] #I name of operand to be returned
+pointer o #I pointer to output operand
+
+int ip, column, offset, csize, type, nchars
+pointer cptr
+bool streq()
+int lexnum(), ctod(), ctoi()
+
+begin
+ # Find the symbol.
+ cptr = DC_COLNAMES(dc)
+ column = 0
+ do ip = 1, MAX_NCOLUMNS {
+ if (streq (operand, Memc[cptr])) {
+ column = ip
+ break
+ }
+ cptr = cptr + SZ_COLNAME + 1
+ }
+ if (column <= 0)
+ call xvv_error1 ("Column '%s' not found", operand[1])
+
+ # Find column pointer.
+ offset = Memi[DC_COFFSETS(dc)+column-1]
+ csize = Memi[DC_COFFSETS(dc)+column] - offset
+ cptr = DC_RECORD(dc)+offset-1
+
+ # Determine the type of the symbol.
+ ip = 1
+ type = lexnum (Memc[cptr], ip, nchars)
+ #if (Memc[cptr+nchars+ip-1] != EOS)
+ #type = LEX_NONNUM
+
+ # Decode the symbol.
+ switch (type) {
+ case LEX_OCTAL, LEX_DECIMAL, LEX_HEX:
+ call xvv_initop (o, 0, TY_INT)
+ ip = 1
+ nchars = ctoi (Memc[cptr], ip, O_VALI(o))
+ case LEX_REAL:
+ call xvv_initop (o, 0, TY_DOUBLE)
+ ip = 1
+ nchars = ctod (Memc[cptr], ip, O_VALD(o))
+ case LEX_NONNUM:
+ call xvv_initop (o, csize, TY_CHAR)
+ call strcpy (Memc[cptr], O_VALC(o), csize)
+ }
+end
diff --git a/pkg/images/imcoords/src/t_ccmap.x b/pkg/images/imcoords/src/t_ccmap.x
new file mode 100644
index 00000000..969438be
--- /dev/null
+++ b/pkg/images/imcoords/src/t_ccmap.x
@@ -0,0 +1,2079 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include <ctype.h>
+include <math.h>
+include <math/gsurfit.h>
+include <imhdr.h>
+include <pkg/skywcs.h>
+include "../../lib/geomap.h"
+
+# Define the source of the reference point.
+define CC_REFPOINTSTR "|coords|user|tweak|"
+define CC_COORDS 1
+define CC_USER 2
+define CC_TWEAK 3
+
+# Define the possible pixel types.
+define CC_PIXTYPESTR "|logical|physical|"
+define CC_LOGICAL 1
+define CC_PHYSICAL 2
+
+# Define some limits on the input file
+define MAX_FIELDS 100 # the max number of fields in the list
+define TABSIZE 8 # the spacing of the tab stops
+
+# Define the default data buffer size
+define CC_DEFBUFSIZE 1000 # the default buffer size
+
+# T_CCMAP -- Compute the linear portion of the transformation required
+# to convert image x and y coordinates to ra / longitude and dec / latitude
+# coordinates. This version allows combining multiple inputs with different
+# tangent points (as in a dither set) to create a single solution.
+
+procedure t_ccmap ()
+
+pointer in, im, tdxref, tdyref, tdlngref, tdlatref
+pointer sp, infile, image, database, insystem, refsystem, str
+pointer xref, yref, lngref, latref
+pointer graphics, coo, refcoo, tcoo, mw, fit, out, gd, projstr
+double dxref, dyref, dlngref, dlatref, xmin, xmax, ymin, ymax, reject
+int i, inlist, ninfiles, nin, imlist, nimages, coostat, refstat, nchars, ip
+int xreflist, yreflist, lngreflist, latreflist
+int xcolumn, ycolumn, lngcolumn, latcolumn, lngunits, latunits, res, pfd
+int lngrefunits, latrefunits, refpoint_type, tweak, projection
+int reslist, nresfiles
+int geometry, function, xxorder, xyorder, xxterms, yxorder, yyorder, yxterms
+int reclist, nrecords, pixsys, maxiter
+bool verbose, update, interactive
+
+double clgetd()
+pointer dtmap(), immap(), gopen(), cc_utan(), cc_imtan()
+int clpopnu(), clplen(), imtopenp(), imtlen(), clgeti(), clgwrd(), strlen()
+int sk_decwcs(), sk_stati(), imtgetim(), clgfil(), open(), ctod()
+int errget(), imtopen(), strncmp(), cc_rdproj(), strdic()
+bool clgetb()
+errchk open(), cc_map()
+
+begin
+ # Get some working space.
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (database, SZ_FNAME, TY_CHAR)
+ call salloc (insystem, SZ_FNAME, TY_CHAR)
+ call salloc (xref, SZ_FNAME, TY_CHAR)
+ call salloc (yref, SZ_FNAME, TY_CHAR)
+ call salloc (lngref, SZ_FNAME, TY_CHAR)
+ call salloc (latref, SZ_FNAME, TY_CHAR)
+ call salloc (refsystem, SZ_FNAME, TY_CHAR)
+ call salloc (graphics, SZ_FNAME, TY_CHAR)
+ call salloc (projstr, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the input data file list.
+ inlist = clpopnu ("input")
+ ninfiles = clplen (inlist)
+ if (ninfiles <= 0) {
+ call eprintf ("Error: The input coordinate file list is empty\n")
+ call clpcls (inlist)
+ call sfree (sp)
+ return
+ }
+
+ # Open the database output file.
+ call clgstr ("database", Memc[database], SZ_FNAME)
+ out = dtmap (Memc[database], APPEND)
+
+ # Open the record list.
+ call clgstr ("solutions", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS) {
+ reclist = NULL
+ nrecords = 0
+ } else {
+ reclist = imtopen (Memc[str])
+ nrecords = imtlen (reclist)
+ }
+ if (nrecords > 1 && nrecords != ninfiles) {
+ call eprintf ("Error: List of record names does not match input\n")
+ call clpcls (inlist)
+ call dtunmap (out)
+ if (reclist != NULL)
+ call imtclose (reclist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the input image list.
+ imlist = imtopenp ("images")
+ nimages = imtlen (imlist)
+ if (nimages > 1 && nimages != ninfiles) {
+ call eprintf ("Error: Coordinate files and images don't match\n")
+ call imtclose (imlist)
+ call clpcls (inlist)
+ call dtunmap (out)
+ if (reclist != NULL)
+ call imtclose (reclist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the output results lists.
+ reslist = clpopnu ("results")
+ nresfiles = clplen (reslist)
+ if (nresfiles > 1 && nresfiles != ninfiles) {
+ call eprintf ("Error: List of results files does not match input\n")
+ call imtclose (imlist)
+ call clpcls (inlist)
+ call clpcls (reslist)
+ call dtunmap (out)
+ if (reclist != NULL)
+ call imtclose (reclist)
+ call sfree (sp)
+ return
+ }
+
+ # Get the coordinates file format.
+ xcolumn = clgeti ("xcolumn")
+ ycolumn = clgeti ("ycolumn")
+ lngcolumn = clgeti ("lngcolumn")
+ latcolumn = clgeti ("latcolumn")
+ call clgstr ("insystem", Memc[insystem], SZ_FNAME)
+ iferr (lngunits = clgwrd ("lngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ lngunits = 0
+ iferr (latunits = clgwrd ("latunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ latunits = 0
+
+ # Get the reference point parameters.
+ refpoint_type = clgwrd ("refpoint", Memc[str], SZ_FNAME,
+ CC_REFPOINTSTR)
+ tweak = refpoint_type
+ xreflist = clpopnu ("xref")
+ yreflist = clpopnu ("yref")
+ lngreflist = clpopnu ("lngref")
+ latreflist = clpopnu ("latref")
+ call clgstr ("refsystem", Memc[refsystem], SZ_FNAME)
+ if (strncmp (Memc[refsystem], "INDEF", 5) == 0)
+ Memc[refsystem] = EOS
+ iferr (lngrefunits = clgwrd ("lngrefunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ lngrefunits = 0
+ iferr (latrefunits = clgwrd ("latrefunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ latrefunits = 0
+
+ # Get the minimum and maximum reference values.
+ xmin = clgetd ("xmin")
+ xmax = clgetd ("xmax")
+ ymin = clgetd ("ymin")
+ ymax = clgetd ("ymax")
+
+ # Get the coordinate mapping parameters.
+ call clgstr ("projection", Memc[str], SZ_LINE)
+ iferr {
+ pfd = open (Memc[str], READ_ONLY, TEXT_FILE)
+ } then {
+ projection = strdic (Memc[str], Memc[str], SZ_LINE, GM_PROJLIST)
+ if (projection <= 0 || projection == WTYPE_LIN)
+ Memc[projstr] = EOS
+ else
+ call strcpy (Memc[str], Memc[projstr], SZ_LINE)
+ } else {
+ projection = cc_rdproj (pfd, Memc[projstr], SZ_LINE)
+ call close (pfd)
+ }
+ geometry = clgwrd ("fitgeometry", Memc[str], SZ_LINE, GM_GEOMETRIES)
+ function = clgwrd ("function", Memc[str], SZ_LINE, GM_FUNCS)
+ xxorder = clgeti ("xxorder")
+ xyorder = clgeti ("xyorder")
+ xxterms = clgwrd ("xxterms", Memc[str], SZ_LINE, GM_XFUNCS) - 1
+ yxorder = clgeti ("yxorder")
+ yyorder = clgeti ("yyorder")
+ yxterms = clgwrd ("yxterms", Memc[str], SZ_LINE, GM_XFUNCS) - 1
+ maxiter = clgeti ("maxiter")
+ reject = clgetd ("reject")
+
+ # Get the input and output parameters.
+ update = clgetb ("update")
+ iferr (pixsys = clgwrd ("pixsystem", Memc[str], SZ_FNAME,
+ CC_PIXTYPESTR))
+ pixsys = PIXTYPE_LOGICAL
+ else if (pixsys == CC_PHYSICAL)
+ pixsys = PIXTYPE_PHYSICAL
+ else
+ pixsys = PIXTYPE_LOGICAL
+ verbose = clgetb ("verbose")
+
+ # Open the input coordinate system.
+ coostat = sk_decwcs (Memc[insystem], mw, coo, NULL)
+ if (coostat == ERR || mw != NULL) {
+ call eprintf ("Error: Cannot decode the input coordinate system\n")
+ if (mw != NULL)
+ call mw_close (mw)
+ call imtclose (imlist)
+ call clpcls (inlist)
+ call clpcls (reslist)
+ call dtunmap (out)
+ call sfree (sp)
+ return
+ }
+
+ # Determine the units of the input coordinate system.
+ if (lngunits <= 0)
+ lngunits = sk_stati (coo, S_NLNGUNITS)
+ call sk_seti (coo, S_NLNGUNITS, lngunits)
+ if (latunits <= 0)
+ latunits = sk_stati (coo, S_NLATUNITS)
+ call sk_seti (coo, S_NLATUNITS, latunits)
+ call sk_seti (coo, S_PIXTYPE, pixsys)
+
+ # Set default reference coordinate.
+ Memc[xref] = EOS
+ Memc[yref] = EOS
+ Memc[lngref] = EOS
+ Memc[latref] = EOS
+
+ # Open the reference coordinate system if possible.
+ refstat = sk_decwcs (Memc[refsystem], mw, refcoo, NULL)
+ if (refstat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ refcoo = NULL
+ if (lngrefunits <= 0)
+ lngrefunits = sk_stati (coo, S_NLNGUNITS)
+ if (latrefunits <= 0)
+ latrefunits = sk_stati (coo, S_NLATUNITS)
+ } else {
+ if (lngrefunits <= 0)
+ lngrefunits = sk_stati (refcoo, S_NLNGUNITS)
+ call sk_seti (refcoo, S_NLNGUNITS, lngrefunits)
+ if (latrefunits <= 0)
+ latrefunits = sk_stati (refcoo, S_NLATUNITS)
+ call sk_seti (refcoo, S_NLATUNITS, latrefunits)
+ }
+
+ # Get the graphics parameters.
+ interactive = clgetb ("interactive")
+ call clgstr ("graphics", Memc[graphics], SZ_FNAME)
+
+ # Flush standard output on newline.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Initialize the coordinate mapping structure.
+ call geo_minit (fit, projection, geometry, function, xxorder, xyorder,
+ xxterms, yxorder, yyorder, yxterms, maxiter, reject)
+ call strcpy (Memc[projstr], GM_PROJSTR(fit), SZ_LINE)
+
+ # Process the input.
+ call calloc (in, ninfiles, TY_INT)
+ call calloc (im, ninfiles, TY_POINTER)
+ call calloc (tdxref, ninfiles, TY_DOUBLE)
+ call calloc (tdyref, ninfiles, TY_DOUBLE)
+ call calloc (tdlngref, ninfiles, TY_DOUBLE)
+ call calloc (tdlatref, ninfiles, TY_DOUBLE)
+ call amovkd (INDEFD, Memd[tdxref], ninfiles)
+ call amovkd (INDEFD, Memd[tdyref], ninfiles)
+ call amovkd (INDEFD, Memd[tdlngref], ninfiles)
+ call amovkd (INDEFD, Memd[tdlatref], ninfiles)
+
+ # Loop over the files. This is a little messy in order to allow
+ # both the case where all inputs are combined or separately done.
+ repeat {
+
+ nin = 0
+ while (clgfil (inlist, Memc[infile], SZ_FNAME) != EOF) {
+
+ # Open text file of coordinates.
+ Memi[in+nin] = open (Memc[infile], READ_ONLY, TEXT_FILE)
+
+ # Open the input image.
+ if (nimages > 0) {
+ if (imtgetim (imlist, Memc[image], SZ_FNAME) == EOF) {
+ Memi[im+nin] = NULL
+ } else if (update) {
+ Memi[im+nin] = immap (Memc[image], READ_WRITE, 0)
+ } else {
+ Memi[im+nin] = immap (Memc[image], READ_ONLY, 0)
+ }
+ if (Memi[im+nin] != NULL) {
+ if (IM_NDIM(Memi[im+nin]) != 2) {
+ call printf ("Skipping file: %s Image: %s is not 2D\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[image])
+ call imunmap (Memi[im+nin])
+ next
+ }
+ } else
+ Memc[image] = EOS
+ } else {
+ Memi[im+nin] = NULL
+ Memc[image] = EOS
+ }
+
+ if (nin == 0) {
+
+ # Open the results file.
+ if (nresfiles <= 0)
+ res = NULL
+ else if (clgfil (reslist, Memc[str], SZ_FNAME) != EOF)
+ res = open (Memc[str], NEW_FILE, TEXT_FILE)
+ else
+ res = NULL
+
+ # Set the output file record name.
+ if (nrecords > 0) {
+ if (imtgetim (reclist, GM_RECORD(fit), SZ_FNAME) != EOF)
+ ;
+ } else if (Memi[im] == NULL) {
+ call strcpy (Memc[infile], GM_RECORD(fit), SZ_FNAME)
+ } else {
+ #call imgimage (Memc[image], Memc[str], SZ_FNAME)
+ call strcpy (Memc[image], GM_RECORD(fit), SZ_FNAME)
+ }
+ }
+
+ # Determine the coordinates of the reference point if possible.
+ if (clgfil (xreflist, Memc[xref], SZ_FNAME) == EOF)
+ ;
+ if (clgfil (yreflist, Memc[yref], SZ_FNAME) == EOF)
+ ;
+ if (clgfil (lngreflist, Memc[lngref], SZ_FNAME) == EOF)
+ ;
+ if (clgfil (latreflist, Memc[latref], SZ_FNAME) == EOF)
+ ;
+ ip = 1
+ nchars = ctod (Memc[xref], ip, dxref)
+ if (nchars <= 0 || nchars != strlen (Memc[xref]))
+ dxref = INDEFD
+ ip = 1
+ nchars = ctod (Memc[yref], ip, dyref)
+ if (nchars <= 0 || nchars != strlen (Memc[yref]))
+ dyref = INDEFD
+ ip = 1
+ nchars = ctod (Memc[lngref], ip, dlngref)
+ if (nchars <= 0 || nchars != strlen (Memc[lngref]))
+ dlngref = INDEFD
+ if (dlngref < 0.0d0 || dlngref > 360.0d0)
+ dlngref = INDEFD
+ ip = 1
+ nchars = ctod (Memc[latref], ip, dlatref)
+ if (nchars <= 0 || nchars != strlen (Memc[latref]))
+ dlatref = INDEFD
+ if (dlatref < -90.0d0 || dlatref > 90.0d0)
+ dlatref = INDEFD
+
+ Memd[tdxref+nin] = dxref
+ Memd[tdyref+nin] = dyref
+ Memd[tdlngref+nin] = dlngref
+ Memd[tdlatref+nin] = dlatref
+
+ # Determine the tangent points and convert them to the
+ # celestial coordinate system of the input data,
+
+ # The tangent point will be determined directly from
+ # the input coordinates.
+ if (refpoint_type == CC_COORDS) {
+
+ if (nin == 0) {
+ if (verbose && res != STDOUT)
+ call sk_iiprint ("Refsystem", Memc[insystem],
+ NULL, coo)
+ if (res != NULL)
+ call sk_iiwrite (res, "Refsystem", Memc[insystem],
+ NULL, coo)
+ }
+ Memd[tdxref+nin] = INDEFD
+ Memd[tdyref+nin] = INDEFD
+ Memd[tdlngref+nin] = INDEFD
+ Memd[tdlatref+nin] = INDEFD
+
+ # The tangent point was set by the user and a tangent point
+ # reference system may or may not have been defined.
+ } else if (! IS_INDEFD(dlngref) && ! IS_INDEFD (dlatref)) {
+
+ tcoo = cc_utan (refcoo, coo, dxref, dyref, dlngref, dlatref,
+ Memd[tdlngref+nin], Memd[tdlatref+nin],
+ lngrefunits, latrefunits)
+ call sk_stats (tcoo, S_COOSYSTEM, Memc[str], SZ_FNAME)
+ if (nin == 0) {
+ if (verbose && res != STDOUT)
+ call sk_iiprint ("Refsystem", Memc[str], NULL, tcoo)
+ if (res != NULL)
+ call sk_iiwrite (res, "Refsystem", Memc[str],
+ NULL, tcoo)
+ call sk_close (tcoo)
+ }
+
+ } else if (Memi[im+nin] != NULL) {
+
+ tcoo = cc_imtan (Memi[im+nin], Memc[xref], Memc[yref],
+ Memc[lngref], Memc[latref], Memc[refsystem],
+ refcoo, coo, Memd[tdxref+nin], Memd[tdyref+nin],
+ Memd[tdlngref+nin], Memd[tdlatref+nin],
+ lngrefunits, latrefunits)
+ call sk_stats (tcoo, S_COOSYSTEM, Memc[str], SZ_FNAME)
+ if (nin == 0) {
+ if (verbose && res != STDOUT)
+ call sk_iiprint ("Refsystem", Memc[str], NULL, tcoo)
+ if (res != NULL)
+ call sk_iiwrite (res, "Refsystem", Memc[str],
+ NULL, tcoo)
+ call sk_close (tcoo)
+ }
+
+ # The tangent point will be determined directly from
+ # the input coordinates.
+ } else {
+
+ if (nin == 0) {
+ if (verbose && res != STDOUT)
+ call sk_iiprint ("Refsystem", Memc[insystem],
+ NULL, coo)
+ if (res != NULL)
+ call sk_iiwrite (res, "Refsystem", Memc[insystem],
+ NULL, coo)
+ }
+ Memd[tdxref+nin] = INDEFD
+ Memd[tdyref+nin] = INDEFD
+ Memd[tdlngref+nin] = INDEFD
+ Memd[tdlatref+nin] = INDEFD
+
+ }
+
+ if (nin == 0) {
+ # Print information about the input coordinate system.
+ if (verbose && res != STDOUT)
+ call sk_iiprint ("Insystem", Memc[insystem], NULL, coo)
+ if (res != NULL)
+ call sk_iiwrite (res, "Insystem", Memc[insystem],
+ NULL, coo)
+ }
+
+ # Print the input and out file information.
+ if (verbose && res != STDOUT) {
+ call printf ("\nCoords File: %s Image: %s\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[image])
+ call printf (" Database: %s Solution: %s\n")
+ call pargstr (Memc[database])
+ call pargstr (GM_RECORD(fit))
+ }
+ if (res != NULL) {
+ call fprintf (res, "\n# Coords File: %s Image: %s\n")
+ call pargstr (Memc[infile])
+ call pargstr (Memc[image])
+ call fprintf (res, "# Database: %s Solution: %s\n")
+ call pargstr (Memc[database])
+ call pargstr (GM_RECORD(fit))
+ }
+
+ nin = nin + 1
+ if (nrecords > 1 || nresfiles > 1)
+ break
+ }
+ if (nin == 0)
+ break
+
+ iferr {
+ if (interactive)
+ gd = gopen (Memc[graphics], NEW_FILE, STDGRAPH)
+ else
+ gd = NULL
+ call cc_map (gd, nin, Memi[in], out, Memi[im], res, coo, fit,
+ xcolumn, ycolumn, lngcolumn, latcolumn, tweak,
+ Memd[tdxref], Memd[tdyref], Memd[tdlngref], Memd[tdlatref],
+ xmin, xmax, ymin, ymax, update, verbose)
+ if (gd != NULL)
+ call gclose (gd)
+ } then {
+ if (verbose && res != STDOUT) {
+ if (nin == 1) {
+ call printf ("Error fitting coordinate list: %s\n")
+ call pargstr (Memc[infile])
+ } else
+ call printf ("Error fitting coordinate lists\n")
+ call flush (STDOUT)
+ Memc[str] = EOS
+ if (errget (Memc[str], SZ_LINE) == 0)
+ ;
+ call printf (" %s\n")
+ call pargstr (Memc[str])
+ }
+ if (res != NULL) {
+ if (nin == 1) {
+ call fprintf (res,
+ "# Error fitting coordinate list: %s\n")
+ call pargstr (Memc[infile])
+ } else
+ call fprintf (res,
+ "# Error fitting coordinate lists\n")
+ call flush (STDOUT)
+ if (errget (Memc[str], SZ_LINE) == 0)
+ ;
+ call fprintf (res, "# %s\n")
+ call pargstr (Memc[str])
+ }
+ if (gd != NULL)
+ call gclose (gd)
+ }
+
+
+ if (nresfiles == ninfiles)
+ call close (res)
+ do i = 1, nin {
+ call close (Memi[in+i-1])
+ if (Memi[im+i-1] != NULL)
+ call imunmap (Memi[im+i-1])
+ }
+ }
+
+ call mfree (in, TY_INT)
+ call mfree (im, TY_POINTER)
+ call mfree (tdxref, TY_DOUBLE)
+ call mfree (tdyref, TY_DOUBLE)
+ call mfree (tdlngref, TY_DOUBLE)
+ call mfree (tdlatref, TY_DOUBLE)
+
+ call geo_free (fit)
+ call sk_close (coo)
+ call clpcls (xreflist)
+ call clpcls (yreflist)
+ call clpcls (latreflist)
+ call clpcls (lngreflist)
+ if (nresfiles < ninfiles)
+ call close (res)
+ call dtunmap (out)
+ if (reclist != NULL)
+ call imtclose (reclist)
+ call imtclose (imlist)
+ call clpcls (inlist)
+ call clpcls (reslist)
+ call sfree (sp)
+end
+
+
+# CC_UTAN -- Convert the user defined tangent point from the reference
+# point celestial coordinate system to the input coordinate celestial
+# coordinate system.
+
+pointer procedure cc_utan (refcoo, coo, idxref, idyref, idlngref, idlatref, odlngref, odlatref,
+ lngrefunits, latrefunits)
+
+pointer refcoo #I pointer to the reference point system
+pointer coo #I pointer to the input coordinate system
+double idxref #I the input x reference point
+double idyref #I the input y reference point
+double idlngref #I the input reference point ra / longitude
+double idlatref #I the input reference point dec / latitude
+double odxref #O the output x reference point
+double odyref #O the output y reference point
+double odlngref #O the output reference point ra / longitude
+double odlatref #O the output reference point dec / latitude
+int lngrefunits #I the input reference ra / longitude units
+int latrefunits #I the input reference dec / latitude units
+
+pointer trefcoo
+pointer sk_copy()
+
+begin
+ odxref = idxref
+ odyref = idyref
+ if (refcoo != NULL) {
+ trefcoo = sk_copy (refcoo)
+ } else {
+ trefcoo = sk_copy (coo)
+ call sk_seti (trefcoo, S_NLNGUNITS, lngrefunits)
+ call sk_seti (trefcoo, S_NLATUNITS, latrefunits)
+ }
+ call sk_ultran (trefcoo, coo, idlngref, idlatref, odlngref, odlatref, 1)
+
+ return (trefcoo)
+end
+
+
+# CC_IMTAN -- Read the tangent point from the image and convert it from the
+# reference point celestial coordinate system to the input coordinate celestial
+# coordinate system.
+
+pointer procedure cc_imtan (im, xref, yref, lngref, latref, refsystem, refcoo,
+ coo, odxref, odyref, odlngref, odlatref, lngrefunits, latrefunits)
+
+pointer im #I pointer to the input image
+char xref[ARB] #I the x reference keyword
+char yref[ARB] #I the y reference keyword
+char lngref[ARB] #I the ra / longitude keyword
+char latref[ARB] #I the dec / latitude keyword
+char refsystem[ARB] #I the reference point coordinate system
+pointer refcoo #I pointer to the reference point system
+pointer coo #I pointer to the input coordinate system
+double odxref #O the output x reference point
+double odyref #O the output y reference point
+double odlngref #O the output reference point ra / longitude
+double odlatref #O the output reference point dec / latitude
+int lngrefunits #I the input reference ra / longitude units
+int latrefunits #I the input reference dec / latitude units
+
+double idxref, idyref, idlngref, idlatref, idepoch
+pointer sp, str, tcoo, mw
+double imgetd()
+pointer sk_copy()
+int sk_decwcs()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ iferr (idxref = imgetd (im, xref))
+ idxref = INDEFD
+ iferr (idyref = imgetd (im, yref))
+ idyref = INDEFD
+ iferr (idlngref = imgetd (im, lngref))
+ idlngref = INDEFD
+ if (idlngref < 0.0d0 || idlngref > 360.0d0)
+ idlngref = INDEFD
+ iferr (idlatref = imgetd (im, latref))
+ idlatref = INDEFD
+ if (idlatref < -90.0d0 || idlatref > 90.0d0)
+ idlatref = INDEFD
+
+ if (!IS_INDEFD(idxref))
+ odxref = idxref
+ if (!IS_INDEFD(idyref))
+ odyref = idyref
+
+ if (IS_INDEFD(idlngref) || IS_INDEFD(idlatref))
+ tcoo = sk_copy (coo)
+ else if (refcoo != NULL) {
+ tcoo = sk_copy (refcoo)
+ call sk_ultran (tcoo, coo, idlngref, idlatref, odlngref,
+ odlatref, 1)
+ } else {
+ iferr (idepoch = imgetd (im, refsystem))
+ idepoch = INDEFD
+ if (IS_INDEFD(idepoch))
+ tcoo = sk_copy (coo)
+ else {
+ call sprintf (Memc[str], SZ_FNAME, "fk4 b%g")
+ call pargd (idepoch)
+ if (sk_decwcs (Memc[str], mw, tcoo, NULL) == ERR) {
+ call sk_close (tcoo)
+ tcoo = sk_copy (coo)
+ }
+ if (mw != NULL)
+ call mw_close (mw)
+ }
+ call sk_seti (tcoo, S_NLNGUNITS, lngrefunits)
+ call sk_seti (tcoo, S_NLATUNITS, latrefunits)
+ call sk_ultran (tcoo, coo, idlngref, idlatref, odlngref,
+ odlatref, 1)
+ }
+
+ call sfree (sp)
+
+ return (tcoo)
+end
+
+
+# CC_MAP -- Compute the required coordinate transformation.
+#
+# This version uses the nin variable.
+
+procedure cc_map (gd, nin, in, out, im, res, coo, fit,
+ xcolumn, ycolumn, lngcolumn, latcolumn, tweak,
+ xtan, ytan, ratan, dectan,
+ xmin, xmax, ymin, ymax, update, verbose)
+
+pointer gd #I graphics stream pointer
+int nin #I number of input files
+int in[ARB] #I the input file descriptors
+pointer out #I the output file descriptor
+pointer im[ARB] #I the input image pointers
+int res #I the results file descriptor
+pointer coo # pointer to the input coordinate system
+pointer fit #I pointer to fit parameters
+int xcolumn, ycolumn #I the x and y column numbers
+int lngcolumn, latcolumn #I the longitude and latitude column numbers
+int tweak #I tweak flag
+double xtan[ARB], ytan[ARB] #I the input x and y of the tangent point
+double ratan[ARB], dectan[ARB] #I the input ra and dec of the tangent point
+double xmin, xmax #I max and min xref values
+double ymin, ymax #I max and min yref values
+bool update #I update the image wcs
+bool verbose #I verbose mode
+
+double mintemp, maxtemp, lngrms, latrms, lngmean, latmean
+pointer sp, str, projstr
+pointer n, xref, yref, xifit, etafit, lngfit, latfit, wts
+pointer lngref, latref, xi, eta, lngref1, latref1, xi1, eta1
+pointer sx1, sy1, sx2, sy2, xerrmsg, yerrmsg
+int i, npts, npts1
+double asumd()
+int cc_rdxyrd(), sk_stati(), rg_wrdstr()
+bool streq()
+
+errchk geo_fitd, geo_mgfitd()
+
+begin
+ # Get working space.
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (projstr, SZ_LINE, TY_CHAR)
+ call salloc (xerrmsg, SZ_LINE, TY_CHAR)
+ call salloc (yerrmsg, SZ_LINE, TY_CHAR)
+
+ # Initialize the pointers.
+ xref = NULL
+ yref = NULL
+ lngref = NULL
+ latref = NULL
+ xi = NULL
+ eta = NULL
+ xifit = NULL
+ etafit = NULL
+ lngfit = NULL
+ latfit = NULL
+ wts = NULL
+
+ # Read in data and check that it is in range.
+ if (gd != NULL)
+ call gdeactivate (gd, 0)
+ npts = cc_rdxyrd (in, im, xtan, ytan, ratan, dectan, nin,
+ coo, xcolumn, ycolumn, lngcolumn, latcolumn, tweak,
+ n, xref, yref, lngref, latref, xmin, xmax, ymin, ymax)
+ if (gd != NULL)
+ call greactivate (gd, 0)
+ if (npts == 0)
+ return
+
+ # Compute the mean of the reference and input coordinates.
+ GM_XOREF(fit) = asumd (Memd[xref], npts) / npts
+ GM_YOREF(fit) = asumd (Memd[yref], npts) / npts
+ GM_XOIN(fit) = asumd (Memd[lngref], npts) / npts
+ GM_YOIN(fit) = asumd (Memd[latref], npts) / npts
+
+ # Set the sky projection str.
+ if (rg_wrdstr (GM_PROJECTION(fit), Memc[projstr], SZ_LINE,
+ GM_PROJLIST) <= 0 || GM_PROJECTION(fit) == GM_LIN)
+ Memc[projstr] = EOS
+ else
+ call strcpy (GM_PROJSTR(fit), Memc[projstr], SZ_LINE)
+
+ # Compute the position of the reference point for the solution.
+ if (IS_INDEFD(ratan[1]) || IS_INDEFD(dectan[1])) {
+ call cc_refpt (coo, Memd[lngref], Memd[latref], npts,
+ lngmean, latmean)
+ if (IS_INDEFD(ratan[1]))
+ GM_XREFPT(fit) = lngmean
+ else
+ GM_XREFPT(fit) = ratan[1]
+ if (IS_INDEFD(dectan[1]))
+ GM_YREFPT(fit) = latmean
+ else
+ GM_YREFPT(fit) = dectan[1]
+ } else {
+ GM_XREFPT(fit) = ratan[1]
+ GM_YREFPT(fit) = dectan[1]
+ }
+
+ # Allocate space for and compute the weights.
+ call malloc (wts, npts, TY_DOUBLE)
+ call amovkd (double(1.), Memd[wts], npts)
+
+ # Determine the x max and min.
+ if (IS_INDEFD(xmin) || IS_INDEFD(xmax)) {
+ call alimd (Memd[xref], npts, mintemp, maxtemp)
+ if (! IS_INDEFD(xmin))
+ GM_XMIN(fit) = xmin
+ else
+ GM_XMIN(fit) = mintemp
+ if (! IS_INDEFD(xmax))
+ GM_XMAX(fit) = xmax
+ else
+ GM_XMAX(fit) = maxtemp
+ } else {
+ GM_XMIN(fit) = xmin
+ GM_XMAX(fit) = xmax
+ }
+
+ # Determine the y max and min.
+ if (IS_INDEFD(ymin) || IS_INDEFD(ymax)) {
+ call alimd (Memd[yref], npts, mintemp, maxtemp)
+ if (! IS_INDEFD(ymin))
+ GM_YMIN(fit) = ymin
+ else
+ GM_YMIN(fit) = mintemp
+ if (! IS_INDEFD(ymax))
+ GM_YMAX(fit) = ymax
+ else
+ GM_YMAX(fit) = maxtemp
+ } else {
+ GM_YMIN(fit) = ymin
+ GM_YMAX(fit) = ymax
+ }
+
+ # Convert the ra / longitude and dec / latitude values to standard
+ # coordinates in arc seconds before fitting.
+ call malloc (xi, npts, TY_DOUBLE)
+ call malloc (eta, npts, TY_DOUBLE)
+ lngref1 = lngref; latref1 = latref; xi1 = xi; eta1 = eta
+ do i = 1, nin {
+ npts1 = Memi[n+i-1]
+ if (npts1 == 0)
+ next
+ if (IS_INDEFD(ratan[i]) || IS_INDEFD(dectan[i]))
+ call rg_celtostd (Memc[projstr], Memd[lngref1], Memd[latref1],
+ Memd[xi1], Memd[eta1], npts1, lngmean, latmean,
+ sk_stati(coo, S_NLNGUNITS), sk_stati(coo, S_NLATUNITS))
+ else
+ call rg_celtostd (Memc[projstr], Memd[lngref1], Memd[latref1],
+ Memd[xi1], Memd[eta1], npts1, ratan[i], dectan[i],
+ sk_stati(coo, S_NLNGUNITS), sk_stati(coo, S_NLATUNITS))
+ lngref1 = lngref1 + npts1
+ latref1 = latref1 + npts1
+ xi1 = xi1 + npts1
+ eta1 = eta1 + npts1
+ }
+ call amulkd (Memd[xi], 3600.0d0, Memd[xi], npts)
+ call amulkd (Memd[eta], 3600.0d0, Memd[eta], npts)
+
+ # Initalize surface pointers.
+ sx1 = NULL
+ sy1 = NULL
+ sx2 = NULL
+ sy2 = NULL
+
+ # Fit the data.
+ if (! (IS_INDEFD(xtan[1]) || IS_INDEFD(ytan[1]))) {
+ call geo_setd (fit, GMXO, xtan[1])
+ call geo_setd (fit, GMYO, ytan[1])
+ call geo_setd (fit, GMXOREF, 0D0)
+ call geo_setd (fit, GMYOREF, 0D0)
+ }
+ if (gd != NULL) {
+ iferr {
+ call geo_mgfitd (gd, fit, sx1, sy1, sx2, sy2, Memd[xref],
+ Memd[yref], Memd[xi], Memd[eta], Memd[wts], npts,
+ Memc[xerrmsg], Memc[yerrmsg], SZ_LINE)
+ } then {
+ call gdeactivate (gd, 0)
+ call mfree (xi, TY_DOUBLE)
+ call mfree (eta, TY_DOUBLE)
+ call mfree (wts, TY_DOUBLE)
+ call geo_mmfreed (sx1, sy1, sx2, sy2)
+ call sfree (sp)
+ call error (3, "Too few data points in XI or ETA fits.")
+ }
+ call gdeactivate (gd, 0)
+ if (verbose && res != STDOUT) {
+ call printf ("Coordinate mapping status\n")
+ call flush (STDOUT)
+ }
+ if (res != NULL)
+ call fprintf (res, "# Coordinate mapping status\n")
+ } else {
+ if (verbose && res != STDOUT) {
+ call printf ("Coordinate mapping status\n ")
+ call flush (STDOUT)
+ }
+ if (res != NULL) {
+ call fprintf (res, "# Coordinate mapping status\n# ")
+ }
+ iferr {
+ call geo_fitd (fit, sx1, sy1, sx2, sy2, Memd[xref], Memd[yref],
+ Memd[xi], Memd[eta], Memd[wts], npts, Memc[xerrmsg],
+ Memc[yerrmsg], SZ_LINE)
+ } then {
+ #call printf ("%s %s\n")
+ #call pargstr (Memc[xerrmsg])
+ #call pargstr (Memc[yerrmsg])
+ #call flush (STDOUT)
+ call mfree (xi, TY_DOUBLE)
+ call mfree (eta, TY_DOUBLE)
+ call mfree (wts, TY_DOUBLE)
+ call geo_mmfreed (sx1, sy1, sx2, sy2)
+ call sfree (sp)
+ call error (3, "Too few data points in XI or ETA fits.")
+ }
+ if (verbose && res != STDOUT) {
+ call printf ("%s %s\n")
+ call pargstr (Memc[xerrmsg])
+ call pargstr (Memc[yerrmsg])
+ call flush (STDOUT)
+ }
+ if (res != NULL) {
+ call fprintf (res, "%s %s\n")
+ call pargstr (Memc[xerrmsg])
+ call pargstr (Memc[yerrmsg])
+ }
+ }
+
+ # Allocate fitting arrays.
+ call malloc (xifit, npts, TY_DOUBLE)
+ call malloc (etafit, npts, TY_DOUBLE)
+ call malloc (lngfit, npts, TY_DOUBLE)
+ call malloc (latfit, npts, TY_DOUBLE)
+
+ # Compute the fitted ra / dec or longitude latitude,
+ if (res != NULL || verbose) {
+ call cc_eval (sx1, sy1, sx2, sy2, Memd[xref], Memd[yref],
+ Memd[xifit], Memd[etafit], npts)
+ call cc_rms (fit, Memd[xi], Memd[eta], Memd[xifit], Memd[etafit],
+ Memd[wts], npts, lngrms, latrms)
+ call adivkd (Memd[xifit], 3600.0d0, Memd[xifit], npts)
+ call adivkd (Memd[etafit], 3600.0d0, Memd[etafit], npts)
+ call rg_stdtocel (Memc[projstr], Memd[xifit], Memd[etafit],
+ Memd[lngfit], Memd[latfit], npts, GM_XREFPT(fit),
+ GM_YREFPT(fit), sk_stati(coo, S_NLNGUNITS), sk_stati(coo,
+ S_NLATUNITS))
+ }
+
+ # Print some detailed info about the fit.
+ if (verbose && res != STDOUT) {
+ call printf (
+ " Ra/Dec or Long/Lat fit rms: %0.3g %0.3g (arcsec arcsec)\n")
+ call pargd (lngrms)
+ call pargd (latrms)
+ call cc_show (STDOUT, coo, Memc[projstr], GM_XREFPT(fit),
+ GM_YREFPT(fit), sx1, sy1, NO)
+ }
+ if (res != NULL) {
+ call fprintf (res,
+ "# Ra/Dec or Long/Lat fit rms: %0.3g %0.3g (arcsec arcsec)\n")
+ call pargd (lngrms)
+ call pargd (latrms)
+ call cc_show (res, coo, Memc[projstr], GM_XREFPT(fit),
+ GM_YREFPT(fit), sx1, sy1, YES)
+ }
+
+ # Compute the wcs mapping rms.
+ if (! streq (GM_PROJSTR(fit), "tnx") && ! streq (GM_PROJSTR(fit),
+ "zpx")) {
+ call cc_eval (sx1, sy1, NULL, NULL, Memd[xref], Memd[yref],
+ Memd[xifit], Memd[etafit], npts)
+ call cc_rms (fit, Memd[xi], Memd[eta], Memd[xifit],
+ Memd[etafit], Memd[wts], npts, lngrms, latrms)
+ }
+
+ # Update the image wcs.
+ do i = 1, nin {
+ if (im[i] != NULL) {
+ if (i == 1) {
+ if (verbose && res != STDOUT) {
+ call printf ("Wcs mapping status\n")
+ call printf (
+ " Ra/Dec or Long/Lat wcs rms: %0.3g %0.3g (arcsec arcsec)\n")
+ call pargd (lngrms)
+ call pargd (latrms)
+ }
+ if (res != NULL) {
+ call fprintf (res, "# Wcs mapping status\n")
+ call fprintf (res,
+ "# Ra/Dec or Long/Lat wcs rms: %0.3g %0.3g (arcsec arcsec)\n")
+ call pargd (lngrms)
+ call pargd (latrms)
+ }
+ }
+ if (update) {
+ if (IS_INDEFD(ratan[i]) || IS_INDEFD(dectan[i]))
+ call cc_nwcsim (im[i], coo, Memc[projstr], lngmean,
+ latmean, sx1, sy1, sx2, sy2, false)
+ else
+ call cc_nwcsim (im[i], coo, Memc[projstr], ratan[i],
+ dectan[i], sx1, sy1, sx2, sy2, false)
+ if (i == 1) {
+ if (verbose && res != STDOUT)
+ call printf ("Updating image header wcs\n\n")
+ if (res != NULL)
+ call fprintf (res,
+ "# Updating image header wcs\n\n")
+ }
+ }
+ }
+ }
+
+ # Write the database file.
+ call cc_out (fit, coo, out, sx1, sy1, sx2, sy2, lngrms, latrms)
+
+ # List results for individual objects.
+ if (res != NULL)
+ call cc_plist (res, fit, coo, Memd[xref], Memd[yref], Memd[lngref],
+ Memd[latref], Memd[lngfit], Memd[latfit], Memd[wts],
+ npts)
+
+ # Free the space and close files.
+ call geo_mmfreed (sx1, sy1, sx2, sy2)
+
+ if (n != NULL)
+ call mfree (n, TY_INT)
+ if (xref != NULL)
+ call mfree (xref, TY_DOUBLE)
+ if (yref != NULL)
+ call mfree (yref, TY_DOUBLE)
+ if (lngref != NULL)
+ call mfree (lngref, TY_DOUBLE)
+ if (latref != NULL)
+ call mfree (latref, TY_DOUBLE)
+ if (xi != NULL)
+ call mfree (xi, TY_DOUBLE)
+ if (eta != NULL)
+ call mfree (eta, TY_DOUBLE)
+ if (xifit != NULL)
+ call mfree (xifit, TY_DOUBLE)
+ if (etafit != NULL)
+ call mfree (etafit, TY_DOUBLE)
+ if (wts != NULL)
+ call mfree (wts, TY_DOUBLE)
+ if (lngfit != NULL)
+ call mfree (lngfit, TY_DOUBLE)
+ if (latfit != NULL)
+ call mfree (latfit, TY_DOUBLE)
+
+ call sfree (sp)
+end
+
+
+# CC_RDXYRD -- Read in the x, y, ra, and dec values from the input file(s).
+#
+# Adjust the tangent points if there is an image WCS.
+
+int procedure cc_rdxyrd (in, im, xtan, ytan, ratan, dectan, nin,
+ coo, xcolumn, ycolumn, lngcolumn, latcolumn, tweak,
+ n, xref, yref, lngref, latref, xmin, xmax, ymin, ymax)
+
+int in[nin] #I the input file file descriptors
+pointer im[nin] #I the input image pointers
+double xtan[ARB], ytan[ARB] #I the input x and y of the tangent point
+double ratan[ARB], dectan[ARB] #I the input ra and dec of the tangent point
+int nin #I number of input files
+pointer coo #I the input coordinate system
+int xcolumn, ycolumn #I the columns containing the x / y values
+int lngcolumn, latcolumn #I the columns containing the lng / lat values
+int tweak #I tweak flag
+pointer n #U pointer to the number of points
+pointer xref, yref #I pointers to the x / y value arrays
+pointer lngref, latref #I pointers to the lng / lat value arrays
+double xmin, xmax #U the min and max x values
+double ymin, ymax #U the min and max y values
+
+int i, npts, npts1
+pointer xref1, yref1, lngref1, latref1
+
+int cc_rdxyrd1()
+
+begin
+ call calloc (n, nin, TY_INT)
+
+ npts = 0
+ do i = 1, nin {
+ npts1 = cc_rdxyrd1 (in[i], im[i], xtan[i], ytan[i], ratan[i],
+ dectan[i], coo, xcolumn, ycolumn, lngcolumn, latcolumn, tweak,
+ xref1, yref1, lngref1, latref1, xmin, xmax, ymin, ymax)
+ Memi[n+i-1] = npts1
+ if (npts1 == 0)
+ next
+ if (npts == 0) {
+ xref = xref1
+ yref = yref1
+ lngref = lngref1
+ latref = latref1
+ } else {
+ call realloc (xref, npts+npts1, TY_DOUBLE)
+ call realloc (yref, npts+npts1, TY_DOUBLE)
+ call realloc (lngref, npts+npts1, TY_DOUBLE)
+ call realloc (latref, npts+npts1, TY_DOUBLE)
+ call amovd (Memd[xref1], Memd[xref+npts], npts1)
+ call amovd (Memd[yref1], Memd[yref+npts], npts1)
+ call amovd (Memd[lngref1], Memd[lngref+npts], npts1)
+ call amovd (Memd[latref1], Memd[latref+npts], npts1)
+ call mfree (xref1, TY_DOUBLE)
+ call mfree (yref1, TY_DOUBLE)
+ call mfree (lngref1, TY_DOUBLE)
+ call mfree (latref1, TY_DOUBLE)
+ }
+ npts = npts + npts1
+ }
+
+ if (npts == 0) {
+ call mfree (n, TY_INT)
+
+ if (i > 1)
+ call printf ("Coordinate lists have no data in range.\n")
+ }
+
+ return (npts)
+end
+
+
+# CC_RDXYRD1 -- Read in the x, y, ra, and dec values from the input file.
+#
+# If a reference point (both pixel and value) and an image (with a
+# valid celestial WCS) are defined then the WCS is reset to the reference
+# point and the reference point value is then shifted to make the
+# the WCS coordinates evaluated at the input pixel coordinates agree
+# if the input celestial coordinates on average.
+
+int procedure cc_rdxyrd1 (in, im, xtan, ytan, ratan, dectan, icoo,
+ xcolumn, ycolumn, lngcolumn, latcolumn, tweak,
+ xref, yref, lngref, latref, xmin, xmax, ymin, ymax)
+
+int in #I the input file file descriptor
+pointer im #I the input image pointer
+double xtan, ytan #I the input x and y of the tangent point
+double ratan, dectan #I the input ra and dec of the tangent point
+pointer icoo #I the input coordinate system
+int xcolumn, ycolumn #I the columns containing the x / y values
+int lngcolumn, latcolumn #I the columns containing the lng / lat values
+int tweak #I tweak flag
+pointer xref, yref #I pointers to the input x / y values
+pointer lngref, latref #I pointers to the input lng / lat values
+double xmin, xmax #U the min and max x values
+double ymin, ymax #U the min and max y values
+
+int nline, i, npts, bufsize, nfields, max_fields, nsig, offset
+double lng1, lat1, lng2, lat2, x, y, z, sumx, sumy, sumz, r, pa, wterm[8]
+pointer sp, inbuf, linebuf, field_pos
+pointer mw, ct, coo
+int getline(), li_get_numd(), sk_decim()
+pointer mw_ctrand(), mw_sctran()
+
+int sk_stati()
+
+begin
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (linebuf, SZ_LINE, TY_CHAR)
+ call salloc (field_pos, MAX_FIELDS, TY_INT)
+
+ bufsize = CC_DEFBUFSIZE
+ call malloc (xref, bufsize, TY_DOUBLE)
+ call malloc (yref, bufsize, TY_DOUBLE)
+ call malloc (lngref, bufsize, TY_DOUBLE)
+ call malloc (latref, bufsize, TY_DOUBLE)
+
+ # Check whether to adjust the reference value based on the
+ # current image WCS.
+ mw = NULL; ct = NULL; coo = NULL
+ if (tweak == 3 && im != NULL && !IS_INDEFD(xtan) && !IS_INDEFD(ytan) &&
+ !IS_INDEFD(ratan) && !IS_INDEFD(dectan)) {
+ if (sk_decim (im, "logical", mw, coo) != ERR && mw != NULL) {
+ call sk_seti (coo, S_NLNGUNITS, SKY_DEGREES)
+ call sk_ultran (icoo, coo, ratan, dectan, lng1, lat1, 1)
+ call mw_gwtermd (mw, wterm[1], wterm[3], wterm[5], 2)
+ wterm[1] = xtan; wterm[2] = ytan
+ wterm[3] = lng1; wterm[4] = lat1
+ call mw_swtermd (mw, wterm[1], wterm[3], wterm[5], 2)
+ ct = mw_sctran (mw, "logical", "world", 03B)
+ sumx = 0d0; sumy = 0d0; sumz = 0d0
+ } else {
+ if (mw != NULL)
+ call mw_close (mw)
+ call sk_close (coo)
+ mw = NULL; coo = NULL
+ }
+ }
+
+ npts = 0
+ max_fields = MAX_FIELDS
+ for (nline = 1; getline (in, Memc[inbuf]) != EOF; nline = nline + 1) {
+
+ # Skip over leading white space.
+ for (i = inbuf; IS_WHITE(Memc[i]); i = i + 1)
+ ;
+
+ # Skip comment and blank lines.
+ if (Memc[i] == '#')
+ next
+ else if (Memc[i] == '\n' || Memc[i] == EOS)
+ next
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[linebuf], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[linebuf], Memi[field_pos], max_fields,
+ nfields)
+
+ # Decode the x coordinate.
+ if (xcolumn > nfields)
+ next
+ offset = Memi[field_pos+xcolumn-1]
+ if (li_get_numd (Memc[linebuf+offset-1], Memd[xref+npts],
+ nsig) == 0)
+ next
+
+ # Decode the y coordinate.
+ if (ycolumn > nfields)
+ next
+ offset = Memi[field_pos+ycolumn-1]
+ if (li_get_numd (Memc[linebuf+offset-1], Memd[yref+npts],
+ nsig) == 0)
+ next
+
+ # Decode the ra / longitude coordinate.
+ if (lngcolumn > nfields)
+ next
+ offset = Memi[field_pos+lngcolumn-1]
+ if (li_get_numd (Memc[linebuf+offset-1], Memd[lngref+npts],
+ nsig) == 0)
+ next
+
+ # Decode the dec / latitude coordinate.
+ if (latcolumn > nfields)
+ next
+ offset = Memi[field_pos+latcolumn-1]
+ if (li_get_numd (Memc[linebuf+offset-1], Memd[latref+npts],
+ nsig) == 0)
+ next
+
+ # Accumulate cartisian shifts from image WCS coordinates.
+ if (ct != NULL) {
+ call mw_c2trand (ct, Memd[xref+npts], Memd[yref+npts],
+ lng1, lat1)
+ call sk_ultran (icoo, coo, Memd[lngref+npts], Memd[latref+npts],
+ lng2, lat2, 1)
+ lng1 = DDEGTORAD(lng1); lat1 = DDEGTORAD(lat1)
+ lng2 = DDEGTORAD(lng2); lat2 = DDEGTORAD(lat2)
+ x = sin (lat2) - sin(lat1)
+ y = cos (lat2) * sin (lng2) - cos (lat1) * sin (lng1)
+ z = cos (lat2) * cos (lng2) - cos (lat1) * cos (lng1)
+ sumx = sumx + x; sumy = sumy + y; sumz = sumz + z
+ }
+
+ npts = npts + 1
+
+ if (npts >= bufsize) {
+ bufsize = bufsize + CC_DEFBUFSIZE
+ call realloc (xref, bufsize, TY_DOUBLE)
+ call realloc (yref, bufsize, TY_DOUBLE)
+ call realloc (lngref, bufsize, TY_DOUBLE)
+ call realloc (latref, bufsize, TY_DOUBLE)
+ }
+ }
+
+ # Adjust the tangent point value.
+ if (npts > 0 && ct != NULL) {
+ sumx = sumx / npts; sumy = sumy / npts; sumz = sumz / npts
+ r = sqrt (sumx**2 + sumy**2 + sumz**2) / 2
+ r = 2 * atan2 (r, sqrt(max(0d0,1d0-r)))
+ r = 3600 * DRADTODEG (r)
+ call eprintf ("Tangent point shift = %.2f\n")
+ call pargd (r)
+
+ call sk_ultran (icoo, coo, ratan, dectan, lng1, lat1, 1)
+ lng2 = DDEGTORAD(lng1); lat2 = DDEGTORAD(lat1)
+ x = sin (lat2) + sumx
+ y = cos (lat2) * sin (lng2) + sumy
+ z = cos (lat2) * cos (lng2) + sumz
+ pa = atan2 (y, x)
+ if (pa < 0d0)
+ pa = pa + DTWOPI
+ if (pa >= DTWOPI)
+ pa = pa - DTWOPI
+ r = z
+ if (abs(r) > 0.99d0) {
+ if (r < 0d0)
+ r = DPI - asin (sqrt (x * x + y * y))
+ else
+ r = asin (sqrt (x * x + y * y))
+ } else
+ r = acos (r)
+ x = sin (r) * cos (pa)
+ y = sin (r) * sin (pa)
+ z = cos (r)
+ lng2 = atan2 (y, z)
+ if (lng2 < 0d0)
+ lng2 = lng2 + DTWOPI
+ if (lng2 >= DTWOPI)
+ lng2 = lng2 - DTWOPI
+ lat2 = x
+ if (abs (lat2) > 0.99d0) {
+ if (lat2 < 0d0)
+ lat2 = -acos (sqrt (y * y + z * z))
+ else
+ lat2 = acos (sqrt (y * y + z * z))
+ } else
+ lat2 = asin (lat2)
+ lng2 = DRADTODEG (lng2); lat2 = DRADTODEG (lat2)
+ call sk_ultran (coo, icoo, lng2, lat2, ratan, dectan, 1)
+ }
+
+ # Finish up.
+
+ if (npts <= 0) {
+ call mfree (xref, TY_DOUBLE)
+ call mfree (yref, TY_DOUBLE)
+ call mfree (lngref, TY_DOUBLE)
+ call mfree (latref, TY_DOUBLE)
+
+ call fstats (in, F_FILENAME, Memc[linebuf], SZ_LINE)
+ call printf ("Coordinate list: %s has no data in range.\n")
+ call pargstr (Memc[linebuf])
+ } else if (npts < bufsize) {
+ call realloc (xref, npts, TY_DOUBLE)
+ call realloc (yref, npts, TY_DOUBLE)
+ call realloc (lngref, npts, TY_DOUBLE)
+ call realloc (latref, npts, TY_DOUBLE)
+ }
+
+ if (ct != NULL)
+ call mw_ctfree (ct)
+ if (mw != NULL)
+ call mw_close (mw)
+ if (coo != NULL)
+ call sk_close (coo)
+ call sfree (sp)
+
+ return (npts)
+end
+
+
+# CC_REFPT -- Compute the coordinates of the reference point by averaging
+# the celestial coordinates.
+
+
+procedure cc_refpt (coo, lngref, latref, npts, lngmean, latmean)
+
+pointer coo #I the input coordinate system descriptor
+double lngref[ARB] #I the input longitude coordinates
+double latref[ARB] #I the input latitude coordinates
+int npts #I the number of input coordinates
+double lngmean #O the output mean longitude
+double latmean #O the output mean latitude
+
+double sumx, sumy, sumz, sumdx, sumdy, sumdz
+double tlng, tlat
+double x, y, z, tr, tpa
+int i
+int sk_stati()
+
+begin
+ sumx = 0.0d0; sumy = 0.0d0; sumz = 0.0d0
+ sumdx = 0.0d0; sumdy = 0.0d0; sumdz = 0.0d0
+
+ # Loop over the data points.
+ do i = 1, npts {
+
+ # Convert to radians.
+ switch (sk_stati(coo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ tlng = DDEGTORAD (15.0d0 * lngref[i])
+ case SKY_DEGREES:
+ tlng = DDEGTORAD (lngref[i])
+ case SKY_RADIANS:
+ tlng = lngref[i]
+ }
+ switch (sk_stati(coo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ tlat = DDEGTORAD (15.0d0 * latref[i])
+ case SKY_DEGREES:
+ tlat = DDEGTORAD (latref[i])
+ case SKY_RADIANS:
+ tlat = latref[i]
+ }
+
+ x = sin (tlat)
+ y = cos (tlat) * sin (tlng)
+ z = cos (tlat) * cos (tlng)
+
+ sumx = sumx + x
+ sumy = sumy + y
+ sumz = sumz + z
+ }
+
+ # Compute the average vector components.
+ sumx = sumx / npts
+ sumy = sumy / npts
+ sumz = sumz / npts
+
+ # Now compute the average distance and position angle.
+ tpa = atan2 (sumy, sumx)
+ if (tpa < 0.0d0)
+ tpa = tpa + DTWOPI
+ if (tpa >= DTWOPI)
+ tpa = tpa - DTWOPI
+ tr = sumz
+ if (abs(tr) > 0.99d0) {
+ if (tr < 0.0d0)
+ tr = DPI - asin (sqrt (sumx * sumx + sumy * sumy))
+ else
+ tr = asin (sqrt (sumx * sumx + sumy * sumy))
+ } else
+ tr = acos (tr)
+
+ # Solve for the average longitude and latitude.
+ sumx = sin (tr) * cos (tpa)
+ sumy = sin (tr) * sin (tpa)
+ sumz = cos (tr)
+ lngmean = atan2 (sumy, sumz)
+ if (lngmean < 0.0d0)
+ lngmean = lngmean + DTWOPI
+ if (lngmean >= DTWOPI)
+ lngmean = lngmean - DTWOPI
+ latmean = sumx
+ if (abs (latmean) > 0.99d0) {
+ if (latmean < 0.0d0)
+ latmean = -acos (sqrt(sumy ** 2 + sumz ** 2))
+ else
+ latmean = acos (sqrt(sumy ** 2 + sumz ** 2))
+ } else
+ latmean = asin (latmean)
+
+ # Convert back to appropriate units.
+ switch (sk_stati(coo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ lngmean = DRADTODEG (lngmean) / 15.0d0
+ case SKY_DEGREES:
+ lngmean = DRADTODEG (lngmean)
+ case SKY_RADIANS:
+ ;
+ }
+ switch (sk_stati(coo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ latmean = DRADTODEG (latmean) / 15.0d0
+ case SKY_DEGREES:
+ latmean = DRADTODEG (latmean)
+ case SKY_RADIANS:
+ ;
+ }
+end
+
+
+# CC_EVAL -- Compute the fitted standard coordinates.
+
+procedure cc_eval (sx1, sy1, sx2, sy2, xref, yref, xi, eta, npts)
+
+pointer sx1, sy1 #I pointer to linear surfaces
+pointer sx2, sy2 #I pointer to higher order surfaces
+double xref[ARB] #I the x reference coordinates
+double yref[ARB] #I the y reference coordinates
+double xi[ARB] #O the fitted xi coordinates
+double eta[ARB] #O the fitted eta coordinates
+int npts #I the number of points
+
+pointer sp, temp
+
+begin
+ call smark (sp)
+ call salloc (temp, npts, TY_DOUBLE)
+
+ call dgsvector (sx1, xref, yref, xi, npts)
+ if (sx2 != NULL) {
+ call dgsvector (sx2, xref, yref, Memd[temp], npts)
+ call aaddd (Memd[temp], xi, xi, npts)
+ }
+ call dgsvector (sy1, xref, yref, eta, npts)
+ if (sy2 != NULL) {
+ call dgsvector (sy2, xref, yref, Memd[temp], npts)
+ call aaddd (Memd[temp], eta, eta, npts)
+ }
+
+ call sfree (sp)
+end
+
+
+# CC_RMS -- Compute the rms of the fit in arcseconds.
+
+procedure cc_rms (fit, xi, eta, xifit, etafit, wts, npts, xirms, etarms)
+
+pointer fit #I pointer to the fit structure
+double xi[ARB] #I the input xi coordinates
+double eta[ARB] #I the input eta coordinates
+double xifit[ARB] #I the fitted chi coordinates
+double etafit[ARB] #I the fitted eta coordinates
+double wts[ARB] #I the input weights array
+int npts #I the number of points
+double xirms #O the output xi rms
+double etarms #O the output eta rms
+
+int i, index, ngood
+pointer sp, twts
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (twts, npts, TY_DOUBLE)
+
+ # Compute the weights.
+ call amovd (wts, Memd[twts], npts)
+ do i = 1, GM_NREJECT(fit) {
+ index = Memi[GM_REJ(fit)+i-1]
+ if (wts[index] > 0.0d0)
+ Memd[twts+index-1] = 0.0d0
+ }
+
+ # Accumulate the squares.
+ xirms = 0.0d0
+ etarms = 0.0d0
+ do i = 1, npts {
+ xirms = xirms + Memd[twts+i-1] * (xi[i] - xifit[i]) ** 2
+ etarms = etarms + Memd[twts+i-1] * (eta[i] - etafit[i]) ** 2
+ }
+
+ # Compute the rms.
+ #ngood = max (0, GM_NPTS(fit) - GM_NREJECT(fit) - GM_NWTS0(fit))
+ ngood = max (0, GM_NPTS(fit) - GM_NWTS0(fit))
+ if (ngood > 1) {
+ xirms = sqrt (xirms / (ngood - 1))
+ etarms = sqrt (etarms / (ngood - 1))
+ } else {
+ xirms = 0.0d0
+ etarms = 0.0d0
+ }
+ xirms = xirms
+ etarms = etarms
+
+ call sfree (sp)
+end
+
+
+# CC_SHOW -- Print the coodinate mapping parameters.
+
+procedure cc_show (fd, coo, projection, lngref, latref, sx1, sy1, comment)
+
+int fd #I the output file descriptor
+pointer coo #I pointer to the coordinate structure
+char projection[ARB] #I the sky projection geometry
+double lngref, latref #I the coordinates of the reference point
+pointer sx1, sy1 #I pointer to linear surfaces
+int comment #I comment the output ?
+
+double xshift, yshift, a, b, c, d, denom
+double xpix, ypix, xscale, yscale, xrot, yrot
+pointer sp, str, keyword, value
+bool fp_equald()
+int sk_stati()
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (keyword, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+
+ # Compute the geometric parameters.
+ call geo_gcoeffd (sx1, sy1, xshift, yshift, a, b, c, d)
+
+ # Compute the position of the reference pixel from the geometric
+ # parameters.
+ denom = a * d - c * b
+ if (denom == 0.0d0)
+ xpix = INDEFD
+ else
+ xpix = (b * yshift - d * xshift) / denom
+ if (denom == 0.0d0)
+ ypix = INDEFD
+ else
+ ypix = (c * xshift - a * yshift) / denom
+
+ if (comment == NO) {
+ call fprintf (fd, "Coordinate mapping parameters\n")
+ call fprintf (fd, " Sky projection geometry: %s\n")
+ } else {
+ call fprintf (fd, "# Coordinate mapping parameters\n")
+ call fprintf (fd, "# Sky projection geometry: %s\n")
+ }
+ if (projection[1] == EOS)
+ call pargstr ("lin")
+ else {
+ call sscan (projection)
+ call gargwrd (Memc[str], SZ_LINE)
+ call pargstr (Memc[str])
+ repeat {
+ call gargwrd (Memc[keyword], SZ_FNAME)
+ if (Memc[keyword] == EOS)
+ break
+ call gargwrd (Memc[value], SZ_FNAME)
+ if (Memc[value] != '=')
+ break
+ call gargwrd (Memc[value], SZ_FNAME)
+ if (Memc[value] == EOS)
+ break
+ if (comment == NO) {
+ call fprintf (fd, " Projection parameter %s: %s\n")
+ } else {
+ call fprintf (fd, "# Projection parameter %s: %s\n")
+ }
+ call pargstr (Memc[keyword])
+ call pargstr (Memc[value])
+ }
+
+ }
+
+ # Output the reference point.
+ if (comment == NO) {
+ call sprintf (Memc[str], SZ_LINE,
+ " Reference point: %s %s (%s %s)\n")
+ } else {
+ call sprintf (Memc[str], SZ_LINE,
+ "# Reference point: %s %s (%s %s)\n")
+ }
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("%0.2h")
+ case SKY_RADIANS:
+ call pargstr ("%0.7g")
+ case SKY_HOURS:
+ call pargstr ("%0.3h")
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("%0.2h")
+ case SKY_RADIANS:
+ call pargstr ("%0.7g")
+ case SKY_HOURS:
+ call pargstr ("%0.3h")
+ }
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("degrees")
+ case SKY_RADIANS:
+ call pargstr ("radians")
+ case SKY_HOURS:
+ call pargstr ("hours")
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("degrees")
+ case SKY_RADIANS:
+ call pargstr ("radians")
+ case SKY_HOURS:
+ call pargstr ("hours")
+ }
+ if (comment == NO) {
+ call printf (Memc[str])
+ call pargd (lngref)
+ call pargd (latref)
+ } else {
+ call fprintf (fd, Memc[str])
+ call pargd (lngref)
+ call pargd (latref)
+ }
+
+ if (comment == NO) {
+ call fprintf (fd,
+ " Reference point: %0.3f %0.3f (pixels pixels)\n")
+ call pargd (xpix)
+ call pargd (ypix)
+ } else {
+ call fprintf (fd,
+ "# Reference point: %0.3f %0.3f (pixels pixels)\n")
+ call pargd (xpix)
+ call pargd (ypix)
+ }
+
+ # Output the scale factors.
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+ if (comment == NO) {
+ call fprintf (fd,
+ " X and Y scale: %0.3f %0.3f (arcsec/pixel arcsec/pixel)\n")
+ call pargd (xscale)
+ call pargd (yscale)
+ } else {
+ call fprintf (fd,
+ "# X and Y scale: %0.3f %0.3f (arcsec/pixel arcsec/pixel)\n")
+ call pargd (xscale)
+ call pargd (yscale)
+ }
+
+ # Output the rotation factors.
+ if (fp_equald (a, 0.0d0) && fp_equald (c, 0.0d0))
+ xrot = 0.0d0
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < 0.0d0)
+ xrot = xrot + 360.0d0
+ if (fp_equald (b, 0.0d0) && fp_equald (d, 0.0d0))
+ yrot = 0.0d0
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < 0.0d0)
+ yrot = yrot + 360.0d0
+ if (comment == NO) {
+ call fprintf (fd,
+ " X and Y axis rotation: %0.3f %0.3f (degrees degrees)\n")
+ call pargd (xrot)
+ call pargd (yrot)
+ } else {
+ call fprintf (fd,
+ "# X and Y axis rotation: %0.3f %0.3f (degrees degrees)\n")
+ call pargd (xrot)
+ call pargd (yrot)
+ }
+
+ call sfree (sp)
+end
+
+
+# CC_OUT -- Write the output database file record.
+
+procedure cc_out (fit, coo, out, sx1, sy1, sx2, sy2, lxrms, lyrms)
+
+pointer fit #I pointer to fitting structure
+pointer coo #I pointer to the coordinate system structure
+int out #I pointer to database file
+pointer sx1, sy1 #I pointer to linear surfaces
+pointer sx2, sy2 #I pointer to distortion surfaces
+double lxrms, lyrms #I the input wcs x and y rms
+
+double xshift, yshift, a, b, c, d, denom, xrms, yrms
+double xpixref, ypixref, xscale, yscale, xrot, yrot
+int i, npts, ncoeff
+pointer sp, str, xcoeff, ycoeff, keyword, value
+bool fp_equald()
+int dgsgeti(), rg_wrdstr(), sk_stati()
+
+begin
+ # Allocate some working memory.
+ call smark (sp)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (keyword, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+
+ # Compute the rms.
+ #npts = max (0, GM_NPTS(fit) - GM_NREJECT(fit) - GM_NWTS0(fit))
+ npts = max (0, GM_NPTS(fit) - GM_NWTS0(fit))
+ xrms = max (0.0d0, GM_XRMS(fit))
+ yrms = max (0.0d0, GM_YRMS(fit))
+ if (npts > 1) {
+ xrms = sqrt (xrms / (npts - 1))
+ yrms = sqrt (yrms / (npts - 1))
+ } else {
+ xrms = 0.0d0
+ yrms = 0.0d0
+ }
+
+ # Compute the geometric parameters.
+ call geo_gcoeffd (sx1, sy1, xshift, yshift, a, b, c, d)
+ denom = a * d - c * b
+ if (denom == 0.0d0)
+ xpixref = INDEFD
+ else
+ xpixref = (b * yshift - d * xshift) / denom
+ if (denom == 0.0d0)
+ ypixref = INDEFD
+ else
+ ypixref = (c * xshift - a * yshift) / denom
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+ if (fp_equald (a, 0.0d0) && fp_equald (c, 0.0d0))
+ xrot = 0.0d0
+ else
+ xrot = RADTODEG(atan2 (-c, a))
+ if (xrot < 0.0d0)
+ xrot = xrot + 360.0d0
+ if (fp_equald (b, 0.0d0) && fp_equald (d, 0.0d0))
+ yrot = 0.0d0
+ else
+ yrot = RADTODEG(atan2 (b, d))
+ if (yrot < 0.0d0)
+ yrot = yrot + 360.0d0
+
+ # Print title.
+ call dtptime (out)
+ call dtput (out, "begin\t%s\n")
+ call pargstr (GM_RECORD(fit))
+
+ # Print out some information about the data.
+ call dtput (out, "\txrefmean\t%g\n")
+ call pargd (GM_XOREF(fit))
+ call dtput (out, "\tyrefmean\t%g\n")
+ call pargd (GM_YOREF(fit))
+ call dtput (out, "\tlngmean\t\t%g\n")
+ call pargd (GM_XOIN(fit))
+ call dtput (out, "\tlatmean\t\t%g\n")
+ call pargd (GM_YOIN(fit))
+
+ # Print out information about the tangent point.
+ if (rg_wrdstr(sk_stati(coo, S_PIXTYPE), Memc[str], SZ_FNAME,
+ PIXTYPE_LIST) <= 0)
+ call strcpy ("logical", Memc[str], SZ_FNAME)
+ call dtput (out, "\tpixsystem\t%s\n")
+ call pargstr (Memc[str])
+ call sk_stats (coo, S_COOSYSTEM, Memc[str], SZ_FNAME)
+ call dtput (out, "\tcoosystem\t%g\n")
+ call pargstr (Memc[str])
+
+ if (rg_wrdstr (GM_PROJECTION(fit), Memc[str], SZ_FNAME,
+ GM_PROJLIST) <= 0)
+ call strcpy ("tan", Memc[str], SZ_FNAME)
+ call dtput (out, "\tprojection\t%s\n")
+ call pargstr (Memc[str])
+ call sscan (GM_PROJSTR(fit))
+ call gargwrd (Memc[str], SZ_FNAME)
+ repeat {
+ call gargwrd (Memc[keyword], SZ_FNAME)
+ if (Memc[keyword] == EOS)
+ break
+ call gargwrd (Memc[value], SZ_FNAME)
+ if (Memc[value] != '=')
+ break
+ call gargwrd (Memc[value], SZ_FNAME)
+ if (Memc[value] == EOS)
+ break
+ call dtput (out, "\t%s\t\t%s\n")
+ call pargstr (Memc[keyword])
+ call pargstr (Memc[value])
+ }
+
+ call dtput (out, "\tlngref\t\t%g\n")
+ call pargd (GM_XREFPT(fit))
+ call dtput (out, "\tlatref\t\t%g\n")
+ call pargd (GM_YREFPT(fit))
+ if (rg_wrdstr (sk_stati(coo, S_NLNGUNITS), Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST) <= 0)
+ ;
+ call dtput (out, "\tlngunits\t%s\n")
+ call pargstr (Memc[str])
+ if (rg_wrdstr (sk_stati(coo, S_NLATUNITS), Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST) <= 0)
+ ;
+ call dtput (out, "\tlatunits\t%s\n")
+ call pargstr (Memc[str])
+ call dtput (out, "\txpixref\t\t%g\n")
+ call pargd (xpixref)
+ call dtput (out, "\typixref\t\t%g\n")
+ call pargd (ypixref)
+
+ # Print out information about the fit.
+ if (rg_wrdstr (GM_FIT(fit), Memc[str], SZ_FNAME, GM_GEOMETRIES) <= 0)
+ call strcpy ("general", Memc[str], SZ_FNAME)
+ call dtput (out, "\tgeometry\t%s\n")
+ call pargstr (Memc[str])
+ if (rg_wrdstr (GM_FUNCTION(fit), Memc[str], SZ_FNAME, GM_FUNCS) <= 0)
+ call strcpy ("polynomial", Memc[str], SZ_FNAME)
+ call dtput (out, "\tfunction\t%s\n")
+ call pargstr (Memc[str])
+ call dtput (out, "\txishift\t\t%g\n")
+ call pargd (xshift)
+ call dtput (out, "\tetashift\t%g\n")
+ call pargd (yshift)
+ call dtput (out, "\txmag\t\t%g\n")
+ call pargd (xscale)
+ call dtput (out, "\tymag\t\t%g\n")
+ call pargd (yscale)
+ call dtput (out, "\txrotation\t%g\n")
+ call pargd (xrot)
+ call dtput (out, "\tyrotation\t%g\n")
+ call pargd (yrot)
+
+ # Output the rms of the fit.
+ call dtput (out, "\twcsxirms\t%g\n")
+ call pargd (lxrms)
+ call dtput (out, "\twcsetarms\t%g\n")
+ call pargd (lyrms)
+ call dtput (out, "\txirms\t\t%g\n")
+ call pargd (xrms)
+ call dtput (out, "\tetarms\t\t%g\n")
+ call pargd (yrms)
+
+ # Allocate memory for linear coefficients.
+ ncoeff = max (dgsgeti (sx1, GSNSAVE), dgsgeti (sy1, GSNSAVE))
+ call calloc (xcoeff, ncoeff, TY_DOUBLE)
+ call calloc (ycoeff, ncoeff, TY_DOUBLE)
+
+ # Encode the linear coefficients.
+ call dgssave (sx1, Memd[xcoeff])
+ call dgssave (sy1, Memd[ycoeff])
+
+ # Output the linear coefficients.
+ call dtput (out, "\tsurface1\t%d\n")
+ call pargi (ncoeff)
+ do i = 1, ncoeff {
+ call dtput (out, "\t\t\t%g\t%g\n")
+ call pargd (Memd[xcoeff+i-1])
+ call pargd (Memd[ycoeff+i-1])
+ }
+
+ # Free the linear coefficient memory.
+ call mfree (xcoeff, TY_DOUBLE)
+ call mfree (ycoeff, TY_DOUBLE)
+
+ # Allocate memory for higer order coefficients.
+ if (sx2 == NULL)
+ ncoeff = 0
+ else
+ ncoeff = dgsgeti (sx2, GSNSAVE)
+ if (sy2 == NULL)
+ ncoeff = max (0, ncoeff)
+ else
+ ncoeff = max (dgsgeti (sy2, GSNSAVE), ncoeff)
+ call calloc (xcoeff, ncoeff, TY_DOUBLE)
+ call calloc (ycoeff, ncoeff, TY_DOUBLE)
+
+ # Encode the coefficients.
+ call dgssave (sx2, Memd[xcoeff])
+ call dgssave (sy2, Memd[ycoeff])
+
+ # Output the coefficients.
+ call dtput (out, "\tsurface2\t%d\n")
+ call pargi (ncoeff)
+ do i = 1, ncoeff {
+ call dtput (out, "\t\t\t%g\t%g\n")
+ call pargd (Memd[xcoeff+i-1])
+ call pargd (Memd[ycoeff+i-1])
+ }
+
+ # Cleanup.
+ call mfree (xcoeff, TY_DOUBLE)
+ call mfree (ycoeff, TY_DOUBLE)
+ call sfree (sp)
+end
+
+
+# CC_PLIST -- List the coordinates and the residuals.
+
+procedure cc_plist (fd, fit, coo, xref, yref, lngref, latref, lngfit, latfit,
+ wts, npts)
+
+int fd #I the results file descriptor
+pointer fit #I pointer to the fit structure
+pointer coo #I pointer to the coordinate structure
+double xref[ARB] #I the input x coordinates
+double yref[ARB] #I the input y coordinates
+double lngref[ARB] #I the input ra / longitude coordinates
+double latref[ARB] #I the input dec / latitude coordinates
+double lngfit[ARB] #I the fitted ra / longitude coordinates
+double latfit[ARB] #I the fitted dec / latitude coordinates
+double wts[ARB] #I the weights array
+int npts #I the number of data points
+
+double diflng, diflat
+int i, index
+pointer sp, fmtstr, lngunits, latunits, twts
+int sk_stati()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (fmtstr, SZ_LINE, TY_CHAR)
+ call salloc (lngunits, SZ_FNAME, TY_CHAR)
+ call salloc (latunits, SZ_FNAME, TY_CHAR)
+ call salloc (twts, npts, TY_DOUBLE)
+
+ # Get the unit strings.
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ call strcpy ("hours", Memc[lngunits], SZ_FNAME)
+ case SKY_DEGREES:
+ call strcpy ("degrees", Memc[lngunits], SZ_FNAME)
+ default:
+ call strcpy ("radians", Memc[lngunits], SZ_FNAME)
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ call strcpy ("hours", Memc[latunits], SZ_FNAME)
+ case SKY_DEGREES:
+ call strcpy ("degrees", Memc[latunits], SZ_FNAME)
+ default:
+ call strcpy ("radians", Memc[latunits], SZ_FNAME)
+ }
+
+ # Compute the weights.
+ call amovd (wts, Memd[twts], npts)
+ do i = 1, GM_NREJECT(fit) {
+ index = Memi[GM_REJ(fit)+i-1]
+ if (wts[index] > 0.0d0)
+ Memd[twts+index-1] = 0.0d0
+ }
+
+ # Print banner.
+ call fprintf (fd, "\n# Input Coordinate Listing\n")
+ call fprintf (fd, "# Column 1: X (pixels)\n")
+ call fprintf (fd, "# Column 2: Y (pixels)\n")
+ call fprintf (fd, "# Column 3: Ra / Longitude (%s)\n")
+ call pargstr (Memc[lngunits])
+ call fprintf (fd, "# Column 4: Dec / Latitude (%s)\n")
+ call pargstr (Memc[latunits])
+ call fprintf (fd, "# Column 5: Fitted Ra / Longitude (%s)\n")
+ call pargstr (Memc[lngunits])
+ call fprintf (fd, "# Column 6: Fitted Dec / Latitude (%s)\n")
+ call pargstr (Memc[latunits])
+ call fprintf (fd,
+ "# Column 7: Residual Ra / Longitude (arcseconds)\n")
+ call fprintf (fd,
+ "# Column 8: Residual Dec / Latitude (arcseconds)\n\n")
+
+ # Create format string.
+ call sprintf (Memc[fmtstr], SZ_LINE, "%s %s %s %s %s %s %s %s\n")
+ call pargstr ("%10.3f")
+ call pargstr ("%10.3f")
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ call pargstr ("%12.3h")
+ case SKY_DEGREES:
+ call pargstr ("%12.2h")
+ default:
+ call pargstr ("%12.7g")
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ call pargstr ("%12.3h")
+ case SKY_DEGREES:
+ call pargstr ("%12.2h")
+ default:
+ call pargstr ("%12.7g")
+ }
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_HOURS:
+ call pargstr ("%12.3h")
+ case SKY_DEGREES:
+ call pargstr ("%12.2h")
+ default:
+ call pargstr ("%12.7g")
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_HOURS:
+ call pargstr ("%12.3h")
+ case SKY_DEGREES:
+ call pargstr ("%12.2h")
+ default:
+ call pargstr ("%12.7g")
+ }
+ call pargstr ("%6.3f")
+ call pargstr ("%6.3f")
+
+ do i = 1, npts {
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_DEGREES:
+ diflng = (lngref[i] - lngfit[i]) * 3600.0d0
+ case SKY_HOURS:
+ diflng = 15.0d0 * (lngref[i] - lngfit[i]) * 3600.0d0 *
+ cos (DEGTORAD(latref[i]))
+ case SKY_RADIANS:
+ diflng = RADTODEG ((lngref[i] - lngfit[i])) * 3600.0d0
+ default:
+ diflng = lngref[i] - lngfit[i]
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_DEGREES:
+ diflat = (latref[i] - latfit[i]) * 3600.0d0
+ case SKY_HOURS:
+ diflat = 15.0d0 * (latref[i] - latfit[i]) * 3600.0d0
+ case SKY_RADIANS:
+ diflat = RADTODEG ((latref[i] - latfit[i])) * 3600.0d0
+ default:
+ diflat = latref[i] - latfit[i]
+ }
+ call fprintf (fd, Memc[fmtstr])
+ call pargd (xref[i])
+ call pargd (yref[i])
+ call pargd (lngref[i])
+ call pargd (latref[i])
+ if (Memd[twts+i-1] > 0.0d0) {
+ call pargd (lngfit[i])
+ call pargd (latfit[i])
+ call pargd (diflng)
+ call pargd (diflat)
+ } else {
+ call pargd (INDEFD)
+ call pargd (INDEFD)
+ call pargd (INDEFD)
+ call pargd (INDEFD)
+ }
+ }
+
+ call fprintf (fd, "\n")
+
+ call sfree (sp)
+end
diff --git a/pkg/images/imcoords/src/t_ccsetwcs.x b/pkg/images/imcoords/src/t_ccsetwcs.x
new file mode 100644
index 00000000..85c0c0ff
--- /dev/null
+++ b/pkg/images/imcoords/src/t_ccsetwcs.x
@@ -0,0 +1,751 @@
+include <imhdr.h>
+include <math.h>
+include <mwset.h>
+include <pkg/skywcs.h>
+
+# Define the possible pixel types
+
+define CC_PIXTYPESTR "|logical|physical|"
+define CC_LOGICAL 1
+define CC_PHYSICAL 2
+
+
+# T_CCSETWCS -- Create a wcs and write it to the image header. The wcs may
+# be read from a database file written by CCMAP or it may be input by the
+# user.
+
+procedure t_ccsetwcs ()
+
+bool transpose, verbose, update
+double xref, yref, xscale, yscale, xrot, yrot, lngref, latref
+double txref, tyref, txscale, tyscale, txrot, tyrot, tlngref, tlatref
+int imlist, reclist, lngunits, latunits, coostat, recstat, proj, pixsys, pfd
+pointer sp, image, database, record, insystem, projstr, str
+pointer dt, im, coo, tcoo, mw, sx1, sy1, sx2, sy2
+bool clgetb()
+double clgetd()
+int imtopenp(), clgwrd(), sk_decwcs(), sk_stati(), imtlen()
+int imtgetim(), cc_dtwcs(), strdic(), cc_rdproj(), open()
+pointer dtmap(), immap()
+errchk open()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (database, SZ_FNAME, TY_CHAR)
+ call salloc (record, SZ_FNAME, TY_CHAR)
+ call salloc (insystem, SZ_FNAME, TY_CHAR)
+ call salloc (projstr, SZ_LINE, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ imlist = imtopenp ("images")
+ call clgstr ("database", Memc[database], SZ_FNAME)
+
+ # Fetch the celestial coordinate system parameters.
+ if (Memc[database] == EOS) {
+ dt = NULL
+ reclist = NULL
+ xref = clgetd ("xref")
+ yref = clgetd ("yref")
+ xscale = clgetd ("xmag")
+ yscale = clgetd ("ymag")
+ xrot = clgetd ("xrotation")
+ yrot = clgetd ("yrotation")
+ lngref = clgetd ("lngref")
+ latref = clgetd ("latref")
+ iferr (lngunits = clgwrd ("lngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ lngunits = 0
+ iferr (latunits = clgwrd ("latunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ latunits = 0
+ call clgstr ("coosystem", Memc[insystem], SZ_FNAME)
+ coostat = sk_decwcs (Memc[insystem], mw, coo, NULL)
+ if (coostat == ERR || mw != NULL) {
+ call eprintf ("Error decoding the coordinate system %s\n")
+ call pargstr (Memc[insystem])
+ if (mw != NULL)
+ call mw_close (mw)
+ if (coo != NULL)
+ #call mfree (coo, TY_STRUCT)
+ call sk_close (coo)
+ call imtclose (imlist)
+ call sfree (sp)
+ return
+ }
+ if (lngunits <= 0)
+ lngunits = sk_stati (coo, S_NLNGUNITS)
+ call sk_seti (coo, S_NLNGUNITS, lngunits)
+ if (latunits <= 0)
+ latunits = sk_stati (coo, S_NLATUNITS)
+ call sk_seti (coo, S_NLATUNITS, latunits)
+
+ call clgstr ("projection", Memc[projstr], SZ_LINE)
+ iferr {
+ pfd = open (Memc[projstr], READ_ONLY, TEXT_FILE)
+ } then {
+ proj = strdic (Memc[projstr], Memc[projstr], SZ_LINE,
+ WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projstr] = EOS
+ } else {
+ proj = cc_rdproj (pfd, Memc[projstr], SZ_LINE)
+ call close (pfd)
+ }
+
+ iferr (pixsys = clgwrd ("pixsystem", Memc[str], SZ_FNAME,
+ CC_PIXTYPESTR))
+ pixsys = PIXTYPE_LOGICAL
+ else if (pixsys == CC_PHYSICAL)
+ pixsys = PIXTYPE_PHYSICAL
+ else
+ pixsys = PIXTYPE_LOGICAL
+ call sk_seti (coo, S_PIXTYPE, pixsys)
+ } else {
+ dt = dtmap (Memc[database], READ_ONLY)
+ reclist = imtopenp ("solutions")
+ if ((imtlen (reclist) > 1) && (imtlen (imlist) !=
+ imtlen (reclist))) {
+ call eprintf (
+ " The image and record list lengths are different\n")
+ call imtclose (reclist)
+ call dtunmap (dt)
+ call imtclose (imlist)
+ call sfree (sp)
+ return
+ }
+ coo = NULL
+ }
+
+ transpose = clgetb ("transpose")
+ verbose = clgetb ("verbose")
+ update = clgetb ("update")
+
+ # Loop over the images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ if (update)
+ im = immap (Memc[image], READ_WRITE, 0)
+ else
+ im = immap (Memc[image], READ_ONLY, 0)
+ if (IM_NDIM(im) != 2) {
+ call printf ("Skipping non 2D image %s\n")
+ call pargstr (Memc[image])
+ call imunmap (im)
+ next
+ }
+
+ if (dt == NULL) {
+
+ if (verbose) {
+ call printf ("Image: %s\n")
+ call pargstr (Memc[image])
+ }
+
+ # Compute the linear transformation parameters.
+ if (IS_INDEFD(lngref))
+ tlngref = 0.0d0
+ else
+ tlngref = lngref
+ if (IS_INDEFD(latref))
+ tlatref = 0.0d0
+ else
+ tlatref = latref
+ if (IS_INDEFD(xref))
+ txref = (1.0d0 + IM_LEN(im,1)) / 2.0
+ else
+ txref = xref
+ if (IS_INDEFD(yref))
+ tyref = (1.0d0 + IM_LEN(im,2)) / 2.0
+ else
+ tyref = yref
+ if (IS_INDEFD(xscale))
+ txscale = 1.0d0
+ else
+ txscale = xscale
+ if (IS_INDEFD(yscale))
+ tyscale = 1.0d0
+ else
+ tyscale = yscale
+ if (IS_INDEFD(xrot))
+ txrot = 0.0d0
+ else
+ txrot = xrot
+ if (IS_INDEFD(yrot))
+ tyrot = 0.0d0
+ else
+ tyrot = yrot
+
+ if (verbose)
+ call cc_usershow (coo, Memc[projstr], tlngref, tlatref,
+ txref, tyref, txscale, tyscale, txrot, tyrot,
+ transpose)
+
+ if (update) {
+ call cc_userwcs (im, coo, Memc[projstr], tlngref, tlatref,
+ txref, tyref, txscale, tyscale, txrot, tyrot,
+ transpose)
+ if (verbose)
+ call printf ("Updating image header wcs\n")
+ }
+
+ } else {
+ if (imtgetim (reclist, Memc[record], SZ_FNAME) == EOF)
+ #call strcpy (Memc[image], Memc[record], SZ_FNAME)
+ ;
+ if (verbose) {
+ call printf ("Image: %s Database: %s Solution: %d\n")
+ call pargstr (Memc[image])
+ call pargstr (Memc[database])
+ call pargstr (Memc[record])
+ }
+ sx1 = NULL; sx2 = NULL
+ sy1 = NULL; sy2 = NULL
+ tcoo = NULL
+ recstat = cc_dtwcs (dt, Memc[record], tcoo, Memc[projstr],
+ tlngref, tlatref, sx1, sy1, sx2, sy2, txref, tyref, txscale,
+ tyscale, txrot, tyrot)
+ if (recstat == ERR) {
+ call printf (" Cannot find or decode ")
+ call printf ("record %s in database file %s\n")
+ call pargstr (Memc[record])
+ call pargstr (Memc[database])
+ } else {
+ call sscan (Memc[projstr])
+ call gargwrd (Memc[str], SZ_FNAME)
+ proj = strdic (Memc[str], Memc[str], SZ_FNAME,
+ WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projstr] = EOS
+ if (verbose)
+ call cc_usershow (tcoo, Memc[projstr], tlngref,
+ tlatref, txref, tyref, txscale, tyscale, txrot,
+ tyrot, transpose)
+ if (update) {
+ call cc_nwcsim (im, tcoo, Memc[projstr], tlngref,
+ tlatref, sx1, sy1, sx2, sy2, transpose)
+ if (verbose)
+ call printf ("Updating image header wcs\n")
+ }
+ }
+ if (tcoo != NULL)
+ #call mfree (tcoo, TY_STRUCT)
+ call sk_close (tcoo)
+ if (sx1 != NULL)
+ call dgsfree (sx1)
+ if (sy1 != NULL)
+ call dgsfree (sy1)
+ }
+
+ call imunmap (im)
+ }
+
+ # Close up memory.
+ if (coo != NULL)
+ #call mfree (coo, TY_STRUCT)
+ call sk_close (coo)
+ if (dt != NULL)
+ call dtunmap (dt)
+ if (reclist != NULL)
+ call imtclose (reclist)
+ call imtclose (imlist)
+
+ call sfree (sp)
+end
+
+
+define NEWCD Memd[ncd+(($2)-1)*ndim+($1)-1]
+
+# CC_USERWCS -- Compute the image wcs from the user parameters.
+
+procedure cc_userwcs (im, coo, projection, lngref, latref, xref, yref,
+ xscale, yscale, xrot, yrot, transpose)
+
+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
+
+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
+ }
+
+ # 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)
+ }
+ call sk_saveim (coo, mwnew, im)
+ call mw_saveim (mwnew, im)
+ 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
+
+
+# CC_USERSHOW -- Print the image wcs parameters in user friendly format.
+
+procedure cc_usershow (coo, projection, lngref, latref, xref, yref, xscale,
+ yscale, xrot, yrot, transpose)
+
+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
+
+pointer sp, str, keyword, value
+int sk_stati()
+
+begin
+ # Allocate temporary space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+ call salloc (keyword, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+
+ call printf ("Coordinate mapping parameters\n")
+ call printf (" Sky projection geometry: %s\n")
+ if (projection[1] == EOS)
+ call pargstr ("lin")
+ else {
+ call sscan (projection)
+ call gargwrd (Memc[str], SZ_LINE)
+ call pargstr (Memc[str])
+ repeat {
+ call gargwrd (Memc[keyword], SZ_FNAME)
+ if (Memc[keyword] == EOS)
+ break
+ call gargwrd (Memc[value], SZ_FNAME)
+ if (Memc[value] != '=')
+ break
+ call gargwrd (Memc[value], SZ_FNAME)
+ if (Memc[value] == EOS)
+ break
+ call printf (" Projection parameter %s: %s\n")
+ call pargstr (Memc[keyword])
+ call pargstr (Memc[value])
+ }
+ }
+
+ # Output the reference point.
+ call sprintf (Memc[str], SZ_LINE,
+ " Reference point: %s %s (%s %s)\n")
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("%0.2h")
+ case SKY_RADIANS:
+ call pargstr ("%0.7g")
+ case SKY_HOURS:
+ call pargstr ("%0.3h")
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("%0.2h")
+ case SKY_RADIANS:
+ call pargstr ("%0.7g")
+ case SKY_HOURS:
+ call pargstr ("%0.3h")
+ }
+ switch (sk_stati (coo, S_NLNGUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("degrees")
+ case SKY_RADIANS:
+ call pargstr ("radians")
+ case SKY_HOURS:
+ call pargstr ("hours")
+ }
+ switch (sk_stati (coo, S_NLATUNITS)) {
+ case SKY_DEGREES:
+ call pargstr ("degrees")
+ case SKY_RADIANS:
+ call pargstr ("radians")
+ case SKY_HOURS:
+ call pargstr ("hours")
+ }
+ call printf (Memc[str])
+ call pargd (lngref)
+ call pargd (latref)
+
+ # Output the logical axes.
+ if (sk_stati (coo, S_CTYPE) == CTYPE_EQUATORIAL)
+ call printf (" Ra/Dec logical image axes: %d %d\n")
+ else
+ call printf (" Long/Lat logical image axes: %d %d\n")
+ if (! transpose) {
+ call pargi (1)
+ call pargi (2)
+ } else {
+ call pargi (2)
+ call pargi (1)
+ }
+
+ # Output the reference point in pixels.
+ call printf (" Reference point: %0.3f %0.3f (pixels pixels)\n")
+ call pargd (xref)
+ call pargd (yref)
+
+ # Output the scale factors.
+ call printf (
+ " X and Y scale: %0.3f %0.3f (arcsec/pixel arcsec/pixel)\n")
+ call pargd (xscale)
+ call pargd (yscale)
+
+ # Output the rotation angles.
+ call printf (
+ " X and Y coordinate rotation: %0.3f %0.3f (degrees degrees)\n")
+ call pargd (xrot)
+ call pargd (yrot)
+
+ call sfree (sp)
+end
+
+
+# CC_DTWCS -- Read the wcs from the database records written by CCMAP.
+
+int procedure cc_dtwcs (dt, record, coo, projection, lngref, latref, sx1, sy1,
+ sx2, sy2, xref, yref, xscale, yscale, xrot, yrot)
+
+pointer dt #I pointer to the database
+char record[ARB] #I the database records to be read
+pointer coo #O pointer to the coordinate structure
+char projection[ARB] #O the sky projection geometry
+double lngref, latref #O the reference point world coordinates
+pointer sx1, sy1 #O pointer to the linear x and y fits
+pointer sx2, sy2 #O pointer to the distortion x and y fits
+double xref, yref #O the reference point in pixels
+double xscale, yscale #O the x and y scale factors
+double xrot, yrot #O the x and y axis rotation angles
+
+int i, op, ncoeff, junk, rec, coostat, lngunits, latunits, pixsys
+double xshift, yshift, a, b, c, d, denom
+pointer sp, xcoeff, ycoeff, nxcoeff, nycoeff, mw, projpar, projvalue
+bool fp_equald()
+double dtgetd()
+int dtlocate(), dtgeti(), dtscan(), sk_decwcs(), strdic(), strlen()
+int gstrcpy()
+errchk dtgstr(), dtgetd(), dtgeti(), dgsrestore()
+
+begin
+ # Locate the appropriate records.
+ iferr (rec = dtlocate (dt, record))
+ return (ERR)
+
+ # Open the coordinate structure.
+ iferr (call dtgstr (dt, rec, "coosystem", projection, SZ_FNAME))
+ return (ERR)
+ coostat = sk_decwcs (projection, mw, coo, NULL)
+ if (coostat == ERR || mw != NULL) {
+ if (mw != NULL)
+ call mw_close (mw)
+ projection[1] = EOS
+ return (ERR)
+ }
+
+ # Get the pixel coordinate system.
+ iferr (call dtgstr (dt, rec, "pixsystem", projection, SZ_FNAME)) {
+ pixsys = PIXTYPE_LOGICAL
+ } else {
+ pixsys = strdic (projection, projection, SZ_FNAME, PIXTYPE_LIST)
+ if (pixsys != PIXTYPE_PHYSICAL)
+ pixsys = PIXTYPE_LOGICAL
+ }
+ call sk_seti (coo, S_PIXTYPE, pixsys)
+
+
+ # Get the reference point units.
+ iferr (call dtgstr (dt, rec, "lngunits", projection, SZ_FNAME))
+ return (ERR)
+ lngunits = strdic (projection, projection, SZ_FNAME, SKY_LNG_UNITLIST)
+ if (lngunits > 0)
+ call sk_seti (coo, S_NLNGUNITS, lngunits)
+ iferr (call dtgstr (dt, rec, "latunits", projection, SZ_FNAME))
+ return (ERR)
+ latunits = strdic (projection, projection, SZ_FNAME, SKY_LAT_UNITLIST)
+ if (latunits > 0)
+ call sk_seti (coo, S_NLATUNITS, latunits)
+
+ # Get the reference point.
+ iferr (call dtgstr (dt, rec, "projection", projection, SZ_FNAME))
+ return (ERR)
+ iferr (lngref = dtgetd (dt, rec, "lngref"))
+ return (ERR)
+ iferr (latref = dtgetd (dt, rec, "latref"))
+ return (ERR)
+
+ # Read in the coefficients.
+ iferr (ncoeff = dtgeti (dt, rec, "surface1"))
+ return (ERR)
+ call smark (sp)
+ call salloc (xcoeff, ncoeff, TY_DOUBLE)
+ call salloc (ycoeff, ncoeff, TY_DOUBLE)
+ do i = 1, ncoeff {
+ junk = dtscan(dt)
+ call gargd (Memd[xcoeff+i-1])
+ call gargd (Memd[ycoeff+i-1])
+ }
+
+ # Restore the linear part of the fit.
+ call dgsrestore (sx1, Memd[xcoeff])
+ call dgsrestore (sy1, Memd[ycoeff])
+
+ # Get and restore the distortion part of the fit.
+ ncoeff = dtgeti (dt, rec, "surface2")
+ if (ncoeff > 0) {
+ call salloc (nxcoeff, ncoeff, TY_DOUBLE)
+ call salloc (nycoeff, ncoeff, TY_DOUBLE)
+ do i = 1, ncoeff {
+ junk = dtscan(dt)
+ call gargd (Memd[nxcoeff+i-1])
+ call gargd (Memd[nycoeff+i-1])
+ }
+ iferr {
+ call dgsrestore (sx2, Memd[nxcoeff])
+ } then {
+ call mfree (sx2, TY_STRUCT)
+ sx2 = NULL
+ }
+ iferr {
+ call dgsrestore (sy2, Memd[nycoeff])
+ } then {
+ call mfree (sy2, TY_STRUCT)
+ sy2 = NULL
+ }
+ } else {
+ sx2 = NULL
+ sy2 = NULL
+ }
+ # Compute the coefficients.
+ call geo_gcoeffd (sx1, sy1, xshift, yshift, a, b, c, d)
+
+ # Compute the reference point.
+ denom = a * d - c * b
+ if (denom == 0.0d0)
+ xref = INDEFD
+ else
+ xref = (b * yshift - d * xshift) / denom
+ if (denom == 0.0d0)
+ yref = INDEFD
+ else
+ yref = (c * xshift - a * yshift) / denom
+
+ # Compute the scale factors.
+ xscale = sqrt (a * a + c * c)
+ yscale = sqrt (b * b + d * d)
+
+ # Compute the rotation angles.
+ if (fp_equald (a, 0.0d0) && fp_equald (c, 0.0d0))
+ xrot = 0.0d0
+ else
+ xrot = RADTODEG (atan2 (-c, a))
+ if (xrot < 0.0d0)
+ xrot = xrot + 360.0d0
+ if (fp_equald (b, 0.0d0) && fp_equald (d, 0.0d0))
+ yrot = 0.0d0
+ else
+ yrot = RADTODEG (atan2 (b, d))
+ if (yrot < 0.0d0)
+ yrot = yrot + 360.0d0
+
+ # Read in up to 10 projection parameters.
+ call salloc (projpar, SZ_FNAME, TY_CHAR)
+ call salloc (projvalue, SZ_FNAME, TY_CHAR)
+ op = strlen (projection) + 1
+ do i = 0, 9 {
+ call sprintf (Memc[projpar], SZ_FNAME, "projp%d")
+ call pargi (i)
+ iferr (call dtgstr (dt, rec, Memc[projpar], Memc[projvalue],
+ SZ_FNAME))
+ next
+ op = op + gstrcpy (" ", projection[op], SZ_LINE - op + 1)
+ op = op + gstrcpy (Memc[projpar], projection[op],
+ SZ_LINE - op + 1)
+ op = op + gstrcpy (" = ", projection[op], SZ_LINE - op + 1)
+ op = op + gstrcpy (Memc[projvalue], projection[op],
+ SZ_LINE - op + 1)
+ }
+
+ call sfree (sp)
+
+ return (OK)
+end
diff --git a/pkg/images/imcoords/src/t_ccstd.x b/pkg/images/imcoords/src/t_ccstd.x
new file mode 100644
index 00000000..d9ce3a6b
--- /dev/null
+++ b/pkg/images/imcoords/src/t_ccstd.x
@@ -0,0 +1,468 @@
+include <fset.h>
+include <ctype.h>
+include <math.h>
+include <pkg/skywcs.h>
+
+
+define MAX_FIELDS 100 # Maximum number of fields in list
+define TABSIZE 8 # Spacing of tab stops
+
+# T_CCSTD -- Transform a list of x and y and RA and DEC coordinates to
+# their polar coordinate equivalents, after appying an optional linear
+# transformation to the x and y side
+
+procedure t_ccstd()
+
+bool forward, polar
+int inlist, outlist, reclist, infd, outfd
+int xcolumn, ycolumn, lngcolumn, latcolumn, lngunits, latunits
+int geometry, min_sigdigits
+pointer sp, infile, outfile, record, str, dt, sx1, sy1, sx2, sy2, coo, mw
+pointer xformat, yformat, lngformat, latformat
+bool clgetb(), streq()
+int fntopnb(), imtopenp(), fntlenb(), imtlen(), fntgfnb(), imtgetim()
+int open(), clgwrd(), clgeti()
+pointer dtmap()
+
+begin
+ # Allocate memory for transformation parameters structure
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (record, SZ_FNAME, TY_CHAR)
+ call salloc (xformat, SZ_FNAME, TY_CHAR)
+ call salloc (yformat, SZ_FNAME, TY_CHAR)
+ call salloc (lngformat, SZ_FNAME, TY_CHAR)
+ call salloc (latformat, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the input and output file lists.
+ call clgstr ("input", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS)
+ call strcpy ("STDIN", Memc[str], SZ_FNAME)
+ inlist = fntopnb(Memc[str], NO)
+ call clgstr ("output", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS)
+ call strcpy ("STDOUT", Memc[str], SZ_FNAME)
+ outlist = fntopnb (Memc[str], NO)
+ call clgstr ("database", Memc[str], SZ_FNAME)
+ if (Memc[str] != EOS) {
+ dt = dtmap (Memc[str], READ_ONLY)
+ reclist = imtopenp ("solutions")
+ geometry = clgwrd ("geometry", Memc[str], SZ_LINE,
+ ",linear,distortion,geometric,")
+ } else {
+ dt = NULL
+ reclist = NULL
+ geometry = 0
+ }
+ forward = clgetb ("forward")
+ polar = clgetb ("polar")
+
+ # Test the input and out file and record lists for validity.
+ if (fntlenb(inlist) <= 0)
+ call error (0, "The input file list is empty")
+ if (fntlenb(outlist) <= 0)
+ call error (0, "The output file list is empty")
+ if (fntlenb(outlist) > 1 && fntlenb(outlist) != fntlenb(inlist))
+ call error (0,
+ "Input and output file lists are not the same length")
+ if (dt != NULL && reclist != NULL) {
+ if (imtlen (reclist) > 1 && imtlen (reclist) != fntlenb (inlist))
+ call error (0,
+ "Input file and record lists are not the same length.")
+ }
+
+ # Get the input file format parameters.
+ xcolumn = clgeti ("xcolumn")
+ ycolumn = clgeti ("ycolumn")
+ lngcolumn = clgeti ("lngcolumn")
+ latcolumn = clgeti ("latcolumn")
+ iferr (lngunits = clgwrd ("lngunits", Memc[str], SZ_LINE,
+ SKY_LNG_UNITLIST))
+ lngunits = 0
+ iferr (latunits = clgwrd ("latunits", Memc[str], SZ_LINE,
+ SKY_LAT_UNITLIST))
+ latunits = 0
+
+ # Get the output file format parameters.
+ call clgstr ("lngformat", Memc[lngformat], SZ_FNAME)
+ call clgstr ("latformat", Memc[latformat], SZ_FNAME)
+ call clgstr ("xformat", Memc[xformat], SZ_FNAME)
+ call clgstr ("yformat", Memc[yformat], SZ_FNAME)
+ min_sigdigits = clgeti ("min_sigdigits")
+
+ # Get the output file name.
+ if (fntgfnb (outlist, Memc[outfile], SZ_FNAME) == EOF)
+ call strcpy ("STDOUT", Memc[outfile], SZ_FNAME)
+ outfd = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+ if (streq (Memc[outfile], "STDOUT") || outfd == STDOUT)
+ call fseti (outfd, F_FLUSHNL, YES)
+
+ # Get the record name.
+ if (reclist == NULL)
+ Memc[record] = EOS
+ else if (imtgetim (reclist, Memc[record], SZ_FNAME) == EOF)
+ Memc[record] = EOS
+
+ # Call procedure to get parameters and fill structure.
+ coo = NULL; sx1 = NULL; sy1 = NULL; sx2 = NULL; sy2 = NULL
+ call cc_init_std (dt, Memc[record], geometry, lngunits,
+ latunits, sx1, sy1, sx2, sy2, mw, coo)
+
+ # While input list is not depleted, open file and transform list.
+ while (fntgfnb (inlist, Memc[infile], SZ_FNAME) != EOF) {
+
+ infd = open (Memc[infile], READ_ONLY, TEXT_FILE)
+
+ # Transform the coordinates.
+ call cc_transform_std (infd, outfd, xcolumn, ycolumn, lngcolumn,
+ latcolumn, lngunits, latunits, Memc[xformat], Memc[yformat],
+ Memc[lngformat], Memc[latformat], min_sigdigits, sx1, sy1, sx2,
+ sy2, mw, coo, forward, polar)
+
+ # Do not get a new output file name if there is not output
+ # file list or if only one output file was specified.
+ # Otherwise fetch the new name.
+ if (fntlenb(outlist) > 1) {
+ call close (outfd)
+ if (fntgfnb (outlist, Memc[outfile], SZ_FNAME) != EOF)
+ outfd = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+ if (streq (Memc[outfile], "STDOUT") || outfd == STDOUT)
+ call fseti (outfd, F_FLUSHNL, YES)
+ }
+
+ call close (infd)
+
+ # Do not reset the transformation if there is no record list
+ # or only one record is specified. Otherwise fetch the next
+ # record name.
+ if (reclist != NULL && imtlen (reclist) > 1) {
+ if (imtgetim (reclist, Memc[record], SZ_FNAME) != EOF) {
+ call cc_free_std (sx1, sy1, sx2, sy2, mw, coo)
+ call cc_init_std (dt, Memc[record], geometry,
+ lngunits, latunits, sx1, sy1, sx2, sy2, mw, coo)
+ }
+ }
+ }
+
+ # Free the surface descriptors.
+ call cc_free_std (sx1, sy1, sx2, sy2, mw, coo)
+
+ # Close up file and record templates.
+ if (dt != NULL)
+ call dtunmap (dt)
+ call close (outfd)
+ call fntclsb (inlist)
+ call fntclsb (outlist)
+ if (reclist != NULL)
+ call imtclose (reclist)
+ call sfree (sp)
+
+end
+
+
+# CC_TRANSFORM_STD -- This procedure is called once for each file in the
+# input list. For each line in the input file that isn't blank or comment,
+# the line is transformed. Blank and comment lines are output unaltered.
+
+procedure cc_transform_std (infd, outfd, xfield, yfield, lngfield, latfield,
+ lngunits, latunits, xformat, yformat, lngformat, latformat,
+ min_sigdigits, sx1, sy1, sx2, sy2, mw, coo, forward, polar)
+
+int infd #I the input file descriptor
+int outfd #I the output file descriptor
+int xfield #I the x column number
+int yfield #I the y column number
+int lngfield #I the ra / longitude column number
+int latfield #I the dec / latitude column number
+int lngunits #I the ra / longitude units
+int latunits #I the dec / latitude units
+char xformat[ARB] #I output format of the r / x coordinate
+char yformat[ARB] #I output format of the t / y coordinate
+char lngformat[ARB] #I output format of the r / longitude coordinate
+char latformat[ARB] #I output format of the t / latitude coordinate
+int min_sigdigits #I the minimum number of digits to be output
+pointer sx1, sy1 #I pointers to the linear x and y surfaces
+pointer sx2, sy2 #I pointers to the x and y distortion surfaces
+pointer mw #I pointer to the mwcs structure
+pointer coo #I pointer to the celestial coordinate structure
+bool forward #I Is the transform in the forward direction ?
+bool polar #I Polar standard coordinates ?
+
+double xd, yd, lngd, latd, txd, tyd, tlngd, tlatd
+int max_fields, nline, nfields, nchars
+int offset, tlngunits, tlatunits
+pointer sp, inbuf, linebuf, field_pos, outbuf, ip, ct
+pointer vfields, values, nsdigits, vformats
+int getline(), li_get_numd(), sk_stati()
+pointer mw_sctran()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (linebuf, SZ_LINE, TY_CHAR)
+ call salloc (field_pos, MAX_FIELDS, TY_INT)
+ call salloc (outbuf, SZ_LINE, TY_CHAR)
+ call salloc (vfields, 4, TY_INT)
+ call salloc (values, 4, TY_DOUBLE)
+ call salloc (nsdigits, 4, TY_INT)
+ call salloc (vformats, (SZ_FNAME + 1) * 4, TY_CHAR)
+
+ # Determine the longitude and latitude units.
+ if (lngunits <= 0) {
+ if (coo == NULL)
+ tlngunits = SKY_HOURS
+ else
+ tlngunits = sk_stati (coo, S_NLNGUNITS)
+ } else
+ tlngunits = lngunits
+ if (latunits <= 0) {
+ if (coo == NULL)
+ tlatunits = SKY_DEGREES
+ else
+ tlatunits = sk_stati (coo, S_NLATUNITS)
+ } else
+ tlatunits = latunits
+
+ # Set the output fields.
+ Memi[vfields] = xfield
+ Memi[vfields+1] = yfield
+ Memi[vfields+2] = lngfield
+ Memi[vfields+3] = latfield
+
+ # If the formats are undefined set suitable default formats.
+ if (lngformat[1] == EOS) {
+ if (forward)
+ call strcpy ("%10.3f", Memc[vformats+2*(SZ_FNAME+1)], SZ_FNAME)
+ else {
+ switch (tlngunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.2h", Memc[vformats+2*(SZ_FNAME+1)],
+ SZ_FNAME)
+ case SKY_DEGREES:
+ call strcpy ("%11.1h", Memc[vformats+2*(SZ_FNAME+1)],
+ SZ_FNAME)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", Memc[vformats+2*(SZ_FNAME+1)],
+ SZ_FNAME)
+ default:
+ call strcpy ("%10.3f", Memc[vformats+2*(SZ_FNAME+1)],
+ SZ_FNAME)
+ }
+ }
+ } else
+ call strcpy (lngformat, Memc[vformats+2*(SZ_FNAME+1)], SZ_FNAME)
+
+ if (latformat[1] == EOS) {
+ if (forward)
+ call strcpy ("%10.3f", Memc[vformats+3*(SZ_FNAME+1)], SZ_FNAME)
+ else {
+ switch (tlatunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.2h", Memc[vformats+3*(SZ_FNAME+1)],
+ SZ_FNAME)
+ case SKY_DEGREES:
+ call strcpy ("%11.1h", Memc[vformats+3*(SZ_FNAME+1)],
+ SZ_FNAME)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", Memc[vformats+3*(SZ_FNAME+1)],
+ SZ_FNAME)
+ default:
+ call strcpy ("%10.3f", Memc[vformats+3*(SZ_FNAME+1)],
+ SZ_FNAME)
+ }
+ }
+ } else
+ call strcpy (latformat, Memc[vformats+3*(SZ_FNAME+1)], SZ_FNAME)
+
+ if (xformat[1] == EOS)
+ call strcpy ("%10.3f", Memc[vformats], SZ_FNAME)
+ else
+ call strcpy (xformat, Memc[vformats], SZ_FNAME)
+ if (yformat[1] == EOS)
+ call strcpy ("%10.3f", Memc[vformats+(SZ_FNAME+1)], SZ_FNAME)
+ else
+ call strcpy (yformat, Memc[vformats+(SZ_FNAME+1)], SZ_FNAME)
+
+
+ # If the transformation can be represented by mwcs then compile the
+ # appropriate transform. Other wise use the surface fitting code
+ # to do the transformation.
+ if (mw != NULL) {
+ if (forward)
+ ct = mw_sctran (mw, "world", "logical", 03B)
+ else
+ ct = mw_sctran (mw, "logical", "world", 03B)
+ }
+
+ max_fields = MAX_FIELDS
+ for (nline=1; getline (infd, Memc[inbuf]) != EOF; nline = nline + 1) {
+
+ for (ip=inbuf; IS_WHITE(Memc[ip]); ip=ip+1)
+ ;
+
+ if (Memc[ip] == '#') {
+ # Pass comment lines on to the output unchanged.
+ call putline (outfd, Memc[inbuf])
+ next
+ } else if (Memc[ip] == '\n' || Memc[ip] == EOS) {
+ # Blank lines too.
+ call putline (outfd, Memc[inbuf])
+ next
+ }
+
+ # If the transformation is undefined then pass the line on
+ # undisturbed.
+ if (mw == NULL) {
+ call putline (outfd, Memc[inbuf])
+ next
+ }
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[linebuf], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[linebuf], Memi[field_pos], max_fields,
+ nfields)
+
+ # Check that all the data is present.
+ if (lngfield > nfields || latfield > nfields || xfield > nfields ||
+ yfield > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Not enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ # Read the longitude / latitude or rstd / thetastd coordinates.
+ offset = Memi[field_pos+lngfield-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], lngd,
+ Memi[nsdigits+2])
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad lng / xi value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ offset = Memi[field_pos+latfield-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], latd,
+ Memi[nsdigits+3])
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad lat / eta value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ # Read the x and y or r and theta coordinates.
+ offset = Memi[field_pos+xfield-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], xd, Memi[nsdigits])
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad x / r value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+ offset = Memi[field_pos+yfield-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], yd, Memi[nsdigits+1])
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad y / theta value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ # Transform the longitude / latitude coordinates in lngunits /
+ # latunits to / from the xi / eta coordinates in arcseconds, and
+ # transform the x and y coordinates to or from the r and theta
+ # coordinates.
+ if (forward) {
+ switch (tlngunits) {
+ case SKY_RADIANS:
+ tlngd = RADTODEG(lngd)
+ case SKY_HOURS:
+ tlngd = 15.0d0 * lngd
+ default:
+ tlngd = lngd
+ }
+ switch (tlatunits) {
+ case SKY_RADIANS:
+ tlatd = RADTODEG(latd)
+ case SKY_HOURS:
+ tlatd = 15.0d0 * latd
+ default:
+ tlatd = latd
+ }
+ txd = xd
+ tyd = yd
+ } else if (polar) {
+ tlngd = lngd * cos (DEGTORAD(latd)) / 3600.0d0
+ tlatd = lngd * sin (DEGTORAD(latd)) / 3600.0d0
+ txd = xd * cos (DEGTORAD(yd))
+ tyd = xd * sin (DEGTORAD(yd))
+ } else {
+ tlngd = lngd / 3600.0d0
+ tlatd = latd / 3600.0d0
+ txd = xd
+ tyd = yd
+ }
+ call mw_c2trand (ct, tlngd, tlatd, lngd, latd)
+ call cc_do_std (txd, tyd, xd, yd, sx1, sy1, sx2, sy2, forward)
+ if (! forward) {
+ switch (tlngunits) {
+ case SKY_RADIANS:
+ Memd[values+2] = DEGTORAD(lngd)
+ case SKY_HOURS:
+ Memd[values+2] = lngd / 15.0d0
+ default:
+ Memd[values+2] = lngd
+ }
+ switch (tlatunits) {
+ case SKY_RADIANS:
+ Memd[values+3] = DEGTORAD(latd)
+ case SKY_HOURS:
+ Memd[values+3] = latd / 15.0d0
+ default:
+ Memd[values+3] = latd
+ }
+ Memd[values] = xd
+ Memd[values+1] = yd
+ } else if (polar) {
+ Memd[values] = sqrt (xd * xd + yd * yd)
+ Memd[values+1] = RADTODEG(atan2 (yd, xd))
+ if (Memd[values+1] < 0.0d0)
+ Memd[values+1] = Memd[values+1] + 360.0d0
+ Memd[values+2] = sqrt (lngd * lngd + latd * latd) * 3600.0d0
+ Memd[values+3] = RADTODEG (atan2 (latd, lngd))
+ if (Memd[values+3] < 0.0d0)
+ Memd[values+3] = Memd[values+3] + 360.0d0
+ } else {
+ Memd[values] = xd
+ Memd[values+1] = yd
+ Memd[values+2] = lngd * 3600.0d0
+ Memd[values+3] = latd * 3600.0d0
+ }
+
+ # Format the output line.
+ call li_npack_lined (Memc[linebuf], Memc[outbuf], SZ_LINE,
+ Memi[field_pos], nfields, Memi[vfields], Memd[values],
+ Memi[nsdigits], 4, Memc[vformats], SZ_FNAME, min_sigdigits)
+
+ call putline (outfd, Memc[outbuf])
+ }
+
+ if (ct != NULL)
+ call mw_ctfree (ct)
+
+ call sfree (sp)
+end
diff --git a/pkg/images/imcoords/src/t_cctran.x b/pkg/images/imcoords/src/t_cctran.x
new file mode 100644
index 00000000..6efeaf35
--- /dev/null
+++ b/pkg/images/imcoords/src/t_cctran.x
@@ -0,0 +1,374 @@
+include <fset.h>
+include <ctype.h>
+include <math.h>
+include <pkg/skywcs.h>
+
+
+define MAX_FIELDS 100 # Maximum number of fields in list
+define TABSIZE 8 # Spacing of tab stops
+
+# T_CCTRAN -- Transform a list of x and y coordinates to RA nad DEC or vice
+# versa using the celestial coordinate transformation computed by the CCMAP
+# task.
+
+procedure t_cctran()
+
+bool forward
+int inlist, outlist, reclist, geometry, xcolumn, ycolumn, min_sigdigits
+int infd, outfd, lngunits, latunits
+pointer sp, infile, outfile, record, xformat, yformat, str, dt
+pointer sx1, sy1, sx2, sy2, coo, mw
+bool clgetb(), streq()
+int fntopnb(), imtopenp(), fntlenb(), fntgfnb(), clgwrd(), clgeti()
+int open(), imtgetim (), imtlen()
+pointer dtmap()
+
+begin
+ # Allocate memory for transformation parameters structure
+ call smark (sp)
+ call salloc (infile, SZ_FNAME, TY_CHAR)
+ call salloc (outfile, SZ_FNAME, TY_CHAR)
+ call salloc (record, SZ_FNAME, TY_CHAR)
+ call salloc (xformat, SZ_FNAME, TY_CHAR)
+ call salloc (yformat, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the input and output file lists.
+ call clgstr ("input", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS)
+ call strcpy ("STDIN", Memc[str], SZ_FNAME)
+ inlist = fntopnb(Memc[str], NO)
+ call clgstr ("output", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS)
+ call strcpy ("STDOUT", Memc[str], SZ_FNAME)
+ outlist = fntopnb (Memc[str], NO)
+ call clgstr ("database", Memc[str], SZ_FNAME)
+ if (Memc[str] != EOS) {
+ dt = dtmap (Memc[str], READ_ONLY)
+ reclist = imtopenp ("solution")
+ } else {
+ dt = NULL
+ reclist = NULL
+ }
+
+ # Test the input and out file and record lists for validity.
+ if (fntlenb(inlist) <= 0)
+ call error (0, "The input file list is empty")
+ if (fntlenb(outlist) <= 0)
+ call error (0, "The output file list is empty")
+ if (fntlenb(outlist) > 1 && fntlenb(outlist) != fntlenb(inlist))
+ call error (0,
+ "Input and output file lists are not the same length")
+ if (dt != NULL && reclist != NULL) {
+ if (imtlen (reclist) > 1 && imtlen (reclist) != fntlenb (inlist))
+ call error (0,
+ "Input file and record lists are not the same length.")
+ }
+
+ # Get the fitting geometry.
+ geometry = clgwrd ("geometry", Memc[str], SZ_LINE,
+ ",linear,distortion,geometric,")
+ forward = clgetb ("forward")
+
+ # Get the input and output file parameters.
+ iferr (lngunits = clgwrd ("lngunits", Memc[str], SZ_LINE,
+ SKY_LNG_UNITLIST))
+ lngunits = 0
+ iferr (latunits = clgwrd ("latunits", Memc[str], SZ_LINE,
+ SKY_LAT_UNITLIST))
+ latunits = 0
+ xcolumn = clgeti ("xcolumn")
+ ycolumn = clgeti ("ycolumn")
+ call clgstr ("lngformat", Memc[xformat], SZ_FNAME)
+ call clgstr ("latformat", Memc[yformat], SZ_FNAME)
+ min_sigdigits = clgeti ("min_sigdigits")
+
+ # Get the output file name.
+ if (fntgfnb (outlist, Memc[outfile], SZ_FNAME) == EOF)
+ call strcpy ("STDOUT", Memc[outfile], SZ_FNAME)
+ outfd = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+ if (streq (Memc[outfile], "STDOUT") || outfd == STDOUT)
+ call fseti (outfd, F_FLUSHNL, YES)
+
+ # Get the record name.
+ if (reclist == NULL)
+ Memc[record] = EOS
+ else if (imtgetim (reclist, Memc[record], SZ_FNAME) == EOF)
+ Memc[record] = EOS
+
+ # Call procedure to get parameters and fill structure.
+ coo = NULL; sx1 = NULL; sy1 = NULL; sx2 = NULL; sy2 = NULL
+ call cc_init_transform (dt, Memc[record], geometry, lngunits,
+ latunits, sx1, sy1, sx2, sy2, mw, coo)
+
+ # While input list is not depleted, open file and transform list.
+ while (fntgfnb (inlist, Memc[infile], SZ_FNAME) != EOF) {
+
+ infd = open (Memc[infile], READ_ONLY, TEXT_FILE)
+
+ # Transform the coordinates.
+ call cc_transform_file (infd, outfd, xcolumn, ycolumn, lngunits,
+ latunits, Memc[xformat], Memc[yformat], min_sigdigits, sx1,
+ sy1, sx2, sy2, mw, coo, forward)
+
+ # Do not get a new output file name if there is not output
+ # file list or if only one output file was specified.
+ # Otherwise fetch the new name.
+ if (fntlenb(outlist) > 1) {
+ call close (outfd)
+ if (fntgfnb (outlist, Memc[outfile], SZ_FNAME) != EOF)
+ outfd = open (Memc[outfile], NEW_FILE, TEXT_FILE)
+ if (streq (Memc[outfile], "STDOUT") || outfd == STDOUT)
+ call fseti (outfd, F_FLUSHNL, YES)
+ }
+
+ call close (infd)
+
+ # Do not reset the transformation if there is no record list
+ # or only one record is specified. Otherwise fetch the next
+ # record name.
+ if (reclist != NULL && imtlen (reclist) > 1) {
+ if (imtgetim (reclist, Memc[record], SZ_FNAME) != EOF) {
+ call cc_free_transform (sx1, sy1, sx2, sy2, mw, coo)
+ call cc_init_transform (dt, Memc[record], geometry,
+ lngunits, latunits, sx1, sy1, sx2, sy2, mw, coo)
+ }
+ }
+ }
+
+ # Free the surface descriptors.
+ call cc_free_transform (sx1, sy1, sx2, sy2, mw, coo)
+
+ # Close up file and record templates.
+ if (dt != NULL)
+ call dtunmap (dt)
+ call close (outfd)
+ call fntclsb (inlist)
+ call fntclsb (outlist)
+ if (reclist != NULL)
+ call imtclose (reclist)
+ call sfree (sp)
+
+end
+
+
+# CC_TRANSFORM_FILE -- This procedure is called once for each file
+# in the input list. For each line in the input file that isn't
+# blank or comment, the line is transformed. Blank and comment
+# lines are output unaltered.
+
+procedure cc_transform_file (infd, outfd, xfield, yfield, lngunits,
+ latunits, xformat, yformat, min_sigdigits, sx1, sy1, sx2, sy2,
+ mw, coo, forward)
+
+int infd #I the input file descriptor
+int outfd #I the output file descriptor
+int xfield #I the x column number
+int yfield #I the y column number
+int lngunits #I the ra / longitude units
+int latunits #I the dec / latitude units
+char xformat[ARB] #I output format of the x coordinate
+char yformat[ARB] #I output format of the y coordinate
+int min_sigdigits #I the minimum number of digits to be output
+pointer sx1, sy1 #I pointers to the linear x and y surfaces
+pointer sx2, sy2 #I pointers to the x and y distortion surfaces
+pointer mw #I pointer to the mwcs structure
+pointer coo #I pointer to the celestial coordinate structure
+bool forward #I forwards transform ?
+
+double xd, yd, xtd, ytd
+int max_fields, nline, nfields, nchars, nsdig_x, nsdig_y, offset
+int tlngunits, tlatunits
+pointer sp, inbuf, linebuf, field_pos, outbuf, ip, ct, txformat, tyformat
+int getline(), li_get_numd(), sk_stati()
+pointer mw_sctran()
+
+begin
+ # Allocate some working space.
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (linebuf, SZ_LINE, TY_CHAR)
+ call salloc (field_pos, MAX_FIELDS, TY_INT)
+ call salloc (outbuf, SZ_LINE, TY_CHAR)
+ call salloc (txformat, SZ_LINE, TY_CHAR)
+ call salloc (tyformat, SZ_LINE, TY_CHAR)
+
+ # Determine the units.
+ if (lngunits <= 0) {
+ if (coo == NULL)
+ tlngunits = SKY_HOURS
+ else
+ tlngunits = sk_stati (coo, S_NLNGUNITS)
+ } else
+ tlngunits = lngunits
+ if (latunits <= 0) {
+ if (coo == NULL)
+ tlatunits = SKY_DEGREES
+ else
+ tlatunits = sk_stati (coo, S_NLATUNITS)
+ } else
+ tlatunits = latunits
+
+ # If the formats are undefined set suitable default formats.
+ if (xformat[1] == EOS) {
+ if (! forward)
+ call strcpy ("%10.3f", Memc[txformat], SZ_FNAME)
+ else {
+ switch (tlngunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.2h", Memc[txformat], SZ_FNAME)
+ case SKY_DEGREES:
+ call strcpy ("%11.1h", Memc[txformat], SZ_FNAME)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", Memc[txformat], SZ_FNAME)
+ default:
+ call strcpy ("%10.3f", Memc[txformat], SZ_FNAME)
+ }
+ }
+ } else
+ call strcpy (xformat, Memc[txformat], SZ_FNAME)
+
+ if (yformat[1] == EOS) {
+ if (! forward)
+ call strcpy ("%10.3f", Memc[tyformat], SZ_FNAME)
+ else {
+ switch (tlatunits) {
+ case SKY_HOURS:
+ call strcpy ("%12.2h", Memc[tyformat], SZ_FNAME)
+ case SKY_DEGREES:
+ call strcpy ("%11.1h", Memc[tyformat], SZ_FNAME)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", Memc[tyformat], SZ_FNAME)
+ default:
+ call strcpy ("%10.3f", Memc[tyformat], SZ_FNAME)
+ }
+ }
+ } else
+ call strcpy (yformat, Memc[tyformat], SZ_FNAME)
+
+ # If the transformation can be represented by mwcs then compile the
+ # appropriate transform. Other wise use the surface fitting code
+ # to do the transformation.
+ if (mw != NULL) {
+ if (forward)
+ ct = mw_sctran (mw, "logical", "world", 03B)
+ else
+ ct = mw_sctran (mw, "world", "logical", 03B)
+ }
+
+ max_fields = MAX_FIELDS
+ for (nline=1; getline (infd, Memc[inbuf]) != EOF; nline = nline + 1) {
+
+ for (ip=inbuf; IS_WHITE(Memc[ip]); ip=ip+1)
+ ;
+
+ if (Memc[ip] == '#') {
+ # Pass comment lines on to the output unchanged.
+ call putline (outfd, Memc[inbuf])
+ next
+ } else if (Memc[ip] == '\n' || Memc[ip] == EOS) {
+ # Blank lines too.
+ call putline (outfd, Memc[inbuf])
+ next
+ }
+
+ # If the transformation is undefined then pass the line on
+ # undisturbed.
+ if (mw == NULL) {
+ call putline (outfd, Memc[inbuf])
+ next
+ }
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[linebuf], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[linebuf], Memi[field_pos], max_fields,
+ nfields)
+
+ if (xfield > nfields || yfield > nfields) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Not enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ offset = Memi[field_pos+xfield-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], xd, nsdig_x)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad x value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ offset = Memi[field_pos+yfield-1]
+ nchars = li_get_numd (Memc[linebuf+offset-1], yd, nsdig_y)
+ if (nchars == 0) {
+ call fstats (infd, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("Bad y value in file '%s' at line %d:\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (outfd, Memc[linebuf])
+ next
+ }
+
+ # Transform the coordinates.
+ if (! forward) {
+ switch (tlngunits) {
+ case SKY_RADIANS:
+ xd = RADTODEG(xd)
+ case SKY_HOURS:
+ xd = 15.0d0 * xd
+ default:
+ ;
+ }
+ switch (tlatunits) {
+ case SKY_RADIANS:
+ yd = RADTODEG(yd)
+ case SKY_HOURS:
+ yd = 15.0d0 * yd
+ default:
+ ;
+ }
+ }
+ if (sx2 != NULL || sy2 != NULL)
+ call cc_do_transform (xd, yd, xtd, ytd, ct, sx1, sy1,
+ sx2, sy2, forward)
+ else
+ call mw_c2trand (ct, xd, yd, xtd, ytd)
+ if (forward) {
+ switch (tlngunits) {
+ case SKY_RADIANS:
+ xtd = DEGTORAD(xtd)
+ case SKY_HOURS:
+ xtd = xtd / 15.0d0
+ default:
+ ;
+ }
+ switch (tlatunits) {
+ case SKY_RADIANS:
+ ytd = DEGTORAD(ytd)
+ case SKY_HOURS:
+ ytd = ytd / 15.0d0
+ default:
+ ;
+ }
+ }
+
+ # Format the output line.
+ call li_pack_lined (Memc[linebuf], Memc[outbuf], SZ_LINE,
+ Memi[field_pos], nfields, xfield, yfield, xtd, ytd,
+ Memc[txformat], Memc[tyformat], nsdig_x, nsdig_y, min_sigdigits)
+
+ call putline (outfd, Memc[outbuf])
+ }
+
+ if (ct != NULL)
+ call mw_ctfree (ct)
+
+ call sfree (sp)
+end
+
diff --git a/pkg/images/imcoords/src/t_ccxymatch.x b/pkg/images/imcoords/src/t_ccxymatch.x
new file mode 100644
index 00000000..ea34b6c0
--- /dev/null
+++ b/pkg/images/imcoords/src/t_ccxymatch.x
@@ -0,0 +1,576 @@
+include <fset.h>
+include <pkg/skywcs.h>
+include "../../lib/xyxymatch.h"
+
+# T_CCXYMATCH -- This task computes the intersection of a set of pixel
+# coordinate lists with a reference celestial coordinate list. The output is
+# the set of objects common to both lists. In its simplest form CCXYMATCH
+# uses a matching tolerance to generate the common list. Alternatively
+# CCXYMATCH can use coordinate transformation information derived from the
+# positions of one to three stars common to both lists, a sorting algorithm,
+# and a matching tolerance to generate the common list. A more sophisticated
+# pattern matching algorithm is also available which requires no coordinate
+# transformation input from the user but is expensive computationally.
+
+procedure t_ccxymatch()
+
+bool verbose
+double lngin, latin, tlngin, tlatin
+int ilist, rlist, olist, xcol, ycol, lngcol, latcol, lngunits, latunits
+int match, maxntriangles, nreject, rfd, rpfd, ifd, ofd, pfd
+int ntrefstars, nreftie, nrefstars, nrmaxtri, nreftri, nintie, ntie
+int ntliststars, nliststars, ninter, ninmaxtri, nintri, proj
+pointer sp, inname, refname, outname, refpoints, xreftie, yreftie
+pointer xintie, yintie, coeff, projection, str
+pointer xformat, yformat, lngformat, latformat
+pointer lngref, latref, xref, yref, rlineno, rsindex, reftri, reftrirat
+pointer xtrans, ytrans, listindex, xlist, ylist, ilineno, intri, intrirat
+real tolerance, ptolerance, xin, yin, xmag, ymag, xrot, yrot
+real pseparation, separation, ratio
+
+bool clgetb()
+double clgetd()
+int fstati(), clpopnu(), clplen(), clgeti(), clgwrd(), open(), clgfil()
+int rg_getrefcel(), rg_rdlli(), rg_sort(), rg_factorial(), rg_triangle()
+int rg_getreftie(), rg_lincoeff(), rg_rdxyi(), rg_llintersect()
+int rg_match(), rg_mlincoeff(), cc_rdproj(), strdic()
+real clgetr()
+errchk open()
+
+begin
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (inname, SZ_FNAME, TY_CHAR)
+ call salloc (refname, SZ_FNAME, TY_CHAR)
+ call salloc (outname, SZ_FNAME, TY_CHAR)
+ call salloc (refpoints, SZ_FNAME, TY_CHAR)
+ call salloc (xreftie, MAX_NTIE, TY_REAL)
+ call salloc (yreftie, MAX_NTIE, TY_REAL)
+ call salloc (xintie, MAX_NTIE, TY_REAL)
+ call salloc (yintie, MAX_NTIE, TY_REAL)
+ call salloc (coeff, MAX_NCOEFF, TY_REAL)
+ call salloc (projection, SZ_LINE, TY_CHAR)
+ call salloc (xformat, SZ_FNAME, TY_CHAR)
+ call salloc (yformat, SZ_FNAME, TY_CHAR)
+ call salloc (lngformat, SZ_FNAME, TY_CHAR)
+ call salloc (latformat, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Get the input, output, and reference lists.
+ ilist = clpopnu ("input")
+ rlist = clpopnu ("reference")
+ olist = clpopnu ("output")
+ tolerance = clgetr ("tolerance")
+ match = clgwrd ("matching", Memc[str], SZ_LINE, RG_MATCHSTR)
+ if (match == RG_TRIANGLES)
+ ptolerance = clgetr ("ptolerance")
+ else
+ ptolerance = tolerance
+
+ call clgstr ("refpoints", Memc[refpoints], SZ_FNAME)
+
+ # Check the input and output file lengths.
+ if (clplen (rlist) > 1 && clplen (rlist) != clplen (ilist))
+ call error (0,
+ "The number of input and reference lists are not the same")
+ if (clplen (ilist) != clplen (olist))
+ call error (0,
+ "The number of input and output lists are not the same")
+
+ xcol = clgeti ("xcolumn")
+ ycol = clgeti ("ycolumn")
+ lngcol = clgeti ("lngcolumn")
+ latcol = clgeti ("latcolumn")
+ lngunits = clgwrd ("lngunits", Memc[str], SZ_FNAME, SKY_LNG_UNITLIST)
+ latunits = clgwrd ("latunits", Memc[str], SZ_FNAME, SKY_LAT_UNITLIST)
+
+ call clgstr ("projection", Memc[projection], SZ_LINE)
+ iferr {
+ pfd = open (Memc[projection], READ_ONLY, TEXT_FILE)
+ } then {
+ proj = strdic (Memc[projection], Memc[projection], SZ_LINE,
+ WTYPE_LIST)
+ if (proj <= 0 || proj == WTYPE_LIN)
+ Memc[projection] = EOS
+ } else {
+ proj = cc_rdproj (pfd, Memc[projection], SZ_LINE)
+ call close (pfd)
+ }
+
+ # Get the matching parameters.
+ xin = clgetr ("xin")
+ if (IS_INDEFR(xin))
+ xin = 0.0
+ yin = clgetr ("yin")
+ if (IS_INDEFR(yin))
+ yin = 0.0
+ xmag = clgetr ("xmag")
+ if (IS_INDEFR(xmag))
+ xmag = 1.0
+ ymag = clgetr ("ymag")
+ if (IS_INDEFR(ymag))
+ ymag = 1.0
+ xrot = clgetr ("xrotation")
+ if (IS_INDEFR(xrot))
+ xrot = 0.0
+ yrot = clgetr ("yrotation")
+ if (IS_INDEFR(yrot))
+ yrot = 0.0
+ lngin = clgetd ("lngref")
+ latin = clgetd ("latref")
+
+ # Get the algorithm parameters.
+ pseparation = clgetr ("pseparation")
+ separation = clgetr ("separation")
+ maxntriangles = clgeti ("nmatch")
+ ratio = clgetr ("ratio")
+ nreject = clgeti ("nreject")
+
+ # Get the output formatting parameters.
+ call clgstr ("xformat", Memc[xformat], SZ_FNAME)
+ call clgstr ("yformat", Memc[yformat], SZ_FNAME)
+ call clgstr ("lngformat", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS) {
+ switch (lngunits) {
+ case SKY_HOURS, SKY_DEGREES:
+ call strcpy ("%13.3h", Memc[lngformat], SZ_FNAME)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", Memc[lngformat], SZ_FNAME)
+ default:
+ call strcpy ("%10.3f", Memc[lngformat], SZ_FNAME)
+ }
+ } else
+ call strcpy (Memc[str], Memc[lngformat], SZ_FNAME)
+ call clgstr ("latformat", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS) {
+ switch (latunits) {
+ case SKY_HOURS, SKY_DEGREES:
+ call strcpy ("%13.2h", Memc[latformat], SZ_FNAME)
+ case SKY_RADIANS:
+ call strcpy ("%13.7g", Memc[latformat], SZ_FNAME)
+ default:
+ call strcpy ("%10.3f", Memc[latformat], SZ_FNAME)
+ }
+ } else
+ call strcpy (Memc[str], Memc[latformat], SZ_FNAME)
+
+ verbose = clgetb ("verbose")
+
+ # Open the reference list file if any.
+ rfd = NULL
+ if (Memc[refpoints] == EOS)
+ rpfd = NULL
+ else
+ rpfd = open (Memc[refpoints], READ_ONLY, TEXT_FILE)
+
+ # Initialize.
+ lngref = NULL
+ latref = NULL
+ xref = NULL
+ yref = NULL
+ rsindex = NULL
+ rlineno = NULL
+
+ # Loop over the input lists.
+ while (clgfil (ilist, Memc[inname], SZ_FNAME) != EOF &&
+ clgfil (olist, Memc[outname], SZ_FNAME) != EOF) {
+
+ # Open the input list.
+ ifd = open (Memc[inname], READ_ONLY, TEXT_FILE)
+
+ # Open the output list.
+ ofd = open (Memc[outname], NEW_FILE, TEXT_FILE)
+
+ # Open the reference list and get the coordinates.
+ while (clgfil (rlist, Memc[refname], SZ_FNAME) != EOF) {
+
+ # Open the reference file.
+ if (rfd != NULL)
+ call close (rfd)
+ rfd = open (Memc[refname], READ_ONLY, TEXT_FILE)
+
+ # Read the reference data.
+ if (lngref != NULL)
+ call mfree (lngref, TY_DOUBLE)
+ if (latref != NULL)
+ call mfree (latref, TY_DOUBLE)
+ if (xref != NULL)
+ call mfree (xref, TY_REAL)
+ if (yref != NULL)
+ call mfree (yref, TY_REAL)
+ if (rlineno != NULL)
+ call mfree (rlineno, TY_INT)
+ if (rsindex != NULL)
+ call mfree (rsindex, TY_INT)
+ ntrefstars = rg_rdlli (rfd, lngref, latref, xref, yref, rlineno,
+ tlngin, tlatin, lngcol, latcol, Memc[projection], lngin,
+ latin, lngunits, latunits)
+
+ # Prepare the reference list for the merge algorithm. If a tie
+ # point matching algorithm is selected, sort the list in the
+ # y and then the x coordinate and remove coincident points.
+ # If the pattern matching algorithm is used then construct the
+ # triangles used for matching and sort them in order of
+ # increasing ratio.
+
+ call malloc (rsindex, ntrefstars, TY_INT)
+ nrefstars = rg_sort (Memr[xref], Memr[yref], Memi[rsindex],
+ ntrefstars, separation, YES, YES)
+ if (match != RG_TRIANGLES) {
+ reftri = NULL
+ reftrirat = NULL
+ nreftri = nrefstars
+ } else if (nrefstars > 2) {
+ nrmaxtri = rg_factorial (min (nrefstars, maxntriangles), 3)
+ call calloc (reftri, SZ_TRIINDEX * nrmaxtri, TY_INT)
+ call calloc (reftrirat, SZ_TRIPAR * nrmaxtri, TY_REAL)
+ nreftri = rg_triangle (Memr[xref], Memr[yref],
+ Memi[rsindex], nrefstars, Memi[reftri],
+ Memr[reftrirat], nrmaxtri, maxntriangles,
+ tolerance, ratio)
+ } else {
+ nreftri = 0
+ reftri = NULL
+ reftrirat = NULL
+ }
+
+
+ # Fetch the reference tie points if any.
+ if (rpfd != NULL)
+ nreftie = rg_getrefcel (rpfd, Memr[xreftie], Memr[yreftie],
+ 3, Memc[projection], tlngin, tlatin, lngunits, latunits,
+ RG_REFFILE)
+ else
+ nreftie = 0
+
+ break
+ }
+
+ # Fetch the input tie points and compute the coefficients.
+ if (rpfd != NULL)
+ nintie = rg_getreftie (rpfd, Memr[xintie],
+ Memr[yintie], nreftie, RG_INFILE, false)
+ else
+ nintie = 0
+ ntie = min (nreftie, nintie)
+ if (ntie <= 0)
+ call rg_lmkcoeff (xin, yin, xmag, ymag, xrot, yrot,
+ 0.0, 0.0, Memr[coeff], MAX_NCOEFF)
+ else if (rg_lincoeff (Memr[xreftie], Memr[yreftie],
+ Memr[xintie], Memr[yintie], ntie, Memr[coeff],
+ MAX_NCOEFF) == ERR)
+ call rg_lmkcoeff (xin, yin, xmag, ymag, xrot, yrot,
+ 0.0, 0.0, Memr[coeff], MAX_NCOEFF)
+
+ # Print the header.
+ if (verbose) {
+ call printf ("\nInput: %s Reference: %s ")
+ call pargstr (Memc[inname])
+ call pargstr (Memc[refname])
+ call printf ("Number of tie points: %d\n")
+ call pargi (ntie)
+ }
+ call fprintf (ofd, "\n# Input: %s Reference: %s ")
+ call pargstr (Memc[inname])
+ call pargstr (Memc[refname])
+ call fprintf (ofd, "Number of tie points: %d\n")
+ call pargi (ntie)
+
+ # Print the coordinate transformation information.
+ if (verbose)
+ call rg_plincoeff (" xi", " eta", Memr[xreftie],
+ Memr[yreftie], Memr[xintie], Memr[yintie], ntie,
+ Memr[coeff], MAX_NCOEFF)
+ call rg_wlincoeff (ofd, " xi", " eta", Memr[xreftie],
+ Memr[yreftie], Memr[xintie], Memr[yintie], ntie,
+ Memr[coeff], MAX_NCOEFF)
+
+ # Read in the input list.
+ xtrans = NULL
+ ytrans = NULL
+ listindex = NULL
+ ntliststars = rg_rdxyi (ifd, xlist, ylist, ilineno, xcol, ycol)
+
+ # Compute the intersection of the two lists using either an
+ # algorithm depending on common tie points or on a more
+ # sophisticated pattern matching algorithm.
+
+ if (ntrefstars <= 0) {
+ if (verbose)
+ call printf (" The reference coordinate list is empty\n")
+ ninter = 0
+ } else if (ntliststars <= 0) {
+ if (verbose)
+ call printf (" The input coordinate list is empty\n")
+ ninter = 0
+ } else if (nreftri <= 0) {
+ if (verbose)
+ call printf (
+ " No valid reference triangles can be defined\n")
+ } else {
+ call malloc (xtrans, ntliststars, TY_REAL)
+ call malloc (ytrans, ntliststars, TY_REAL)
+ call malloc (listindex, ntliststars, TY_INT)
+ call rg_compute (Memr[xlist], Memr[ylist], Memr[xtrans],
+ Memr[ytrans], ntliststars, Memr[coeff], MAX_NCOEFF)
+ nliststars = rg_sort (Memr[xtrans], Memr[ytrans],
+ Memi[listindex], ntliststars, separation, YES, YES)
+ if (match != RG_TRIANGLES) {
+ intri = NULL
+ intrirat = NULL
+ nintri = nliststars
+ call rg_pllcolumns (ofd)
+ ninter = rg_llintersect (ofd, Memd[lngref], Memd[latref],
+ Memr[xref], Memr[yref], Memi[rsindex], Memi[rlineno],
+ nrefstars, Memr[xlist], Memr[ylist], Memr[xtrans],
+ Memr[ytrans], Memi[listindex], Memi[ilineno],
+ nliststars, tolerance, Memc[lngformat],
+ Memc[latformat],Memc[xformat], Memc[yformat])
+ } else if (nliststars > 2) {
+ ninmaxtri = rg_factorial (min (max(nliststars,nrefstars),
+ maxntriangles), 3)
+ call calloc (intri, SZ_TRIINDEX * ninmaxtri, TY_INT)
+ call calloc (intrirat, SZ_TRIPAR * ninmaxtri, TY_REAL)
+ nintri = rg_triangle (Memr[xtrans], Memr[ytrans],
+ Memi[listindex], nliststars, Memi[intri],
+ Memr[intrirat], ninmaxtri, maxntriangles,
+ ptolerance, ratio)
+ if (nintri <= 0) {
+ if (verbose)
+ call printf (
+ " No valid input triangles can be defined\n")
+ } else {
+ ninter = rg_match (Memr[xref], Memr[yref], nrefstars,
+ Memr[xtrans], Memr[ytrans], nliststars,
+ Memi[reftri], Memr[reftrirat], nreftri, nrmaxtri,
+ ntrefstars, Memi[intri], Memr[intrirat], nintri,
+ ninmaxtri, ntliststars, tolerance, ptolerance,
+ ratio, nreject)
+ }
+ if (nrefstars <= maxntriangles && nliststars <=
+ maxntriangles) {
+ call rg_pllcolumns (ofd)
+ call rg_lmwrite (ofd, Memd[lngref], Memd[latref],
+ Memi[rlineno], Memr[xlist], Memr[ylist],
+ Memi[ilineno], Memi[reftri], nrmaxtri,
+ Memi[intri], ninmaxtri, ninter, Memc[lngformat],
+ Memc[latformat], Memc[xformat], Memc[yformat])
+ } else {
+ if (rg_mlincoeff (Memr[xref], Memr[yref], Memr[xlist],
+ Memr[ylist], Memi[reftri], nrmaxtri,
+ Memi[intri], ninmaxtri, ninter, Memr[coeff],
+ MAX_NCOEFF) == ERR)
+ call rg_lmkcoeff (xin, yin, xmag, ymag, xrot, yrot,
+ 0.0, 0.0, Memr[coeff], MAX_NCOEFF)
+ call rg_compute (Memr[xlist], Memr[ylist],
+ Memr[xtrans], Memr[ytrans], ntliststars,
+ Memr[coeff], MAX_NCOEFF)
+ nliststars = rg_sort (Memr[xtrans], Memr[ytrans],
+ Memi[listindex], ntliststars, separation,
+ YES, YES)
+ if (verbose)
+ call rg_pmlincoeff (" xi", " eta", Memr[coeff],
+ MAX_NCOEFF)
+ call rg_wmlincoeff (ofd, " xi", " eta", Memr[coeff],
+ MAX_NCOEFF)
+ call rg_pllcolumns (ofd)
+ ninter = rg_llintersect (ofd, Memd[lngref],
+ Memd[latref], Memr[xref], Memr[yref], Memi[rsindex],
+ Memi[rlineno], nrefstars, Memr[xlist], Memr[ylist],
+ Memr[xtrans], Memr[ytrans], Memi[listindex],
+ Memi[ilineno], nliststars, tolerance,
+ Memc[lngformat], Memc[latformat], Memc[xformat],
+ Memc[yformat])
+ }
+ } else {
+ if (verbose)
+ call printf (
+ "\tThe input coordinate list has < 3 stars\n")
+ intri = NULL
+ intrirat = NULL
+ nintri = 0
+ ninter = 0
+ }
+ }
+
+ # Print out the number of stars matched in the two lists.
+ if (verbose) {
+ call printf ("%d reference coordinates matched\n")
+ call pargi (ninter)
+ }
+
+ # Free space used by input list.
+ call mfree (xlist, TY_REAL)
+ call mfree (ylist, TY_REAL)
+ call mfree (ilineno, TY_INT)
+ call mfree (listindex, TY_INT)
+ if (xtrans != NULL)
+ call mfree (xtrans, TY_REAL)
+ if (ytrans != NULL)
+ call mfree (ytrans, TY_REAL)
+ if (intri != NULL)
+ call mfree (intri, TY_INT)
+ if (intrirat != NULL)
+ call mfree (intrirat, TY_REAL)
+
+ # Close the input and output lists.
+ call close (ifd)
+ call close (ofd)
+ }
+
+ # Release the memory used to store the reference list.
+ call mfree (lngref, TY_DOUBLE)
+ call mfree (latref, TY_DOUBLE)
+ call mfree (xref, TY_REAL)
+ call mfree (yref, TY_REAL)
+ call mfree (rlineno, TY_INT)
+ call mfree (rsindex, TY_INT)
+ if (reftri != NULL)
+ call mfree (reftri, TY_INT)
+ if (reftrirat != NULL)
+ call mfree (reftrirat, TY_REAL)
+
+ # Close the reference file.
+ if (rfd != NULL)
+ call close (rfd)
+
+ # Close the reference points file.
+ if (rpfd != NULL)
+ call close (rpfd)
+
+ # Close the file lists.
+ call clpcls (ilist)
+ call clpcls (rlist)
+ call clpcls (olist)
+
+ call sfree (sp)
+end
+
+
+# RG_RDLLI -- Read in the celestial coordinates from a file, convert them
+# to standard coordinates, and set the line number index.
+
+int procedure rg_rdlli (fd, lng, lat, x, y, lineno, tlngref, tlatref,
+ xcolumn, ycolumn, projection, lngref, latref, lngunits, latunits)
+
+int fd #I the input file descriptor
+pointer lng #U pointer to the x coordinates
+pointer lat #U pointer to the y coordinates
+pointer x #U pointer to the x coordinates
+pointer y #U pointer to the y coordinates
+pointer lineno #U pointer to the line numbers
+double tlngref #O the adopted reference ra / longitude
+double tlatref #O the adopted reference dec / latitude
+int xcolumn #I column containing the x coordinate
+int ycolumn #I column containing the y coordinate
+char projection[ARB] #I the sky projection geometry
+double lngref #I the input reference ra / longitude
+double latref #I the input reference dec / latitude
+int lngunits #I the ra / longitude units
+int latunits #I the dec / latitude units
+
+int i, ip, bufsize, npts, lnpts, maxcols
+double xval, yval
+pointer sp, str, tx, ty
+int fscan(), nscan(), ctod()
+double asumd()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ bufsize = DEF_BUFSIZE
+ call malloc (lng, bufsize, TY_DOUBLE)
+ call malloc (lat, bufsize, TY_DOUBLE)
+ call malloc (x, bufsize, TY_REAL)
+ call malloc (y, bufsize, TY_REAL)
+ call malloc (lineno, bufsize, TY_INT)
+ maxcols = max (xcolumn, ycolumn)
+
+ npts = 0
+ lnpts = 0
+ while (fscan(fd) != EOF) {
+
+ lnpts = lnpts + 1
+ xval = INDEFD
+ yval = INDEFD
+ do i = 1, maxcols {
+ call gargwrd (Memc[str], SZ_LINE)
+ if (i != nscan())
+ break
+ ip = 1
+ if (i == xcolumn) {
+ if (ctod (Memc[str], ip, xval) <= 0)
+ xval = INDEFD
+ } else if (i == ycolumn) {
+ if (ctod (Memc[str], ip, yval) <= 0)
+ yval = INDEFD
+ }
+ }
+ if (IS_INDEFD(xval) || IS_INDEFD(yval))
+ next
+
+ Memd[lng+npts] = xval
+ Memd[lat+npts] = yval
+ Memi[lineno+npts] = lnpts
+ npts = npts + 1
+ if (npts >= bufsize) {
+ bufsize = bufsize + DEF_BUFSIZE
+ call realloc (lng, bufsize, TY_DOUBLE)
+ call realloc (lat, bufsize, TY_DOUBLE)
+ call realloc (x, bufsize, TY_REAL)
+ call realloc (y, bufsize, TY_REAL)
+ call realloc (lineno, bufsize, TY_INT)
+ }
+ }
+
+ # Compute the reference point and convert to standard coordinates.
+ if (npts > 0) {
+ if (IS_INDEFD(lngref))
+ tlngref = asumd (Memd[lng], npts) / npts
+ else
+ tlngref = lngref
+ if (IS_INDEFD(latref))
+ tlatref = asumd (Memd[lat], npts) / npts
+ else
+ tlatref = latref
+ call salloc (tx, npts, TY_DOUBLE)
+ call salloc (ty, npts, TY_DOUBLE)
+ call rg_celtostd (projection, Memd[lng], Memd[lat], Memd[tx],
+ Memd[ty], npts, tlngref, tlatref, lngunits, latunits)
+ call amulkd (Memd[tx], 3600.0d0, Memd[tx], npts)
+ call amulkd (Memd[ty], 3600.0d0, Memd[ty], npts)
+ call achtdr (Memd[tx], Memr[x], npts)
+ call achtdr (Memd[ty], Memr[y], npts)
+ } else {
+ tlngref = lngref
+ tlatref = latref
+ }
+
+ call sfree (sp)
+
+ return (npts)
+end
+
+
+# RG_PLLCOLUMNS -- Print the column descriptions in the output file.
+
+procedure rg_pllcolumns (ofd)
+
+int ofd #I the output file descriptor
+
+begin
+ call fprintf (ofd, "# Column definitions\n")
+ call fprintf (ofd,
+ "# Column 1: Reference Ra / Longitude coordinate\n")
+ call fprintf (ofd,
+ "# Column 2: Reference Dec / Latitude coordinate\n")
+ call fprintf (ofd, "# Column 3: Input X coordinate\n")
+ call fprintf (ofd, "# Column 4: Input Y coordinate\n")
+ call fprintf (ofd, "# Column 5: Reference line number\n")
+ call fprintf (ofd, "# Column 6: Input line number\n")
+ call fprintf (ofd, "\n")
+end
diff --git a/pkg/images/imcoords/src/t_hpctran.x b/pkg/images/imcoords/src/t_hpctran.x
new file mode 100644
index 00000000..aa398186
--- /dev/null
+++ b/pkg/images/imcoords/src/t_hpctran.x
@@ -0,0 +1,136 @@
+include <math.h>
+
+define DIRS "|ang2row|row2ang|"
+define ANG2PIX 1
+define PIX2ANG 2
+
+define CUNITS "|hourdegree|degrees|radians|"
+define H 1
+define D 2
+define R 3
+
+define MTYPES "|nest|ring|"
+define NEST 1
+define RING 2
+
+
+# T_HPCTRAN -- Convert between HEALPix rows and spherical coordinates.
+#
+# It is up to the user to know the coordinate and map type; e.g.
+# galactic/nested, equatorial/ring. However, the use can use
+# whatever units for the coordinate type; e.g. hours/degrees, radians.
+#
+# The HEALPix row is 1 indexed to be consistent with IRAF conventions.
+# This row can be used to access the map data with TTOOLS tasks.
+
+procedure t_hpctran ()
+
+int dir # Direction (ang2row|row2ang)
+int row # HEALpix map row (1 indexed)
+double lng # RA/longitude
+double lat # DEC/latitude
+int nside # Resolution parameter
+int cunits # Coordinate units
+int mtype # HEALpix map type
+
+char str[10]
+
+int clgeti(), clgwrd()
+double clgetd()
+errchk ang2row, row2ang
+
+begin
+ # Get parameters.
+ dir = clgwrd ("direction", str, 10, DIRS)
+ nside = clgeti ("nside")
+ cunits = clgwrd ("cunits", str, 10, CUNITS)
+ mtype = clgwrd ("maptype", str, 10, MTYPES)
+
+ switch (dir) {
+ case ANG2PIX:
+ lng = clgetd ("lng")
+ lat = clgetd ("lat")
+ switch (cunits) {
+ case 0:
+ call error (1, "Unknown coordinate units")
+ case H:
+ lng = lng * 15D0
+ case R:
+ lng = RADTODEG(lng)
+ lat = RADTODEG(lat)
+ }
+
+ call ang2row (row, lng, lat, mtype, nside)
+
+ call clputi ("row", row)
+ case PIX2ANG:
+ row = clgeti ("row")
+
+ call row2ang (row, lng, lat, mtype, nside)
+
+ switch (cunits) {
+ case 0:
+ call error (1, "Unknown coordinate units")
+ case H:
+ lng = lng / 15D0
+ case R:
+ lng = DEGTORAD(lng)
+ lat = DEGTORAD(lat)
+ }
+
+ call clputd ("lng", lng)
+ call clputd ("lat", lat)
+ }
+
+ # Output the map row.
+ call printf ("%d %g %g\n")
+ call pargi (row)
+ call pargd (lng)
+ call pargd (lat)
+end
+
+
+# TEST_HEALPIX2 -- Test routine as in the HEALPix distribution.
+
+procedure test_healpix2 ()
+
+double theta, phi
+int nside
+int ipix, npix, dpix, ip1
+
+begin
+
+ call printf("Starting C Healpix pixel routines test\n")
+
+ nside = 1024
+ dpix = 23
+
+ # Find the number of pixels in the full map
+ npix = 12*nside*nside
+ call printf("Number of pixels in full map: %d\n")
+ call pargi (npix)
+
+ call printf("dpix: %d\n")
+ call pargi (dpix)
+ call printf("Nest -> ang -> Ring -> ang -> Nest\n")
+# call printf("Nest -> ang -> Nest\n")
+# call printf("Ring -> ang -> Ring\n")
+ for (ipix = 0; ipix < npix; ipix = ipix + dpix) {
+ call pix2ang_nest(nside, ipix, theta, phi)
+ call ang2pix_ring(nside, theta, phi, ip1)
+ call pix2ang_ring(nside, ip1, theta, phi)
+ call ang2pix_nest(nside, theta, phi, ip1)
+# call pix2ang_ring(nside, ipix, theta, phi)
+# call ang2pix_ring(nside, theta, phi, ip1)
+ if (ip1 != ipix) {
+ call printf("Error: %d %d %d\n")
+ call pargi (nside)
+ call pargi (ipix)
+ call pargi (ip1)
+ }
+ }
+
+ call printf("%d\n")
+ call pargi (nside)
+ call printf("test completed\n\n")
+end
diff --git a/pkg/images/imcoords/src/t_imcctran.x b/pkg/images/imcoords/src/t_imcctran.x
new file mode 100644
index 00000000..4729a85d
--- /dev/null
+++ b/pkg/images/imcoords/src/t_imcctran.x
@@ -0,0 +1,922 @@
+include <fset.h>
+include <imhdr.h>
+include <math.h>
+include <mwset.h>
+include <math/gsurfit.h>
+include <pkg/skywcs.h>
+
+procedure t_imcctran ()
+
+double tilng, tilat, tolng, tolat, xscale, yscale, xrot, yrot, xrms, yrms
+double olongpole, olatpole, nlongpole, nlatpole
+pointer sp, imtemplate, insystem, outsystem, image, str
+pointer im, mwin, cooin, mwout, cooout, ctin, ctout
+pointer r, w, cd, ltm, ltv, iltm, nr, ncd, jr
+pointer ix, iy, ox, oy, ilng, ilat, olng, olat
+int imlist, nxgrid, nygrid, npts, instat, outstat, ndim, fitstat, axbits
+bool uselp, verbose, update, usecd
+
+double rg_rmsdiff()
+pointer immap(), rg_xytoxy(), mw_newcopy()
+int fstati(), imtopen(), imtgetim(), sk_decim(), sk_decwcs(), mw_stati()
+int clgeti(), sk_stati(), rg_cdfit()
+bool clgetb(), rg_longpole()
+
+begin
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (imtemplate, SZ_FNAME, TY_CHAR)
+ call salloc (insystem, SZ_FNAME, TY_CHAR)
+ call salloc (outsystem, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the list of images and output coordinate system.
+ call clgstr ("image", Memc[imtemplate], SZ_FNAME)
+ call clgstr ("outsystem", Memc[outsystem], SZ_FNAME)
+
+ # Get the remaining parameters.
+ nxgrid = clgeti ("nx")
+ nygrid = clgeti ("ny")
+ npts = nxgrid * nygrid
+ uselp = clgetb ("longpole")
+ verbose = clgetb ("verbose")
+ update = clgetb ("update")
+
+ # Loop over the list of images
+ imlist = imtopen (Memc[imtemplate])
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the input image after removing any section notation.
+ call imgimage (Memc[image], Memc[image], SZ_FNAME)
+ if (update)
+ im = immap (Memc[image], READ_WRITE, 0)
+ else
+ im = immap (Memc[image], READ_ONLY, 0)
+ if (verbose) {
+ call printf ("INPUT IMAGE: %s\n")
+ call pargstr (Memc[image])
+ }
+
+ # Create the input system name.
+ call sprintf (Memc[insystem], SZ_FNAME, "%s logical")
+ call pargstr (Memc[image])
+
+ # Open the input image coordinate system.
+ instat = sk_decim (im, "logical", mwin, cooin)
+ if (verbose) {
+ if (instat == ERR || mwin == NULL)
+ call printf ("Error decoding the input coordinate system\n")
+ call sk_iiprint ("Insystem", Memc[insystem], mwin, cooin)
+ }
+ if (instat == ERR || mwin == NULL) {
+ if (mwin != NULL)
+ call mw_close (mwin)
+ #call mfree (cooin, TY_STRUCT)
+ call sk_close (cooin)
+ call imunmap (im)
+ next
+ }
+
+ # Open the output coordinate system.
+ outstat = sk_decwcs (Memc[outsystem], mwout, cooout, cooin)
+ if (verbose) {
+ if (outstat == ERR || mwout != NULL)
+ call printf (
+ "Error decoding the output coordinate system\n")
+ call sk_iiprint ("Outsystem", Memc[outsystem], mwout, cooout)
+ }
+ if (outstat == ERR || mwout != NULL) {
+ if (mwout != NULL)
+ call mw_close (mwout)
+ #call mfree (cooout, TY_STRUCT)
+ call sk_close (cooout)
+ call sfree (sp)
+ return
+ }
+
+ # Get the dimensionality of the wcs.
+ ndim = mw_stati (mwin, MW_NPHYSDIM)
+
+ # Allocate working memory for the vectors and matrices.
+ call malloc (r, ndim, TY_DOUBLE)
+ call malloc (w, ndim, TY_DOUBLE)
+ call malloc (cd, ndim * ndim, TY_DOUBLE)
+ call malloc (ltm, ndim * ndim, TY_DOUBLE)
+ call malloc (ltv, ndim, TY_DOUBLE)
+ call malloc (iltm, ndim * ndim, TY_DOUBLE)
+ call malloc (nr, ndim, TY_DOUBLE)
+ call malloc (jr, ndim, TY_DOUBLE)
+ call malloc (ncd, ndim * ndim, TY_DOUBLE)
+
+ # Allocate working memory for the grid points.
+ call malloc (ix, npts, TY_DOUBLE)
+ call malloc (iy, npts, TY_DOUBLE)
+ call malloc (ilng, npts, TY_DOUBLE)
+ call malloc (ilat, npts, TY_DOUBLE)
+ call malloc (ox, npts, TY_DOUBLE)
+ call malloc (oy, npts, TY_DOUBLE)
+ call malloc (olng, npts, TY_DOUBLE)
+ call malloc (olat, npts, TY_DOUBLE)
+
+ # Compute the original logical to world transformation.
+ call mw_gltermd (mwin, Memd[ltm], Memd[ltv], ndim)
+ call mw_gwtermd (mwin, Memd[r], Memd[w], Memd[cd], ndim)
+ call mwvmuld (Memd[ltm], Memd[r], Memd[nr], ndim)
+ call aaddd (Memd[nr], Memd[ltv], Memd[nr], ndim)
+ call mwinvertd (Memd[ltm], Memd[iltm], ndim)
+ call mwmmuld (Memd[cd], Memd[iltm], Memd[ncd], ndim)
+
+ # Compute the logical and world coordinates of the input image
+ # grid points.
+ call rg_rxyl (Memd[ix], Memd[iy], nxgrid, nygrid, 1.0d0,
+ double(sk_stati(cooin, S_NLNGAX)), 1.0d0,
+ double(sk_stati(cooin, S_NLATAX)))
+ ctin = rg_xytoxy (mwin, Memd[ix], Memd[iy], Memd[ilng], Memd[ilat],
+ npts, "logical", "world", sk_stati (cooin, S_XLAX),
+ sk_stati (cooin, S_YLAX))
+
+ # Transfrom the input image grid points to the new world coordinate
+ # system.
+ call rg_lltransform (cooin, cooout, Memd[ilng], Memd[ilat],
+ Memd[olng], Memd[olat], npts)
+
+ # Get the reference point.
+ if (sk_stati(cooin, S_PLNGAX) < sk_stati(cooin, S_PLATAX)) {
+ tilng = Memd[w+sk_stati(cooin,S_PLNGAX)-1]
+ tilat = Memd[w+sk_stati(cooin,S_PLATAX)-1]
+ } else {
+ tilng = Memd[w+sk_stati(cooin,S_PLATAX)-1]
+ tilat = Memd[w+sk_stati(cooin,S_PLNGAX)-1]
+ }
+
+ # Compute the value of longpole and latpole required to transform
+ # the coordinate system.
+ usecd = rg_longpole (mwin, cooin, cooout, tilng, tilat, olongpole,
+ olatpole, nlongpole, nlatpole)
+ if (uselp)
+ usecd = false
+
+ # Output the current image wcs.
+ if (verbose && ! update) {
+ call printf ("\n")
+ call rg_wcsshow (mwin, "Current", Memd[ltv], Memd[ltm], Memd[w],
+ Memd[nr], Memd[ncd], ndim, olongpole, olatpole)
+ }
+
+ # Compute the new world coordinates of the reference point and
+ # update the reference point vector.
+ call rg_lltransform (cooin, cooout, tilng, tilat, tolng, tolat, 1)
+ if (sk_stati(cooout, S_PLNGAX) < sk_stati(cooout, S_PLATAX)) {
+ Memd[w+sk_stati(cooout,S_PLNGAX)-1] = tolng
+ Memd[w+sk_stati(cooout,S_PLATAX)-1] = tolat
+ } else {
+ Memd[w+sk_stati(cooout,S_PLNGAX)-1] = tolat
+ Memd[w+sk_stati(cooout,S_PLATAX)-1] = tolng
+ }
+
+ # Initialize the output transfrom.
+ mwout = mw_newcopy (mwin)
+
+ # Set the terms.
+ call mw_swtermd (mwout, Memd[r], Memd[w], Memd[cd], ndim)
+
+ if (usecd) {
+
+ # Compute the new x and y values.
+ ctout = rg_xytoxy (mwout, Memd[olng], Memd[olat], Memd[ox],
+ Memd[oy], npts, "world", "logical", sk_stati (cooout,
+ S_XLAX), sk_stati (cooout, S_YLAX))
+
+ # Subtract off the origin and compute the coordinate system
+ # rotation angle and scale factor.
+ call asubkd (Memd[ix], Memd[nr+sk_stati(cooin, S_XLAX)-1],
+ Memd[ix], npts)
+ call asubkd (Memd[iy], Memd[nr+sk_stati(cooin, S_YLAX)-1],
+ Memd[iy], npts)
+ call asubkd (Memd[ox], Memd[nr+sk_stati(cooout, S_XLAX)-1],
+ Memd[ox], npts)
+ call asubkd (Memd[oy], Memd[nr+sk_stati(cooout, S_YLAX)-1],
+ Memd[oy], npts)
+ fitstat = rg_cdfit (Memd[ix], Memd[iy], Memd[ox], Memd[oy],
+ npts, xscale, yscale, xrot, yrot)
+
+ } else {
+
+ ctout = NULL
+ xscale = 1.0d0
+ yscale = 1.0d0
+ xrot = 0.0d0
+ yrot = 0.0d0
+ fitstat = OK
+ }
+
+ if (fitstat == OK) {
+
+ # Modify the cd matrix.
+ if (usecd) {
+
+ axbits = 2 ** (sk_stati (cooout, S_XLAX) - 1) +
+ 2 ** (sk_stati (cooout, S_YLAX) - 1)
+ call rg_mwxyrot (mwout, xscale, yscale, xrot, yrot,
+ Memd[ncd], Memd[cd], ndim, axbits)
+ call mwmmuld (Memd[cd], Memd[ltm], Memd[ncd], ndim)
+ call mwinvertd (Memd[ltm], Memd[iltm], ndim)
+ call asubd (Memd[nr], Memd[ltv], Memd[r], ndim)
+ call mwvmuld (Memd[iltm], Memd[r], Memd[jr], ndim)
+ call mw_swtermd (mwout, Memd[jr], Memd[w], Memd[ncd], ndim)
+
+ # Modify longpole and latpole.
+ } else {
+ call sprintf (Memc[str], SZ_LINE, "%g")
+ call pargd (nlongpole)
+ #call eprintf ("longpole='%s'\n")
+ #call pargstr (Memc[str])
+ call mw_swattrs (mwout, sk_stati(cooout, S_PLNGAX),
+ "longpole", Memc[str])
+ call sprintf (Memc[str], SZ_LINE, "%g")
+ call pargd (nlatpole)
+ #call eprintf ("latpole='%s'\n")
+ #call pargstr (Memc[str])
+ call mw_swattrs (mwout, sk_stati(cooout, S_PLATAX),
+ "latpole", Memc[str])
+ call amovd (Memd[ncd], Memd[cd], ndim * ndim)
+ }
+
+ # Compute and print the goodness of fit estimate.
+ if (verbose) {
+ if (ctout != NULL)
+ call mw_ctfree (ctout)
+ ctout = rg_xytoxy (mwout, Memd[olng], Memd[olat],
+ Memd[ox], Memd[oy], npts, "world", "logical",
+ sk_stati (cooout, S_XLAX), sk_stati (cooout, S_YLAX))
+ if (usecd) {
+ call aaddkd (Memd[ix], Memd[nr+sk_stati(cooout,
+ S_XLAX)-1], Memd[ix], npts)
+ call aaddkd (Memd[iy], Memd[nr+sk_stati(cooout,
+ S_YLAX)-1], Memd[iy], npts)
+ }
+ xrms = rg_rmsdiff (Memd[ox], Memd[ix], npts)
+ yrms = rg_rmsdiff (Memd[oy], Memd[iy], npts)
+ }
+
+ # Recompute and store the new wcs if update is enabled.
+ if (update) {
+ call sk_saveim (cooout, mwout, im)
+ call mw_saveim (mwout, im)
+ } else if (verbose) {
+ if (usecd)
+ call rg_wcsshow (mwin, "New", Memd[ltv], Memd[ltm],
+ Memd[w], Memd[nr], Memd[cd], ndim, olongpole,
+ olatpole)
+ else
+ call rg_wcsshow (mwin, "New", Memd[ltv], Memd[ltm],
+ Memd[w], Memd[nr], Memd[cd], ndim, nlongpole,
+ nlatpole)
+ }
+
+ if (verbose) {
+ call printf (
+ "Crval%d,%d: %h, %h -> %h, %h dd:mm:ss.s\n")
+ call pargi (sk_stati(cooout,S_PLNGAX))
+ call pargi (sk_stati(cooout,S_PLATAX))
+ call pargd (tilng)
+ call pargd (tilat)
+ call pargd (tolng)
+ call pargd (tolat)
+ call printf (" Scaling: Xmag: %0.6f Ymag: %0.6f ")
+ call pargd (xscale)
+ call pargd (yscale)
+ call printf ("Xrot: %0.3f Yrot: %0.3f degrees\n")
+ call pargd (xrot)
+ call pargd (yrot)
+ call printf (
+ " Rms: X fit: %0.7g pixels Y fit: %0.7g pixels\n")
+ call pargd (xrms)
+ call pargd (yrms)
+ call printf ("\n")
+ }
+
+ } else
+ call printf ("Error fitting the scaling factors angle\n")
+
+ # Free the memory.
+ call mfree (r, TY_DOUBLE)
+ call mfree (w, TY_DOUBLE)
+ call mfree (cd, TY_DOUBLE)
+ call mfree (ncd, TY_DOUBLE)
+ call mfree (nr, TY_DOUBLE)
+ call mfree (jr, TY_DOUBLE)
+ call mfree (ltm, TY_DOUBLE)
+ call mfree (ltv, TY_DOUBLE)
+ call mfree (iltm, TY_DOUBLE)
+
+ call mfree (ix, TY_DOUBLE)
+ call mfree (iy, TY_DOUBLE)
+ call mfree (ilng, TY_DOUBLE)
+ call mfree (ilat, TY_DOUBLE)
+ call mfree (ox, TY_DOUBLE)
+ call mfree (oy, TY_DOUBLE)
+ call mfree (olng, TY_DOUBLE)
+ call mfree (olat, TY_DOUBLE)
+
+ # Clean up various data stuctures.
+ if (mwin != NULL)
+ call mw_close (mwin)
+ call sk_close (cooin)
+ if (mwout != NULL)
+ call mw_close (mwout)
+ call sk_ctypeim (cooout, im)
+ call sk_close (cooout)
+ call imunmap (im)
+ }
+
+ call imtclose (imlist)
+
+ call sfree (sp)
+end
+
+
+# RG_WCSSHOW -- Print a quick summary of the current wcs.
+
+procedure rg_wcsshow (mwin, label, ltv, ltm, w, r, cd, ndim, longpole, latpole)
+
+pointer mwin #I pointer to the current wcs
+char label[ARB] #I name of the input label
+double ltv[ARB] #I the lterm offsets
+double ltm[ndim,ARB] #I the lterm rotation matrix
+double w[ARB] #I the fits crval parameters
+double r[ARB] #I the fits crpix parameters
+double cd[ndim,ARB] #I the fits rotation matrix
+int ndim #I the dimension of the wcs
+double longpole #I the longpole value assumed
+double latpole #I the latpole value assumed
+
+int i,j
+pointer sp, str
+errchk mw_gwattrs()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print the image name and current wcs.
+ call printf ("%s wcs\n")
+ call pargstr (label)
+
+ # Print the axis banner.
+ call printf (" Axis ")
+ do i = 1, ndim {
+ call printf ("%10d ")
+ call pargi (i)
+ }
+ call printf ("\n")
+
+ # Print the crval parameters.
+ call printf (" Crval ")
+ do i = 1, ndim {
+ call printf ("%10.4f ")
+ call pargd (w[i])
+ }
+ call printf ("\n")
+
+ # Print the crpix parameters.
+ call printf (" Crpix ")
+ do i = 1, ndim {
+ call printf ("%10.2f ")
+ call pargd (r[i])
+ }
+ call printf ("\n")
+
+ # Print the cd matrix.
+ do i = 1, ndim {
+ call printf (" Cd %d ")
+ call pargi (i)
+ do j = 1, ndim {
+ call printf ("%10.4g ")
+ call pargd (cd[j,i])
+ }
+ call printf ("\n")
+ }
+
+ # Print longpole / latpole
+ call printf (" Poles ")
+ call printf ("%10.4f %10.4f\n")
+ call pargd (longpole)
+ call pargd (latpole)
+
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# RG_LONGPOLE -- Compute the value of longpole and latpole required to
+# transform the input celestial coordinate system to the output celestial
+# coordinate system, and determine whether this mode of transformation
+# is required for the specified projection.
+
+bool procedure rg_longpole (mwin, incoo, outcoo, ilng, ilat, ilngpole,
+ ilatpole, olngpole, olatpole)
+
+pointer mwin #I the input image coordinate system descriptor
+pointer incoo #I the input celestial coordinate system descriptor
+pointer outcoo #I the output celestial coordinate system descriptor
+double ilng #I the input celestial ra / longitude coordinate (deg)
+double ilat #I the input celestial dec / latitude coordinate (deg)
+double ilngpole #O the input system longpole value (deg)
+double ilatpole #O the input system latpole value (deg)
+double olngpole #O the output system longpole value (deg)
+double olatpole #O the output system latpole value (deg)
+
+double tilngpole, tilatpole, thetaa, theta0, tilng, tilat, tilngp, tilatp
+double ntilng, ntilat
+pointer sp, str
+int i, projection, ptype
+bool usecd
+int sk_stati(), rg_wrdstr(), strdic(), ctod()
+errchk mw_gwattrs()
+
+begin
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Get the projection type
+ projection = sk_stati (incoo, S_WTYPE)
+ if (projection <= 0)
+ projection = WTYPE_LIN
+ if (rg_wrdstr (projection, Memc[str], SZ_FNAME,
+ PTYPE_LIST) != projection)
+ call strcpy ("z", Memc[str], SZ_FNAME)
+ ptype = strdic (Memc[str], Memc[str], SZ_FNAME, PTYPE_NAMES)
+ if (ptype <= 0)
+ ptype = PTYPE_ZEN
+
+ # Get the input value of longpole if any.
+ iferr {
+ call mw_gwattrs (mwin, 1, "longpole", Memc[str], SZ_LINE)
+ } then {
+ iferr {
+ call mw_gwattrs (mwin, 2, "longpole", Memc[str], SZ_LINE)
+ } then {
+ tilngpole = INDEFD
+ } else {
+ i = 1
+ if (ctod (Memc[str], i, tilngpole) <= 0)
+ tilngpole = INDEFD
+ }
+ } else {
+ i = 1
+ if (ctod (Memc[str], i, tilngpole) <= 0)
+ tilngpole = INDEFD
+ }
+ ilngpole = tilngpole
+
+ # Get the input value of latpole if any.
+ iferr {
+ call mw_gwattrs (mwin, 1, "latpole", Memc[str], SZ_LINE)
+ } then {
+ iferr {
+ call mw_gwattrs (mwin, 2, "latpole", Memc[str], SZ_LINE)
+ } then {
+ tilatpole = INDEFD
+ } else {
+ i = 1
+ if (ctod (Memc[str], i, tilatpole) <= 0)
+ tilatpole = INDEFD
+ }
+ } else {
+ i = 1
+ if (ctod (Memc[str], i, tilatpole) <= 0)
+ tilatpole = INDEFD
+ }
+ ilatpole = tilatpole
+
+ # Get the input value of thetaa if any.
+ iferr {
+ call mw_gwattrs (mwin, 1, "projp1", Memc[str], SZ_LINE)
+ } then {
+ iferr {
+ call mw_gwattrs (mwin, 2, "projp1", Memc[str], SZ_LINE)
+ } then {
+ thetaa = INDEFD
+ } else {
+ i = 1
+ if (ctod (Memc[str], i, thetaa) <= 0)
+ thetaa = INDEFD
+ }
+ } else {
+ i = 1
+ if (ctod (Memc[str], i, thetaa) <= 0)
+ thetaa = INDEFD
+ }
+
+ # Determine theta0.
+ switch (ptype) {
+ case PTYPE_ZEN:
+ theta0 = DHALFPI
+ usecd = true
+ case PTYPE_CYL:
+ theta0 = 0.0d0
+ usecd = false
+ case PTYPE_CON:
+ if (IS_INDEFD(thetaa))
+ call error (0, "Invalid conic projection parameter thetaa")
+ else
+ theta0 = DDEGTORAD(thetaa)
+ usecd = false
+ case PTYPE_EXP:
+ theta0 = DHALFPI
+ usecd = false
+ #usecd = true
+ }
+
+ # Convert the input coordinates to radians.
+ tilng = DDEGTORAD (ilng)
+ tilat = DDEGTORAD (ilat)
+
+ # Determine the appropriate value of longpole and convert to radians.
+ if (IS_INDEFD(tilngpole)) {
+ if (tilat < theta0)
+ tilngpole = DPI
+ else
+ tilngpole = 0.0d0
+ } else
+ tilngpole = DDEGTORAD (tilngpole)
+ if (! IS_INDEFD(tilatpole))
+ tilatpole = DDEGTORAD (tilatpole)
+
+ # Compute the celestial coordinates of the pole in the old system
+ # and latpole.
+ switch (ptype) {
+ case PTYPE_ZEN, PTYPE_EXP:
+ tilngp = tilng
+ tilatp = DHALFPI - tilat
+ default:
+ call rg_cnpole (tilng, tilat, theta0, tilngpole, tilatpole,
+ tilngp, tilatp)
+ }
+ #call eprintf ("%0.5f %0.5f %0.5f %0.5f %0.5f %0.5f %0.5f\n")
+ #call pargd (DRADTODEG(tilng))
+ #call pargd (DRADTODEG(tilat))
+ #call pargd (DRADTODEG(theta0))
+ #call pargd (DRADTODEG(tilngpole))
+ #if (IS_INDEFD(tilatpole))
+ #call pargd (INDEFD)
+ #else
+ #call pargd (DRADTODEG(tilatpole))
+ #call pargd (DRADTODEG(tilngp))
+ #call pargd (DRADTODEG(tilatp))
+
+ # Compute the celestial coordinates in the old celestial coordinate
+ # system of the pole of the new coordinate system. Note that
+ # because the original coordinate system is a sky coordinate
+ # system that the input and output coordinate units are degrees.
+
+ call rg_lltransform (outcoo, incoo, 0.0d0, 90.0d0, ntilng, ntilat, 1)
+ #call eprintf ("%0.5f %0.5f\n")
+ #call pargd (ntilng)
+ #call pargd (ntilat)
+
+ # Compute the new longpole and latpole.
+ call rg_celtonat (DDEGTORAD(ntilng), DDEGTORAD(ntilat), tilngp, tilatp,
+ tilngpole, olngpole, olatpole)
+ olngpole = DRADTODEG(olngpole)
+ olatpole = DRADTODEG(olatpole)
+
+ call sfree (sp)
+
+ return (usecd)
+end
+
+
+# RG_CNPOLE -- Give the celestial coordinates of the reference point, the
+# native latitude of the reference point, and the native longitude
+# of the celestial pole, compute the celestial coordinates of the native
+# pole.
+
+procedure rg_cnpole (ra, dec, theta0, longp, latp, rap, decp)
+
+double ra #I the reference point ra / longitude in radians
+double dec #I the reference point dec / latitude in radians
+double theta0 #I the native latitude of the reference point in radians
+double longp #I the native longpole of the celestial pole in radians
+double latp #I the native latitude of the celestial pole in radians
+double rap #O the ra of native pole in radians (Euler angle 1)
+double decp #O the codec of native pole in radians (Euler angle 2)
+
+double clat0, slat0, cphip, sphip, cthe0, sthe0, x, y, z, u, v, latp1, latp2
+double tol, maxlat, tlatp
+data tol /1.0d-10/
+
+begin
+ clat0 = cos (dec)
+ slat0 = sin (dec)
+ cphip = cos (longp)
+ sphip = sin (longp)
+ cthe0 = cos (theta0)
+ sthe0 = sin (theta0)
+ x = cthe0 * cphip
+ y = sthe0
+ z = sqrt (x * x + y * y)
+
+ if (z == 0.0d0) {
+
+ if (slat0 != 0.0d0)
+ call error (0, "Invalid projection parameters")
+
+ if (IS_INDEFD(latp))
+ call error (0, "Undefined latpole value")
+
+ tlatp = latp
+
+ } else {
+
+ if (abs (slat0 / z) > 1.0d0)
+ call error (0, "Invalid projection parameters")
+
+ u = atan2 (y, x)
+ v = acos (slat0 / z)
+
+ latp1 = u + v
+ if (latp1 > DPI)
+ latp1 = latp1 - DTWOPI
+ else if (latp1 < -DPI)
+ latp1 = latp1 + DTWOPI
+
+ latp2 = u - v
+ if (latp2 > DPI)
+ latp2 = latp2 - DTWOPI
+ else if (latp2 < -DPI)
+ latp2 = latp2 + DTWOPI
+
+ if (IS_INDEFD(latp))
+ maxlat = 999.0d0
+ else
+ maxlat = latp
+ if (abs(maxlat - latp1) < abs(maxlat - latp2)) {
+ if (abs(latp1) < (DHALFPI + tol))
+ tlatp = latp1
+ else
+ tlatp = latp2
+ } else {
+ if (abs(latp2) < (DHALFPI + tol))
+ tlatp = latp2
+ else
+ tlatp = latp1
+ }
+ }
+ decp = DHALFPI - tlatp
+
+ # Determine the celestial longitude of the native pole.
+ z = cos (tlatp) * clat0
+ if (abs(z) < tol) {
+ if (abs(clat0) < tol) {
+ rap = ra
+ decp = DHALFPI - theta0
+ } else if (tlatp > 0.0d0) {
+ rap = ra + longp - DPI
+ decp = 0.0d0
+ } else if (tlatp < 0.0d0) {
+ rap = ra - longp
+ decp = DPI
+ }
+ } else {
+ x = (sthe0 - sin (tlatp) * slat0) / z
+ y = sphip * cthe0 / clat0
+ if (x == 0.0d0 && y == 0.0d0)
+ call error (0, "Invalid projection parameters")
+ rap = ra - atan2 (y,x)
+ }
+ if (ra >= 0.0d0) {
+ if (rap < 0.0d0)
+ rap = rap + DTWOPI
+ } else {
+ if (rap > 0.0d0)
+ rap = rap - DTWOPI
+ }
+end
+
+
+# RG_CELTONAT - Convert celestial to native coordinates given the input Euler
+# angles coordinates of the native pole and the longitude of the celestial pole.
+
+procedure rg_celtonat (ra, dec, rap, decp, longpole, phi, theta)
+
+double ra #I input ra/longitude
+double dec #I input ra/longitude
+double rap #I input euler angle 1 (rap)
+double decp #I input euler angle 2 (90-latp)
+double longpole #I input euler angle 3 (longpole)
+double phi #O output phi
+double theta #O output theta
+
+double x, y, z, dphi
+
+begin
+ x = sin (dec) * sin (decp) - cos (dec) * cos (decp) * cos (ra - rap)
+ if (abs(x) < 1.0d-5)
+ x = -cos (dec + decp) + cos (dec) * cos(decp) * (1.0d0 -
+ cos (ra - rap))
+ y = -cos (dec) * sin (ra - rap)
+ if (x != 0.0d0 || y != 0.0d0)
+ dphi = atan2 (y,x)
+ else
+ dphi = ra - rap - DPI
+ phi = longpole + dphi
+ if (phi > DPI)
+ phi = phi - DTWOPI
+ else if (phi < -DPI)
+ phi = phi + DTWOPI
+ if (mod (ra - rap, DPI) == 0.0d0) {
+ theta = dec + cos (ra - rap) * decp
+ if (theta > DHALFPI)
+ theta = DPI - theta
+ if (theta < -DHALFPI)
+ theta = -DPI - theta
+ } else {
+ z = sin (dec) * cos (decp) + cos (dec) * sin(decp) * cos (ra - rap)
+ if (abs(z) > 0.99d0)
+ theta = sign (acos(sqrt (x*x + y*y)), z)
+ else
+ theta = asin (z)
+ }
+end
+
+
+# RG_CDFIT -- Compute the cd matrix and shift vector required to realign
+# the transformed coordinate systems.
+
+int procedure rg_cdfit (xref, yref, xin, yin, npts, xscale, yscale, xrot, yrot)
+
+double xref[ARB] #I the input x reference vector
+double yref[ARB] #I the input y reference vector
+double xin[ARB] #I the input x vector
+double yin[ARB] #I the input y vector
+int npts #I the number of points
+double xscale, yscale #O the x and y scale factors
+double xrot #O the rotation angle in degrees
+double yrot #O the rotation angle in degrees
+
+int fitstat
+double xshift, yshift
+pointer sp, wts
+int rg_ffit()
+
+begin
+ call smark (sp)
+ call salloc (wts, npts, TY_DOUBLE)
+ call amovkd (1.0d0, Memd[wts], npts)
+
+ fitstat = rg_ffit (xref, yref, xin, yin, Memd[wts], npts,
+ xshift, yshift, xscale, yscale, xrot, yrot)
+ if (fitstat == ERR) {
+ xrot = INDEFD
+ yrot = INDEFD
+ xscale = INDEFD
+ yscale = INDEFD
+ }
+
+ call sfree (sp)
+ return (fitstat)
+end
+
+
+# RG_FFIT -- Compute the x and y shift, th x and y scale, and the x and y
+# rotation angle required to match one set of coordinates to another.
+
+int procedure rg_ffit (xref, yref, xin, yin, wts, npts, xshift, yshift,
+ xmag, ymag, xrot, yrot)
+
+double xref[ARB] #I reference image x values
+double yref[ARB] #I reference image y values
+double xin[ARB] #I input image x values
+double yin[ARB] #I input image y values
+double wts[ARB] #I array of weights
+int npts #I number of points
+double xshift, yshift #O the x and y shifts
+double xmag, ymag #O the x and y scale factors
+double xrot, yrot #O the rotation angles
+
+double xmin, xmax, ymin, ymax
+int xier, yier, ier
+pointer sx1, sy1
+
+begin
+ # Compute the data limits.
+ call alimd (xref, npts, xmin, xmax)
+ call alimd (yref, npts, ymin, ymax)
+
+ # Compute the x fit.
+ call dgsinit (sx1, GS_POLYNOMIAL, 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sx1, xref, yref, xin, wts, npts, WTS_USER, xier)
+
+ # Compute the y fit.
+ call dgsinit (sy1, GS_POLYNOMIAL, 2, 2, GS_XNONE, xmin, xmax,
+ ymin, ymax)
+ call dgsfit (sy1, xref, yref, yin, wts, npts, WTS_USER, yier)
+
+ # Compute the geometric parameters.
+ if (xier != OK || yier != OK) {
+ xshift = INDEFD
+ yshift = INDEFD
+ xmag = INDEFD
+ ymag = INDEFD
+ xrot = INDEFD
+ yrot = INDEFD
+ ier = ERR
+ } else {
+ call geo_lcoeffd (sx1, sy1, xshift, yshift, xmag, ymag, xrot, yrot)
+ ier = OK
+ }
+
+ call dgsfree (sx1)
+ call dgsfree (sy1)
+ return (ier)
+end
+
+
+define CDIN icd[$1,$2]
+define CDOUT ocd[$1,$2]
+
+# RG_MWXYROT -- Scale and rotate the CD matrix by specifying the x and y scale
+# factors in dimensionless units and the rotation angle in degrees. Since only
+# x and y scale factors and one rotation angle can be specified, this routine
+# is useful only useful for a 2D transformation
+
+procedure rg_mwxyrot(mw, xmag, ymag, xtheta, ytheta, icd, ocd, ndim, axbits)
+
+pointer mw #I pointer to MWCS descriptor
+double xmag, ymag #I the x and y scaling factors
+double xtheta #I the x rotation angle, degrees
+double ytheta #I the y rotation angle, degrees
+double icd[ndim,ARB] #U the input CD matrix
+double ocd[ndim,ARB] #U the output CD matrix
+int ndim #I dimensions of the CD matrix
+int axbits #I bitflags defining axes to be rotated
+
+double d_thetax, d_thetay, costx, sintx, costy, sinty
+int axis[IM_MAXDIM], naxes, ax1, ax2, axmap
+int mw_stati()
+errchk syserr
+
+begin
+ # Convert axis bitflags to axis list and get the two axes.
+ call mw_gaxlist (mw, axbits, axis, naxes)
+ axmap = mw_stati (mw, MW_USEAXMAP)
+ call mw_seti (mw, MW_USEAXMAP, NO)
+ ax1 = axis[1]
+ ax2 = axis[2]
+
+ # Rotate the CD matrix.
+ d_thetax = DEGTORAD(xtheta)
+ d_thetay = DEGTORAD(ytheta)
+ costx = cos (d_thetax)
+ sintx = sin (d_thetax)
+ costy = cos (d_thetay)
+ sinty = sin (d_thetay)
+ call amovd (icd, ocd, ndim * ndim)
+
+ CDOUT(ax1,ax1) = xmag * costx * CDIN(ax1,ax1) -
+ xmag * sintx * CDIN(ax2,ax1)
+ CDOUT(ax2,ax1) = ymag * sinty * CDIN(ax1,ax1) +
+ ymag * costy * CDIN(ax2,ax1)
+ CDOUT(ax1,ax2) = xmag * costx * CDIN(ax1,ax2) -
+ xmag * sintx * CDIN(ax2,ax2)
+ CDOUT(ax2,ax2) = ymag * sinty * CDIN(ax1,ax2) +
+ ymag * costy * CDIN(ax2,ax2)
+
+ call mw_seti (mw, MW_USEAXMAP, axmap)
+end
+
+
+# RG_RMSDIFF -- Compute the standard deviation of the difference between 2
+# vectors
+
+double procedure rg_rmsdiff (a, b, npts)
+
+double a[ARB] #I the first input vector
+double b[ARB] #I the second input vector
+int npts #I the number of points
+
+int i
+double sum, rms
+
+begin
+ sum = 0.0d0
+ do i = 1, npts
+ sum = sum + (a[i] - b[i]) ** 2
+
+ if (npts <= 1)
+ rms = INDEFD
+ else
+ rms = sqrt (sum / (npts - 1))
+
+ return (rms)
+end
+
diff --git a/pkg/images/imcoords/src/t_skyctran.x b/pkg/images/imcoords/src/t_skyctran.x
new file mode 100644
index 00000000..05a7e824
--- /dev/null
+++ b/pkg/images/imcoords/src/t_skyctran.x
@@ -0,0 +1,221 @@
+include <fset.h>
+include <pkg/skywcs.h>
+
+procedure t_skyctran()
+
+bool verbose, transform, first_file
+int inlist, outlist, linlist, loutlist, lngcolumn, latcolumn, infd, outfd
+int ilngunits, ilatunits, olngunits, olatunits, min_sigdigits, optype
+int instat, outstat, nilng, nilat, plngcolumn, platcolumn, pxcolumn
+int rvcolumn
+double ilngmin, ilngmax, ilatmin, ilatmax
+int fstati()
+pointer sp, inname, outname, insystem, outsystem, olngformat, olatformat
+pointer ilngformat, ilatformat, str, mwin, mwout, cooin, cooout
+
+bool clgetb(), streq()
+double clgetd()
+int clpopnu(), clplen(), clgfil(), open(), sk_decwcs()
+int clgeti(), clgwrd(), sk_stati()
+errchk clgwrd()
+
+begin
+ call smark (sp)
+ call salloc (inname, SZ_FNAME, TY_CHAR)
+ call salloc (outname, SZ_FNAME, TY_CHAR)
+ call salloc (insystem, SZ_FNAME, TY_CHAR)
+ call salloc (outsystem, SZ_FNAME, TY_CHAR)
+ call salloc (ilngformat, SZ_FNAME, TY_CHAR)
+ call salloc (ilatformat, SZ_FNAME, TY_CHAR)
+ call salloc (olngformat, SZ_FNAME, TY_CHAR)
+ call salloc (olatformat, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ # Open the input and output file lists.
+ inlist = clpopnu ("input")
+ linlist = clplen (inlist)
+ outlist = clpopnu ("output")
+ loutlist = clplen (outlist)
+ call clgstr ("insystem", Memc[insystem], SZ_FNAME)
+ call clgstr ("outsystem", Memc[outsystem], SZ_FNAME)
+ transform = clgetb ("transform")
+
+ # Fetch the file formatting parameters.
+ lngcolumn = clgeti ("lngcolumn")
+ latcolumn = clgeti ("latcolumn")
+ plngcolumn = clgeti ("plngcolumn")
+ platcolumn = clgeti ("platcolumn")
+ pxcolumn = clgeti ("pxcolumn")
+ rvcolumn = clgeti ("rvcolumn")
+ ilngmin = clgetd ("ilngmin")
+ ilngmax = clgetd ("ilngmax")
+ ilatmin = clgetd ("ilatmin")
+ ilatmax = clgetd ("ilatmax")
+ nilng = clgeti ("nilng")
+ nilat = clgeti ("nilat")
+ iferr (ilngunits = clgwrd ("ilngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ ilngunits = 0
+ iferr (ilatunits = clgwrd ("ilatunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ ilatunits = 0
+ call clgstr ("ilngformat", Memc[ilngformat], SZ_FNAME)
+ call clgstr ("ilatformat", Memc[ilatformat], SZ_FNAME)
+
+ iferr (olngunits = clgwrd ("olngunits", Memc[str], SZ_FNAME,
+ SKY_LNG_UNITLIST))
+ olngunits = 0
+ iferr (olatunits = clgwrd ("olatunits", Memc[str], SZ_FNAME,
+ SKY_LAT_UNITLIST))
+ olatunits = 0
+ call clgstr ("olngformat", Memc[olngformat], SZ_FNAME)
+ call clgstr ("olatformat", Memc[olatformat], SZ_FNAME)
+ #min_sigdigits = clgeti ("min_sigdigits")
+ min_sigdigits = 7
+ verbose = clgetb ("verbose")
+
+ # Test the length of the input coordinate list.
+ if (linlist < 1)
+ call error (0, "The input coordinate file list is empty")
+ if (loutlist < 1)
+ call error (0, "The output coordinate file list is empty")
+ if (loutlist > 1 && loutlist != linlist)
+ call error (0,
+ "The number of input and output files are not the same")
+
+ # Determine the input coordinate system.
+ instat = sk_decwcs (Memc[insystem], mwin, cooin, NULL)
+
+ # Determine the output coordinate system.
+ outstat = sk_decwcs (Memc[outsystem], mwout, cooout, NULL)
+
+ # Loop over the input files.
+ first_file = true
+ while (clgfil (inlist, Memc[inname], SZ_FNAME) != EOF) {
+
+ # Open the input coordinate file. The string "imcursor" is
+ # reserved for the image display cursor.
+ if (streq (Memc[inname], "imcursor") && mwin != NULL) {
+ infd = NULL
+ optype = sk_stati (cooin, S_PIXTYPE)
+ call sk_seti (cooin, S_PIXTYPE, PIXTYPE_TV)
+ } else if (streq (Memc[inname], "grid")) {
+ optype = sk_stati (cooin, S_PIXTYPE)
+ infd = NULL
+ } else
+ infd = open (Memc[inname], READ_ONLY, TEXT_FILE)
+
+ # Open the output coordinate file.
+ if (clgfil (outlist, Memc[outname], SZ_FNAME) != EOF) {
+ outfd = open (Memc[outname], NEW_FILE, TEXT_FILE)
+ if (streq (Memc[outname], "STDOUT") || outfd == STDOUT)
+ call fseti (outfd, F_FLUSHNL, YES)
+ call fprintf (outfd, "\n")
+ if (instat == ERR)
+ call fprintf (outfd,
+ "# Error decoding the input coordinate system\n")
+ call sk_iiwrite (outfd, "Insystem", Memc[insystem], mwin,
+ cooin)
+ if (outstat == ERR)
+ call fprintf (outfd,
+ "# Error decoding the output coordinate system\n")
+ call sk_iiwrite (outfd, "Outsystem", Memc[outsystem], mwout,
+ cooout)
+ }
+
+ # Print information about the input and output coordinate system
+ # and the input and output files to the standard output.
+ if (verbose && outfd != STDOUT) {
+ if (first_file) {
+ call printf ("\n")
+ if (instat == ERR)
+ call printf (
+ "Error decoding the input coordinate system\n")
+ call sk_iiprint ("Insystem", Memc[insystem], mwin, cooin)
+ if (outstat == ERR)
+ call printf (
+ "Error decoding the output coordinate system\n")
+ call sk_iiprint ("Outsystem", Memc[outsystem], mwout,
+ cooout)
+ call printf ("\n")
+ }
+ call printf ("Input file: %s Output file: %s\n")
+ call pargstr (Memc[inname])
+ call pargstr (Memc[outname])
+ call flush (STDOUT)
+ }
+
+
+ # Print the input and output file name banner.
+ call fprintf (outfd, "\n# Input file: %s Output file: %s\n")
+ call pargstr (Memc[inname])
+ call pargstr (Memc[outname])
+ call fprintf (outfd, "\n")
+
+ # Transform the coordinate list.
+ if (infd == NULL) {
+ if (streq ("imcursor", Memc[inname]))
+ call sk_curtran (outfd, mwin, mwout, cooin, cooout,
+ olngunits, olatunits, Memc[olngformat],
+ Memc[olatformat], transform)
+ else if (instat == ERR || outstat == ERR)
+ call sk_grcopy (outfd, cooin, cooout, ilngmin, ilngmax,
+ nilng, ilatmin, ilatmax, nilat, ilngunits,
+ ilatunits, olngunits, olatunits, Memc[ilngformat],
+ Memc[ilatformat], Memc[olngformat],
+ Memc[olatformat], transform)
+ else
+ call sk_grtran (outfd, mwin, mwout, cooin, cooout,
+ ilngmin, ilngmax, nilng, ilatmin, ilatmax, nilat,
+ ilngunits, ilatunits, olngunits, olatunits,
+ Memc[ilngformat], Memc[ilatformat], Memc[olngformat],
+ Memc[olatformat], transform)
+ } else {
+ if (infd == STDIN && fstati(STDIN, F_REDIR) == NO)
+ call sk_ttytran (infd, outfd, mwin, mwout, cooin, cooout,
+ ilngunits, ilatunits, olngunits, olatunits,
+ Memc[olngformat], Memc[olatformat])
+ else if (instat == ERR || outstat == ERR)
+ call sk_copytran (infd, outfd, lngcolumn, latcolumn,
+ transform)
+ else
+ call sk_listran (infd, outfd, mwin, mwout, cooin, cooout,
+ lngcolumn, latcolumn, plngcolumn, platcolumn,
+ pxcolumn, rvcolumn, ilngunits, ilatunits, olngunits,
+ olatunits, Memc[olngformat], Memc[olatformat],
+ min_sigdigits, transform)
+ }
+
+ # Close the output coordinate file.
+ if (linlist == loutlist)
+ call close (outfd)
+
+ # Close the input coordinate file.
+ if (infd != NULL)
+ call close (infd)
+ else
+ call sk_seti (cooin, S_PIXTYPE, optype)
+
+ first_file = false
+ }
+
+ # Close the image wcs if one was opened.
+ if (loutlist < linlist)
+ call close (outfd)
+ if (mwin != NULL)
+ call mw_close (mwin)
+ if (mwout != NULL)
+ call mw_close (mwout)
+ #call mfree (cooin, TY_STRUCT)
+ call sk_close (cooin)
+ #call mfree (cooout, TY_STRUCT)
+ call sk_close (cooout)
+
+ # Close up the lists.
+ call clpcls (inlist)
+ call clpcls (outlist)
+
+ call sfree (sp)
+end
+
+
diff --git a/pkg/images/imcoords/src/t_starfind.x b/pkg/images/imcoords/src/t_starfind.x
new file mode 100644
index 00000000..6288ea15
--- /dev/null
+++ b/pkg/images/imcoords/src/t_starfind.x
@@ -0,0 +1,224 @@
+include <fset.h>
+
+# T_STARFIND -- Automatically detect objects in an image given the full-
+# width half-maximum of the image point spread function and a detection
+# threshold using a modified version of the daofind algorithm.
+
+procedure t_starfind ()
+
+int imlist, olist, limlist, lolist, boundary, verbose
+int stat, root, out, nxblock, nyblock
+pointer sp, image, output, outfname, str, wcs, wxformat, wyformat
+pointer im, sf
+real constant
+
+bool clgetb()
+int imtopenp(), clpopnu(), imtlen(), clplen(), clgwrd(), btoi(), open()
+int clgeti(), imtgetim(), clgfil(), fnldir(), strncmp(), strlen()
+pointer immap()
+real clgetr()
+
+begin
+ # Flush STDOUT on a new line.
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (output, SZ_FNAME, TY_CHAR)
+ call salloc (outfname, SZ_FNAME, TY_CHAR)
+ call salloc (wcs, SZ_FNAME, TY_CHAR)
+ call salloc (wxformat, SZ_FNAME, TY_CHAR)
+ call salloc (wyformat, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Open the image and output file lists.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ olist = clpopnu ("output")
+ lolist = clplen (olist)
+
+ # Test the input and output file list.
+ if (lolist > 1 && lolist != limlist) {
+ call imtclose (imlist)
+ call clpcls (olist)
+ call sfree (sp)
+ call error (0, "Imcompatible image and output list lengths")
+ }
+
+ # Get the algorithm parameters.
+ call sf_gpars (sf)
+
+ # Get the wcs paramaters.
+ call clgstr ("wcs", Memc[wcs], SZ_FNAME)
+ call clgstr ("wxformat", Memc[wxformat], SZ_FNAME)
+ call clgstr ("wyformat", Memc[wyformat], SZ_FNAME)
+
+ # Get the image blocking boundary extensions parameters.
+ boundary = clgwrd ("boundary", Memc[str], SZ_LINE,
+ ",constant,nearest,reflect,wrap,")
+ constant = clgetr ("constant")
+ nxblock = clgeti ("nxblock")
+ nyblock = clgeti ("nyblock")
+
+ # Verbose mode ?
+ verbose = btoi (clgetb ("verbose"))
+
+ # Loop over the images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the input image.
+ im = immap (Memc[image], READ_ONLY, 0)
+
+ # Get the output file name and open the file.
+ if (lolist == 0) {
+ call strcpy ("", Memc[outfname], SZ_FNAME)
+ out = NULL
+ } else {
+ stat = clgfil (olist, Memc[output], SZ_FNAME)
+ root = fnldir (Memc[output], Memc[outfname], SZ_FNAME)
+ if (strncmp ("default", Memc[output+root], 7) == 0 || root ==
+ strlen (Memc[output])) {
+ call sf_outname (Memc[image], Memc[outfname], "obj",
+ Memc[outfname], SZ_FNAME)
+ lolist = limlist
+ } else if (stat != EOF) {
+ call strcpy (Memc[output], Memc[outfname], SZ_FNAME)
+ } else {
+ call sf_outname (Memc[image], Memc[outfname], "obj",
+ Memc[outfname], SZ_FNAME)
+ lolist = limlist
+ }
+ }
+ out = open (Memc[outfname], NEW_FILE, TEXT_FILE)
+
+ # Find the stars in an image.
+ call sf_find (im, out, sf, nxblock, nyblock, Memc[wcs],
+ Memc[wxformat], Memc[wyformat], boundary, constant,
+ verbose)
+
+ # Close images and files.
+ call imunmap (im)
+ call close (out)
+
+ }
+
+
+ # Close lists.
+ call sf_free (sf)
+ call imtclose (imlist)
+ call clpcls (olist)
+ call sfree (sp)
+end
+
+
+# SF_OUTNAME -- Construct the output file name. If output is null or a
+# directory, a name is constructed from the root of the image name and
+# the extension. The disk is searched to avoid name collisions.
+
+procedure sf_outname (image, output, ext, name, maxch)
+
+char image[ARB] #I image name
+char output[ARB] #I output directory or name
+char ext[ARB] #I extension
+char name[ARB] #O output name
+int maxch #I maximum size of name
+
+int ndir, nimdir, clindex, clsize
+pointer sp, root, str
+int fnldir(), strlen()
+
+begin
+ call smark (sp)
+ call salloc (root, SZ_FNAME, TY_CHAR)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+
+ ndir = fnldir (output, name, maxch)
+ if (strlen (output) == ndir) {
+ call imparse (image, Memc[root], SZ_FNAME, Memc[str], SZ_FNAME,
+ Memc[str], SZ_FNAME, clindex, clsize)
+ nimdir = fnldir (Memc[root], Memc[str], SZ_FNAME)
+ if (clindex >= 0) {
+ call sprintf (name[ndir+1], maxch, "%s%d.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargi (clindex)
+ call pargstr (ext)
+ } else {
+ call sprintf (name[ndir+1], maxch, "%s.%s.*")
+ call pargstr (Memc[root+nimdir])
+ call pargstr (ext)
+ }
+ call sf_oversion (name, name, maxch)
+ } else
+ call strcpy (output, name, maxch)
+
+ call sfree (sp)
+end
+
+
+## SF_IMROOT -- Fetch the root image name minus the directory specification
+## and the section notation. The length of the root name is returned.
+#
+#int procedure sf_imroot (image, root, maxch)
+#
+#char image[ARB] #I image specification
+#char root[ARB] #O rootname
+#int maxch #I maximum number of characters
+#
+#int nchars
+#pointer sp, str
+#int fnldir(), strlen()
+#
+#begin
+# call smark (sp)
+# call salloc (str, SZ_FNAME, TY_CHAR)
+#
+# call imgimage (image, root, maxch)
+# nchars = fnldir (root, Memc[str], maxch)
+# call strcpy (root[nchars+1], root, maxch)
+#
+# call sfree (sp)
+# return (strlen (root))
+#end
+
+
+# SF_OVERSION -- Compute the next available version number of a given file
+# name template and output the new file name.
+
+procedure sf_oversion (template, filename, maxch)
+
+char template[ARB] #I name template
+char filename[ARB] #O output name
+int maxch #I maximum number of characters
+
+char period
+int newversion, version, len
+pointer sp, list, name
+int fntgfnb() strldx(), ctoi(), fntopnb()
+
+begin
+ # Allocate temporary space
+ call smark (sp)
+ call salloc (name, maxch, TY_CHAR)
+ period = '.'
+ list = fntopnb (template, NO)
+
+ # Loop over the names in the list searchng for the highest version.
+ newversion = 0
+ while (fntgfnb (list, Memc[name], maxch) != EOF) {
+ len = strldx (period, Memc[name])
+ len = len + 1
+ if (ctoi (Memc[name], len, version) <= 0)
+ next
+ newversion = max (newversion, version)
+ }
+
+ # Make new output file name.
+ len = strldx (period, template)
+ call strcpy (template, filename, len)
+ call sprintf (filename[len+1], maxch, "%d")
+ call pargi (newversion + 1)
+
+ call fntclsb (list)
+ call sfree (sp)
+end
diff --git a/pkg/images/imcoords/src/t_wcsctran.x b/pkg/images/imcoords/src/t_wcsctran.x
new file mode 100644
index 00000000..7459ec48
--- /dev/null
+++ b/pkg/images/imcoords/src/t_wcsctran.x
@@ -0,0 +1,643 @@
+include <imio.h>
+include <fset.h>
+include <ctype.h>
+include <imhdr.h>
+include <ctotok.h>
+include <mwset.h>
+
+# Define some limits on the input file
+
+define MAX_FIELDS 100 # maximum number of fields in the list
+define TABSIZE 8 # spacing of the tab stops
+
+# Define the supported units
+
+define WT_UNITSTR "|hours|native|"
+define WT_UHOURS 1
+define WT_UNATIVE 2
+
+define WT_WCSSTR "|logical|tv|physical|world|"
+define WT_LOGICAL 1
+define WT_TV 2
+define WT_PHYSICAL 3
+define WT_WORLD 4
+
+# Define the supported wcs.
+# T_WCSCTRAN -- Transform a list of image coordinates from one coordinate
+# system to another using world coordinate system information stored in
+# the header of a reference image.
+
+procedure t_wcsctran()
+
+bool verbose
+int i, csp, imlist,inlist, outlist, limlist, linlist, loutlist
+int icl, ocl, ndim, wcsndim, ncolumns, nunits, inwcs, outwcs, min_sigdigits
+pointer sp, image, columns, units, iwcs, owcs, fmtstr, fmtptrs
+pointer str, name, im, mw, ct, tmp
+
+bool clgetb()
+int imtopenp(), imtlen(), imtgetim(), fntopnb(), fntlenb(), fntgfnb()
+int open(), mw_stati(), wt_getlabels(), ctoi(), strdic(), clgeti(), nscan()
+int errget()
+pointer immap(), mw_openim(), mw_sctran()
+errchk mw_openim(), mw_gwattrs(), mw_sctran()
+
+begin
+ call smark (sp)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (columns, IM_MAXDIM, TY_INT)
+ call salloc (units, IM_MAXDIM, TY_INT)
+ call salloc (iwcs, SZ_FNAME, TY_CHAR)
+ call salloc (owcs, SZ_FNAME, TY_CHAR)
+ call salloc (fmtstr, SZ_FNAME, TY_CHAR)
+ call salloc (fmtptrs, IM_MAXDIM, TY_POINTER)
+ call salloc (str, SZ_FNAME, TY_CHAR)
+ call salloc (name, SZ_FNAME, TY_CHAR)
+
+ # Get the input and output image and file lists.
+ imlist = imtopenp ("image")
+ limlist = imtlen (imlist)
+ call clgstr ("input", Memc[str], SZ_FNAME)
+ inlist = fntopnb (Memc[str], NO)
+ linlist = fntlenb (inlist)
+ call clgstr ("output", Memc[str], SZ_FNAME)
+ if (Memc[str] == EOS)
+ call strcpy ("STDOUT", Memc[str], SZ_FNAME)
+ outlist = fntopnb (Memc[str], NO)
+ loutlist = fntlenb (outlist)
+
+ # Get the input coordinate file format.
+ call clgstr ("columns", Memc[str], SZ_FNAME)
+ ncolumns = 0
+ csp = 1
+ while (wt_getlabels (Memc[str], csp, Memc[name], SZ_FNAME) != EOF) {
+ i = 1
+ if (ctoi(Memc[name], i, Memi[columns+ncolumns]) <= 0)
+ break
+ ncolumns = ncolumns + 1
+ }
+
+ # Get the input coordinate units. Fill in any missing information
+ # with native units
+ call clgstr ("units", Memc[str], SZ_FNAME)
+ nunits = 0
+ csp = 1
+ while (wt_getlabels (Memc[str], csp, Memc[name], SZ_FNAME) != EOF) {
+ i = strdic (Memc[name], Memc[name], SZ_FNAME, WT_UNITSTR)
+ if (i <= 0)
+ break
+ Memi[units+nunits] = i
+ nunits = nunits + 1
+ }
+ do i = nunits + 1, IM_MAXDIM
+ Memi[units+i-1] = WT_UNATIVE
+
+ # Get the input and output transform.
+ call clgstr ("inwcs", Memc[iwcs], SZ_FNAME)
+ inwcs = strdic (Memc[iwcs], Memc[iwcs], SZ_FNAME, WT_WCSSTR)
+ call clgstr ("outwcs", Memc[owcs], SZ_FNAME)
+ outwcs = strdic (Memc[owcs], Memc[owcs], SZ_FNAME, WT_WCSSTR)
+
+ # Get the format strings and minimum number of significant digits.
+ call clgstr ("formats", Memc[fmtstr], SZ_FNAME)
+ min_sigdigits = clgeti ("min_sigdigits")
+
+ # Get the remaining parameters.
+ verbose = clgetb ("verbose")
+
+ # Check that the image and output list lengths match. The number
+ # of input coordinate lists must be 1 or equal to the number of
+ # input images.
+ if (limlist < 1 || (linlist > 1 && linlist != limlist)) {
+ call imtclose (imlist)
+ call fntclsb (inlist)
+ call fntclsb (outlist)
+ call error (0,
+ "Incompatable image and input coordinate list lengths.")
+ }
+
+ # Check that the image and output list lengths match. The number
+ # of output coordinate lists must be 1 or equal to the number of
+ # input images.
+ if (loutlist > 1 && loutlist != limlist) {
+ call imtclose (imlist)
+ call fntclsb (inlist)
+ call fntclsb (outlist)
+ call error (0,
+ "Incompatable image and output coordinate list lengths.")
+ }
+
+ # Loop over the input images.
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Open the input image.
+ im = immap (Memc[image], READ_ONLY, 0)
+ ndim = IM_NDIM(im)
+
+ # Open the input coordinate file.
+ if (linlist <= 0)
+ icl = NULL
+ else if (fntgfnb (inlist, Memc[str], SZ_FNAME) != EOF)
+ icl = open (Memc[str], READ_ONLY, TEXT_FILE)
+ else
+ call seek (icl, BOF)
+
+ # Open the output coordinate file.
+ if (fntgfnb (outlist, Memc[str], SZ_FNAME) != EOF) {
+ ocl = open (Memc[str], NEW_FILE, TEXT_FILE)
+ if (ocl == STDOUT)
+ call fseti (ocl, F_FLUSHNL, YES)
+ }
+
+ # Print optional banner string.
+ if (verbose) {
+ call fprintf (ocl, "\n# Image: %s Wcsin: %s Wcsout: %s\n")
+ call pargstr (Memc[image])
+ call pargstr (Memc[iwcs])
+ call pargstr (Memc[owcs])
+ }
+
+ # Set up the coordinate transform.
+ mw = NULL
+ iferr {
+
+ tmp = mw_openim (im); mw = tmp
+
+ call mw_seti (mw, MW_USEAXMAP, NO)
+ if (inwcs == WT_TV && outwcs == WT_TV)
+ ct = mw_sctran (mw, "logical", "logical", 0)
+ else if (inwcs == WT_TV)
+ ct = mw_sctran (mw, "logical", Memc[owcs], 0)
+ else if (outwcs == WT_TV)
+ ct = mw_sctran (mw, Memc[iwcs], "logical", 0)
+ else
+ ct = mw_sctran (mw, Memc[iwcs], Memc[owcs], 0)
+ wcsndim = mw_stati (mw, MW_NPHYSDIM)
+
+ if (ndim == 0)
+ ndim = wcsndim
+
+ call sscan (Memc[fmtstr])
+ do i = 1, IM_MAXDIM {
+ call malloc (Memi[fmtptrs+i-1], SZ_FNAME, TY_CHAR)
+ call gargwrd (Memc[Memi[fmtptrs+i-1]], SZ_FNAME)
+ if (nscan() != i || Memc[Memi[fmtptrs+i-1]] == EOS) {
+ if (outwcs == WT_WORLD) {
+ iferr (call mw_gwattrs (mw, i, "format",
+ Memc[Memi[fmtptrs+i-1]], SZ_FNAME))
+ Memc[Memi[fmtptrs+i-1]] = EOS
+ } else
+ Memc[Memi[fmtptrs+i-1]] = EOS
+ }
+ }
+
+ } then {
+ if (verbose) {
+ i = errget (Memc[str], SZ_LINE)
+ call fprintf (ocl, "# \tWarning: %s\n")
+ call pargstr (Memc[str])
+ }
+ if (mw != NULL)
+ call mw_close (mw)
+ mw = NULL
+ ct = NULL
+ }
+
+ # Check that the transform is valid.
+ if (ct == NULL) {
+
+ # Skip the image if the transform is undefined.
+ if (verbose) {
+ call fprintf (ocl,
+ "# \tSkipping: Unable to compile requested transform\n")
+ }
+
+ # For input or output tv coordinates the image must be 2D
+ } else if (ndim != 2 && (inwcs == WT_TV || outwcs == WT_TV)) {
+
+ # Skip the image if the transform is undefined.
+ if (verbose) {
+ call fprintf (ocl,
+ "# \tSkipping: Image must be 2D for wcs type tv\n")
+ }
+
+ # Check that the number of input columns is enough for images.
+ } else if ((ncolumns < ndim) || (ncolumns < wcsndim && inwcs !=
+ WT_LOGICAL && inwcs != WT_TV)) {
+
+ if (verbose) {
+ call fprintf (ocl,
+ "# \tSkipping: Too few input coordinate columns\n")
+ }
+
+ } else {
+
+ # Check the dimension of the wcs versus the dimension of the
+ # image and issue a warning if dimensional reduction has taken
+ # place.
+ if (wcsndim > ndim) {
+ if (verbose) {
+ call fprintf (ocl,
+ "# \tWarning: Image has been dimensionally reduced\n")
+ }
+ }
+ if (verbose) {
+ call fprintf (ocl, "\n")
+ }
+
+ # Transform the coordinate file.
+ call wt_transform (im, icl, ocl, Memi[columns], Memi[units],
+ ndim, inwcs, outwcs, mw, ct, Memi[fmtptrs], wcsndim,
+ min_sigdigits)
+
+ }
+
+ # Free the format pointers.
+ do i = 1, IM_MAXDIM
+ call mfree (Memi[fmtptrs+i-1], TY_CHAR)
+
+ # Close the input image.
+ if (mw != NULL)
+ call mw_close (mw)
+ call imunmap (im)
+
+ # Close the input coordinate file if it is not going to be used.
+ if (linlist == limlist)
+ call close (icl)
+
+ # Close the output coordinate file if it is not going to be
+ # appended to.
+ if (loutlist == limlist)
+ call close (ocl)
+ }
+
+ # Close the input coordinate file
+ if (linlist > 0 && linlist < limlist)
+ call close (icl)
+ if (loutlist < limlist)
+ call close (ocl)
+
+ call imtclose (imlist)
+ call fntclsb (inlist)
+ call fntclsb (outlist)
+
+ call sfree (sp)
+end
+
+
+# WT_TRANSFORM -- Transform the input coordinates from the input coordinate
+# system to the output coordinate system.
+
+procedure wt_transform (im, icl, ocl, columns, units, ndim, inwcs, outwcs, mw,
+ ct, fmtptrs, wcsndim, min_sigdigits)
+
+pointer im #I the input image descriptor
+int icl #I the input coordinate file descriptor
+int ocl #I the output coordinate file descriptor
+int columns[ARB] #I the input coordinate columns
+int units[ARB] #I the input coordinate units
+int ndim #I the number of input coordinates
+int inwcs #I the input wcs type
+int outwcs #I the output wcs type
+pointer mw #I the wcs descriptor
+pointer ct #I the pointer to the compiled transformation
+pointer fmtptrs[ARB] #I the array of format pointers
+int wcsndim #I the dimensions of the wcs
+int min_sigdigits #I the minimum number of significant digits
+
+int nline, ip, nread, nwrite, max_fields, nfields, offset
+pointer sp, inbuf, linebuf, field_pos, outbuf, voff, vstep, paxno, laxno, incoo
+pointer lincoo, outcoo, nsig
+int getline(), li_get_numd()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (inbuf, SZ_LINE, TY_CHAR)
+ call salloc (linebuf, SZ_LINE, TY_CHAR)
+ call salloc (field_pos, MAX_FIELDS, TY_INT)
+ call salloc (outbuf, SZ_LINE, TY_CHAR)
+
+ call salloc (voff, wcsndim, TY_DOUBLE)
+ call salloc (vstep, wcsndim, TY_DOUBLE)
+ call salloc (paxno, wcsndim, TY_INT)
+ call salloc (laxno, wcsndim, TY_INT)
+ call salloc (incoo, wcsndim, TY_DOUBLE)
+ call salloc (lincoo, wcsndim, TY_DOUBLE)
+ call salloc (outcoo, wcsndim, TY_DOUBLE)
+ call salloc (nsig, wcsndim, TY_INT)
+
+ call mw_gaxmap (mw, Memi[paxno], Memi[laxno], wcsndim)
+ call wt_laxmap (outwcs, Memi[paxno], wcsndim, Memi[laxno], ndim)
+ call wt_vmap (im, Memd[voff], Memd[vstep], ndim)
+
+ # Compute the number of coordinates to be read and written.
+ if (inwcs == WT_LOGICAL && ndim < wcsndim)
+ nread = ndim
+ else
+ nread = wcsndim
+ if (outwcs == WT_LOGICAL && ndim < wcsndim)
+ nwrite = ndim
+ else
+ nwrite = wcsndim
+ call amovkd (INDEFD, Memd[outcoo], wcsndim)
+
+ max_fields = MAX_FIELDS
+ for (nline = 1; getline (icl, Memc[inbuf]) != EOF; nline = nline + 1) {
+
+ # Skip over leading white space.
+ for (ip = inbuf; IS_WHITE(Memc[ip]); ip = ip + 1)
+ ;
+
+ # Pass on comment and blank lines unchanged.
+ if (Memc[ip] == '#') {
+ # Pass comment lines on to the output unchanged.
+ call putline (ocl, Memc[inbuf])
+ next
+ } else if (Memc[ip] == '\n' || Memc[ip] == EOS) {
+ # Blank lines too.
+ call putline (ocl, Memc[inbuf])
+ next
+ }
+
+ # Expand tabs into blanks, determine field offsets.
+ call strdetab (Memc[inbuf], Memc[linebuf], SZ_LINE, TABSIZE)
+ call li_find_fields (Memc[linebuf], Memi[field_pos], max_fields,
+ nfields)
+
+ # Decode the coordinates checking for valid input.
+ call aclri (Memi[nsig], wcsndim)
+ do ip = 1, nread {
+
+ if (columns[ip] > nfields) {
+ call fstats (icl, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("\tNot enough fields in file %s line %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call putline (ocl, Memc[linebuf])
+ break
+ }
+
+ offset = Memi[field_pos+columns[ip]-1]
+ if (li_get_numd (Memc[linebuf+offset-1],
+ Memd[incoo+ip-1], Memi[nsig+ip-1]) == 0) {
+ call fstats (icl, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("\tBad value in file %s line %d column %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call pargi (ip)
+ call putline (ocl, Memc[linebuf])
+ break
+ }
+
+ if (IS_INDEFD(Memd[incoo+ip-1])) {
+ call fstats (icl, F_FILENAME, Memc[outbuf], SZ_LINE)
+ call eprintf ("\tBad value in file %s line %d column %d\n")
+ call pargstr (Memc[outbuf])
+ call pargi (nline)
+ call pargi (ip)
+ call putline (ocl, Memc[linebuf])
+ break
+ }
+
+ }
+
+ # Skip to next line if too few fields were read.
+ if (ip <= nread)
+ next
+
+ # Adjust the input coordinate units if necessary.
+ switch (inwcs) {
+ case WT_TV:
+ call wt_tvlogd (Memd[incoo], Memd[incoo], nread, Memd[voff],
+ Memd[vstep])
+ case WT_WORLD:
+ call wt_cunits (Memd[incoo], units, nread)
+ default:
+ ;
+ }
+
+ # Compute the transform.
+ call wt_ctrand (ct, Memd[incoo], Memd[lincoo], Memi[paxno],
+ Memd[outcoo], wcsndim, nread)
+
+ # Adjust the output coordinate units if necessary.
+ switch (outwcs) {
+ case WT_TV:
+ call wt_logtvd (Memd[outcoo], Memd[outcoo], wcsndim,
+ Memi[laxno], Memd[voff], Memd[vstep])
+ default:
+ ;
+ }
+
+ # Create the output file line.
+ call rg_apack_lined (Memc[linebuf], Memc[outbuf], SZ_LINE,
+ Memi[field_pos], nfields, columns, nread, Memd[outcoo],
+ Memi[laxno], fmtptrs, Memi[nsig], nwrite, min_sigdigits)
+
+ # Write out the reformatted output line.
+ call putline (ocl, Memc[outbuf])
+
+ }
+
+ call sfree (sp)
+end
+
+
+# WT_LAXMAP (paxno, wcsndim, laxno, ndim)
+
+procedure wt_laxmap (outwcs, paxno, wcsndim, laxno, ndim)
+
+int outwcs #I the output wcs
+int paxno[ARB] #I the physical axis map
+int wcsndim #I the number of physical axis dimensions
+int laxno[ARB] #O the physical axis map
+int ndim #I the number of logical axis dimensions
+
+int i, j
+
+begin
+ if (outwcs == WT_LOGICAL && ndim < wcsndim) {
+ do i = 1, ndim {
+ laxno[i] = 0
+ do j = 1, wcsndim {
+ if (paxno[j] != i)
+ next
+ laxno[i] = j
+ break
+ }
+ }
+ do i = ndim + 1, wcsndim
+ laxno[i] = 0
+ } else {
+ do i = 1, wcsndim
+ laxno[i] = i
+ }
+end
+
+
+# WT_VMAP -- Fetch the image i/o section map. Tecnically this routine
+# violates a system interface and uses the internal definitions in
+# the imio.h file. However this routine is required to support tv coordinates
+# which are coordinates with respect to the current section, and not identical
+# to physcial coordinates.
+
+procedure wt_vmap (im, voff, vstep, ndim)
+
+pointer im #I the input image descriptor
+double voff[ARB] #O the array of offsets
+double vstep[ARB] #O the array of step sizes
+int ndim #I the number of dimensions
+
+int i, dim
+
+begin
+ do i = 1, ndim {
+ dim = IM_VMAP(im,i)
+ voff[i] = IM_VOFF(im,dim)
+ vstep[i] = IM_VSTEP(im,dim)
+ }
+end
+
+
+# WT_UNITS -- Correct the units of the input coordinates if necessary.
+
+procedure wt_cunits (incoo, units, ncoo)
+
+double incoo[ARB] #I the array of input coordinates
+int units[ARB] #I the array of units
+int ncoo #I the number of coordinates
+
+int i
+
+begin
+ do i = 1, ncoo {
+ switch (units[i]) {
+ case WT_UHOURS:
+ incoo[i] = 15.0d0 * incoo[i]
+ default:
+ ;
+ }
+ }
+end
+
+
+# WT_TVLOGD -- Linearly transform a vector of coordinates using an
+# array of voffsets and scale factors.
+
+procedure wt_tvlogd (incoo, outcoo, ndim, voff, vstep)
+
+double incoo[ARB] #I array of input coordinates
+double outcoo[ARB] #O array of output coordinates
+int ndim #I number of coordinates
+double voff[ARB] #I array of zero points
+double vstep[ARB] #I array of scale factors
+
+int i
+
+begin
+ do i = 1, ndim
+ outcoo[i] = (incoo[i] - voff[i]) / vstep[i]
+end
+
+
+# WT_CTRAND -- Transform the coordinates.
+
+procedure wt_ctrand (ct, incoo, lincoo, paxno, outcoo, wcsndim, nread)
+
+pointer ct #I pointer to the compiled transform
+double incoo[ARB] #I array of input coordinates
+double lincoo[ARB] #U scratch array of input coordinates
+int paxno[ARB] #I the physical axis map
+double outcoo[ARB] #O array of output coordinates
+int wcsndim #I the dimension of the wcs
+int nread #I the number of input coordinates.
+
+int i
+
+begin
+ if (nread < wcsndim) {
+ do i = 1, wcsndim {
+ if (paxno[i] == 0)
+ lincoo[i] = 1.0d0
+ else
+ lincoo[i] = incoo[paxno[i]]
+ }
+ if (ct == NULL)
+ call amovd (lincoo, outcoo, wcsndim)
+ else
+ call mw_ctrand (ct, lincoo, outcoo, wcsndim)
+
+ } else {
+ if (ct == NULL)
+ call amovd (incoo, outcoo, wcsndim)
+ else
+ call mw_ctrand (ct, incoo, outcoo, wcsndim)
+ }
+
+end
+
+
+# WT_LOGTVD -- Linearly transform a vector of coordinates using an
+# array of voffsets and scale factors.
+
+procedure wt_logtvd (incoo, outcoo, wcsndim, laxno, voff, vstep)
+
+double incoo[ARB] #I array of input coordinates
+double outcoo[ARB] #O array of output coordinates
+int wcsndim #I number of coordinates
+int laxno[ARB] #I the logical axis map
+double voff[ARB] #I array of zero points
+double vstep[ARB] #I array of scale factors
+
+int i
+
+begin
+ do i = 1, wcsndim {
+ if (laxno[i] != 0)
+ outcoo[laxno[i]] = (incoo[laxno[i]] * vstep[laxno[i]]) +
+ voff[laxno[i]]
+ }
+end
+
+
+# WT_GETLABELS -- Get the next label from a list of labels.
+
+int procedure wt_getlabels (list, ip, label, maxch)
+
+char list[ARB] #I list of labels
+int ip #U pointer in to the list of labels
+char label[ARB] #O the output label
+int maxch #I maximum length of a column name
+
+int op, token
+int ctotok(), strlen()
+
+begin
+ # Decode the column labels.
+ op = 1
+ while (list[ip] != EOS) {
+
+ token = ctotok (list, ip, label[op], maxch)
+ if (label[op] == EOS)
+ next
+ if ((token == TOK_UNKNOWN) || (token == TOK_CHARCON))
+ break
+ if ((token == TOK_PUNCTUATION) && (label[op] == ',')) {
+ if (op == 1)
+ next
+ else
+ break
+ }
+
+ op = op + strlen (label[op])
+ break
+ }
+
+ label[op] = EOS
+ if ((list[ip] == EOS) && (op == 1))
+ return (EOF)
+ else
+ return (op - 1)
+end
+
diff --git a/pkg/images/imcoords/src/t_wcsedit.x b/pkg/images/imcoords/src/t_wcsedit.x
new file mode 100644
index 00000000..51d44992
--- /dev/null
+++ b/pkg/images/imcoords/src/t_wcsedit.x
@@ -0,0 +1,792 @@
+include <fset.h>
+include <imhdr.h>
+include <mwset.h>
+
+define HELPFILE "imcoords$src/wcsedit.key"
+
+define WCSCMDS ",?,show,update,quit,"
+define WCS_HELP 1
+define WCS_SHOW 2
+define WCS_UPDATE 3
+define WCS_QUIT 4
+
+define WCSPARS ",CRVAL,CRPIX,CD,LTV,LTM,WTYPE,AXTYPE,UNITS,LABEL,FORMAT,"
+define WCS_CRVAL 1
+define WCS_CRPIX 2
+define WCS_CD 3
+define WCS_LTV 4
+define WCS_LTM 5
+define WCS_WTYPE 6
+define WCS_AXTYPE 7
+define WCS_UNITS 8
+define WCS_LABEL 9
+define WCS_FORMAT 10
+
+procedure t_wcsedit ()
+
+bool interactive, verbose, update, install
+int wcsdim, parno, naxes1, naxes2, ndim
+pointer sp, imtemplate, image, parameter, ax1list, ax2list, axes1, axes2
+pointer value, wcs, system
+pointer imlist, im, mwim, r, w, cd, ltm, ltv, iltm, nr, ncd
+bool clgetb(), streq(), wcs_iedit()
+int clgeti(), fstati(), wcs_decode_parno(), wcs_decode_axlist(), imtgetim()
+int mw_stati()
+pointer imtopen(), immap(), mw_openim(), mw_open()
+errchk mw_newsystem()
+
+begin
+ if (fstati (STDOUT, F_REDIR) == NO)
+ call fseti (STDOUT, F_FLUSHNL, YES)
+
+ # Allocate working space.
+ call smark (sp)
+ call salloc (imtemplate, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (parameter, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+ call salloc (ax1list, SZ_FNAME, TY_CHAR)
+ call salloc (ax2list, SZ_FNAME, TY_CHAR)
+ call salloc (axes1, IM_MAXDIM, TY_INT)
+ call salloc (axes2, IM_MAXDIM, TY_INT)
+ call salloc (wcs, SZ_FNAME, TY_CHAR)
+ call salloc (system, SZ_FNAME, TY_CHAR)
+
+ # Get the list of images, parameter to be edited, axes lists,
+ # and new parameter value.
+ call clgstr ("image", Memc[imtemplate], SZ_FNAME)
+ interactive = clgetb ("interactive")
+
+ if (! interactive) {
+
+ # Get and check the wcs parameter to be edited.
+ call clgstr ("parameter", Memc[parameter], SZ_FNAME)
+ parno = wcs_decode_parno (Memc[parameter], SZ_FNAME)
+ if (parno <= 0) {
+ call printf ("%s is not a legal WCS parameter\n")
+ call pargstr (Memc[parameter])
+ call sfree (sp)
+ return
+ }
+
+ # Get the new parameter value.
+ call clgstr ("value", Memc[value], SZ_FNAME)
+
+ # Get the axes for which the parameter is to be edited.
+ call clgstr ("axes1", Memc[ax1list], SZ_FNAME)
+ if (parno == WCS_CD || parno == WCS_LTM)
+ call clgstr ("axes2", Memc[ax2list], SZ_FNAME)
+ else
+ Memc[ax2list] = EOS
+
+ # Print any axis decoding error messages.
+ if (wcs_decode_axlist (parno, Memc[ax1list], Memc[ax2list],
+ IM_MAXDIM, Memi[axes1], naxes1, Memi[axes2], naxes2) == ERR) {
+ if (naxes1 <= 0) {
+ call printf ("Error decoding axes1 list\n")
+ } else if ((Memi[axes1] < 1) || (Memi[axes1+naxes1-1] >
+ IM_MAXDIM)) {
+ call printf ("The axes1 values must be >= 1 and <= %d\n")
+ call pargi (IM_MAXDIM)
+ } else if (naxes2 == 0) {
+ call printf ("Error decoding axes2 list\n")
+ } else if ((Memi[axes2] < 1) || (Memi[axes2+naxes2-1] >
+ IM_MAXDIM)) {
+ call printf ("The axes2 values must be >= 1 and <= %d\n")
+ call pargi (IM_MAXDIM)
+ }
+ call sfree (sp)
+ return
+ }
+ }
+
+ # Get the remaining parameters.
+ call clgstr ("wcs", Memc[wcs], SZ_FNAME)
+ wcsdim = clgeti ("wcsdim")
+ verbose = clgetb ("verbose")
+ update = clgetb ("update")
+
+ # Loop over the list of images
+ imlist = imtopen (Memc[imtemplate])
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Remove any image section.
+ call imgimage (Memc[image], Memc[image], SZ_FNAME)
+
+ # Open the image and the wcs.
+ iferr (im = immap (Memc[image], READ_WRITE, 0)) {
+ im = immap (Memc[image], NEW_IMAGE, 0)
+ IM_NDIM(im) = 0
+ ndim = wcsdim
+ mwim = mw_open (NULL, ndim)
+ call mw_newsystem (mwim, Memc[wcs], ndim)
+ } else {
+ mwim = mw_openim (im)
+ iferr (call mw_ssystem (mwim, Memc[wcs])) {
+ call mw_close (mwim)
+ ndim = IM_NDIM(im)
+ mwim = mw_open (NULL, ndim)
+ call mw_newsystem (mwim, Memc[wcs], ndim)
+ } else
+ ndim = mw_stati (mwim, MW_NPHYSDIM)
+ }
+ call mw_gsystem (mwim, Memc[system], SZ_FNAME)
+
+ # Allocate working memory.
+ call malloc (r, ndim * ndim, TY_DOUBLE)
+ call malloc (w, ndim * ndim, TY_DOUBLE)
+ call malloc (cd, ndim * ndim, TY_DOUBLE)
+ call malloc (ltm, ndim * ndim, TY_DOUBLE)
+ call malloc (ltv, ndim, TY_DOUBLE)
+ call malloc (iltm, ndim * ndim, TY_DOUBLE)
+ call malloc (nr, ndim * ndim, TY_DOUBLE)
+ call malloc (ncd, ndim * ndim, TY_DOUBLE)
+
+ # Compute the original world to logical transformation.
+ call mw_gwtermd (mwim, Memd[r], Memd[w], Memd[cd], ndim)
+ call mw_gltermd (mwim, Memd[ltm], Memd[ltv], ndim)
+ call mwvmuld (Memd[ltm], Memd[r], Memd[nr], ndim)
+ call aaddd (Memd[nr], Memd[ltv], Memd[nr], ndim)
+ call mwinvertd (Memd[ltm], Memd[iltm], ndim)
+ call mwmmuld (Memd[cd], Memd[iltm], Memd[ncd], ndim)
+
+ # Edit the wcs.
+ if (interactive) {
+
+ install = wcs_iedit (mwim, Memc[image], Memc[system],
+ Memd[ltv], Memd[ltm], Memd[w], Memd[nr], Memd[ncd],
+ ndim, verbose)
+
+ } else if (streq (Memc[wcs], "physical") || streq (Memc[wcs],
+ "world") || streq (Memc[wcs], Memc[system])) {
+
+ install = false
+ if (Memi[axes1+naxes1-1] > ndim) {
+ call printf ("For image %s axes1 values must be <= %d\n")
+ call pargstr (Memc[image])
+ call pargi (ndim)
+ } else if (Memi[axes2+max(1,naxes2)-1] > ndim) {
+ call printf (
+ "For image %s axes1,2 values must be <= %d\n")
+ call pargstr (Memc[image])
+ call pargi (ndim)
+ } else {
+
+ call wcs_edit (mwim, parno, Memi[axes1], naxes1,
+ Memi[axes2], naxes2, Memc[value], Memd[ltv],
+ Memd[ltm], Memd[w], Memd[nr], Memd[ncd], ndim)
+
+ if (verbose)
+ call wcs_show (mwim, Memc[image], Memc[system],
+ Memd[ltv], Memd[ltm], Memd[w], Memd[nr],
+ Memd[ncd], ndim)
+
+ if (update)
+ install = true
+ }
+
+ } else {
+ call printf ("Cannot find wcs %s for image %s\n")
+ call pargstr (Memc[wcs])
+ call pargstr (Memc[image])
+ }
+
+
+ # Recompute and store the new wcs if update is enabled.
+ if (install) {
+ call mw_sltermd (mwim, Memd[ltm], Memd[ltv], ndim)
+ 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 (mwim, Memd[nr], Memd[w], Memd[cd], ndim)
+ call mw_saveim (mwim, im)
+ }
+
+ # Free the memory.
+ call mfree (r, TY_DOUBLE)
+ call mfree (w, TY_DOUBLE)
+ call mfree (cd, TY_DOUBLE)
+ call mfree (ncd, TY_DOUBLE)
+ call mfree (nr, TY_DOUBLE)
+ call mfree (ltm, TY_DOUBLE)
+ call mfree (ltv, TY_DOUBLE)
+ call mfree (iltm, TY_DOUBLE)
+
+ call mw_close (mwim)
+ call imunmap (im)
+ }
+
+ call imtclose (imlist)
+ call sfree (sp)
+end
+
+
+# WCS_IEDIT -- Interactively edit the wcs.
+
+bool procedure wcs_iedit (mwim, image, system, ltv, ltm, w, r, cd, ndim,
+ verbose)
+
+pointer mwim # pointer to the current wcs
+char image[ARB] # input image name
+char system[ARB] # wcs system name
+double ltv[ARB] # the lterm offsets
+double ltm[ndim,ARB] # the lterm rotation matrix
+double w[ARB] # the fits crval parameters
+double r[ARB] # the fits crpix parameters
+double cd[ndim,ARB] # the fits rotation matrix
+int ndim # the dimension of the wcs
+bool verbose # verbose mode
+
+bool update
+int cmd, parno, naxes1, naxes2
+pointer sp, parameter, value, ax1list, ax2list, axes1, axes2
+int clscan(), strdic(), nscan(), wcs_decode_parno(), wcs_decode_axlist()
+
+begin
+ # Allocate working memory.
+ call smark (sp)
+ call salloc (parameter, SZ_FNAME, TY_CHAR)
+ call salloc (value, SZ_FNAME, TY_CHAR)
+ call salloc (ax1list, SZ_FNAME, TY_CHAR)
+ call salloc (ax2list, SZ_FNAME, TY_CHAR)
+ call salloc (axes1, ndim, TY_INT)
+ call salloc (axes2, ndim, TY_INT)
+
+ # Print the starting wcs.
+ if (verbose)
+ call wcs_show (mwim, image, system, ltv, ltm, w, r, cd, ndim)
+
+ # Loop over the command stream.
+ update = false
+ while (clscan ("commands") != EOF) {
+
+ # Get the command/parameter.
+ call gargwrd (Memc[parameter], SZ_FNAME)
+ if (nscan() < 1)
+ next
+ cmd = strdic (Memc[parameter], Memc[parameter], SZ_FNAME, WCSCMDS)
+
+ switch (cmd) {
+ case WCS_HELP:
+ call pagefile (HELPFILE, "")
+ case WCS_SHOW:
+ call wcs_show (mwim, image, system, ltv, ltm, w, r, cd, ndim)
+ case WCS_UPDATE:
+ update = true
+ break
+ case WCS_QUIT:
+ update = false
+ break
+ default:
+ call gargwrd (Memc[value], SZ_FNAME)
+ call gargwrd (Memc[ax1list], SZ_FNAME)
+ call gargwrd (Memc[ax2list], SZ_FNAME)
+ parno = wcs_decode_parno (Memc[parameter], SZ_FNAME)
+ if (parno <= 0) {
+ call printf ("%s is not a legal WCS parameter\n")
+ call pargstr (Memc[parameter])
+ } else if (nscan() < 2) {
+ call wcs_pshow (mwim, parno, image, system, ltv, ltm, w,
+ r, cd, ndim)
+ } else if (wcs_decode_axlist (parno, Memc[ax1list],
+ Memc[ax2list], IM_MAXDIM, Memi[axes1], naxes1, Memi[axes2],
+ naxes2) == OK) {
+ call wcs_edit (mwim, parno, Memi[axes1], naxes1,
+ Memi[axes2], naxes2, Memc[value], ltv, ltm, w, r, cd,
+ ndim)
+ if (verbose)
+ call wcs_pshow (mwim, parno, image, system, ltv, ltm,
+ w, r, cd, ndim)
+ } else if (naxes1 <= 0) {
+ call printf ("Error decoding axes1 list\n")
+ } else if ((Memi[axes1] < 1) || (Memi[axes1+naxes1-1] > ndim)) {
+ call printf ("The axes1 values must be >= 1 and <= %d\n")
+ call pargi (ndim)
+ } else if (naxes2 <= 0) {
+ call printf ("Error decoding axes2 list\n")
+ } else if ((Memi[axes2] < 1) || (Memi[axes2+naxes2-1] > ndim)) {
+ call printf ("The axes1 values must be >= 1 and <= %d\n")
+ call pargi (ndim)
+ }
+ }
+ }
+
+ call sfree (sp)
+
+ return (update)
+end
+
+
+# WCS_EDIT -- Edit the wcs.
+
+procedure wcs_edit (mwim, parameter, axis1, naxis1, axis2, naxis2, value, ltv,
+ ltm, w, r, cd, ndim)
+
+pointer mwim # pointer to the current wcs
+int parameter # parameter to be changed
+int axis1[ARB] # list of axes1 for which to change value
+int naxis1 # number of axis for to change value
+int axis2[ARB] # list of cross-term axes
+int naxis2 # number of cross-term axes
+char value[ARB] # new wcs parameter value
+double ltv[ARB] # the lterm offsets
+double ltm[ndim,ARB] # the lterm rotation matrix
+double w[ARB] # the fits crval parameters
+double r[ARB] # the fits crpix parameters
+double cd[ndim,ARB] # the fits rotation matrix
+int ndim # the dimension of the wcs
+
+double dval
+int i, j, ip
+int ctod()
+
+begin
+ ip = 1
+ switch (parameter) {
+ case WCS_CRVAL:
+ if (ctod (value, ip, dval) > 0) {
+ do i = 1, naxis1
+ w[axis1[i]] = dval
+ }
+ case WCS_CRPIX:
+ if (ctod (value, ip, dval) > 0) {
+ do i = 1, naxis1
+ r[axis1[i]] = dval
+ }
+ case WCS_CD:
+ if (ctod (value, ip, dval) > 0) {
+ if (naxis2 == 0) {
+ do i = 1, naxis1
+ cd[axis1[i],axis1[i]] = dval
+ } else {
+ do i = 1, naxis1
+ do j = 1, naxis2
+ cd[axis2[j],axis1[i]] = dval
+ }
+ }
+ case WCS_LTV:
+ if (ctod (value, ip, dval) > 0) {
+ do i = 1, naxis1
+ ltv[axis1[i]] = dval
+ }
+ case WCS_LTM:
+ if (ctod (value, ip, dval) > 0) {
+ if (naxis2 == 0) {
+ do i = 1, naxis1
+ ltm[axis1[i],axis1[i]] = dval
+ } else {
+ do i = 1, naxis1
+ do j = 1, naxis2
+ ltm[axis1[i],axis2[j]] = dval
+ }
+ }
+ case WCS_WTYPE:
+ do i = 1, naxis1 {
+ call mw_swtype (mwim, axis1[i], 1, value, "")
+ call mw_swattrs (mwim, axis1[i], "wtype", value)
+ }
+ case WCS_AXTYPE:
+ do i = 1, naxis1
+ call mw_swattrs (mwim, axis1[i], "axtype", value)
+ case WCS_UNITS:
+ do i = 1, naxis1
+ call mw_swattrs (mwim, axis1[i], "units", value)
+ case WCS_LABEL:
+ do i = 1, naxis1
+ call mw_swattrs (mwim, axis1[i], "label", value)
+ case WCS_FORMAT:
+ do i = 1, naxis1
+ call mw_swattrs (mwim, axis1[i], "format", value)
+ default:
+ ;
+ }
+end
+
+
+# WCS_SHOW -- Print a quick summary of the current wcs.
+
+procedure wcs_show (mwim, image, system, ltv, ltm, w, r, cd, ndim)
+
+pointer mwim # pointer to the current wcs
+char image[ARB] # name of the imput image
+char system[ARB] # name of the input wcs
+double ltv[ARB] # the lterm offsets
+double ltm[ndim,ARB] # the lterm rotation matrix
+double w[ARB] # the fits crval parameters
+double r[ARB] # the fits crpix parameters
+double cd[ndim,ARB] # the fits rotation matrix
+int ndim # the dimension of the wcs
+
+int i,j
+pointer sp, str
+errchk mw_gwattrs()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print the image name and current wcs.
+ call printf ("\nIMAGE: %s CURRENT WCS: %s\n")
+ call pargstr (image)
+ call pargstr (system)
+
+ # Print the axis banner.
+ call printf (" AXIS ")
+ do i = 1, ndim {
+ call printf ("%8d ")
+ call pargi (i)
+ }
+ call printf ("\n")
+
+ # Print the crval parameters.
+ call printf (" CRVAL ")
+ do i = 1, ndim {
+ call printf ("%8g ")
+ call pargd (w[i])
+ }
+ call printf ("\n")
+
+ # Print the crpix parameters.
+ call printf (" CRPIX ")
+ do i = 1, ndim {
+ call printf ("%8g ")
+ call pargd (r[i])
+ }
+ call printf ("\n")
+
+ # Print the cd matrix.
+ do i = 1, ndim {
+ call printf (" CD %d ")
+ call pargi (i)
+ do j = 1, ndim {
+ call printf ("%8g ")
+ call pargd (cd[j,i])
+ }
+ call printf ("\n")
+ }
+
+ # Print the ltv parameters.
+ call printf (" LTV ")
+ do i = 1, ndim {
+ call printf ("%8g ")
+ call pargd (ltv[i])
+ }
+ call printf ("\n")
+
+ # Print the ltm matrix.
+ do i = 1, ndim {
+ call printf (" LTM %d ")
+ call pargi (i)
+ do j = 1, ndim {
+ call printf ("%8g ")
+ call pargd (ltm[i,j])
+ }
+ call printf ("\n")
+ }
+
+ # Print the transformation type.
+ call printf (" WTYPE ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "wtype", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the axis type.
+ call printf (" AXTYPE ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "axtype", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the units.
+ call printf (" UNITS ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "units", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the label.
+ call printf (" LABEL ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "label", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the format.
+ call printf (" FORMAT ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "format", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# WCS_PSHOW -- Print the current values of a specific parameter.
+
+procedure wcs_pshow (mwim, parno, image, system, ltv, ltm, w, r, cd, ndim)
+
+pointer mwim # pointer to the current wcs
+int parno # print the parameter number
+char image[ARB] # name of the imput image
+char system[ARB] # name of the input wcs
+double ltv[ARB] # the lterm offsets
+double ltm[ndim,ARB] # the lterm rotation matrix
+double w[ARB] # the fits crval parameters
+double r[ARB] # the fits crpix parameters
+double cd[ndim,ARB] # the fits rotation matrix
+int ndim # the dimension of the wcs
+
+int i,j
+pointer sp, str
+errchk mw_gwattrs()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (str, SZ_LINE, TY_CHAR)
+
+ # Print the image name and current wcs.
+ call printf ("\nIMAGE: %s CURRENT WCS: %s\n")
+ call pargstr (image)
+ call pargstr (system)
+
+ # Print the axis banner.
+ call printf (" AXIS ")
+ do i = 1, ndim {
+ call printf ("%8d ")
+ call pargi (i)
+ }
+ call printf ("\n")
+
+ switch (parno) {
+ # Print the crval parameters.
+ case WCS_CRVAL:
+ call printf (" CRVAL ")
+ do i = 1, ndim {
+ call printf ("%8g ")
+ call pargd (w[i])
+ }
+ call printf ("\n")
+
+ # Print the crpix parameters.
+ case WCS_CRPIX:
+ call printf (" CRPIX ")
+ do i = 1, ndim {
+ call printf ("%8g ")
+ call pargd (r[i])
+ }
+ call printf ("\n")
+
+ # Print the cd matrix.
+ case WCS_CD:
+ do i = 1, ndim {
+ call printf (" CD %d ")
+ call pargi (i)
+ do j = 1, ndim {
+ call printf ("%8g ")
+ call pargd (cd[j,i])
+ }
+ call printf ("\n")
+ }
+
+ # Print the ltv parameters.
+ case WCS_LTV:
+ call printf (" LTV ")
+ do i = 1, ndim {
+ call printf ("%8g ")
+ call pargd (ltv[i])
+ }
+ call printf ("\n")
+
+ # Print the ltm matrix.
+ case WCS_LTM:
+ do i = 1, ndim {
+ call printf (" LTM %d ")
+ call pargi (i)
+ do j = 1, ndim {
+ call printf ("%8g ")
+ call pargd (ltm[i,j])
+ }
+ call printf ("\n")
+ }
+
+ # Print the transformation type.
+ case WCS_WTYPE:
+ call printf (" WTYPE ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "wtype", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the axis type.
+ case WCS_AXTYPE:
+ call printf (" AXTYPE ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "axtype", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the units.
+ case WCS_UNITS:
+ call printf (" UNITS ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "units", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the label.
+ case WCS_LABEL:
+ call printf (" LABEL ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "label", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+
+ # Print the format.
+ case WCS_FORMAT:
+ call printf (" FORMAT ")
+ do i = 1, ndim {
+ iferr (call mw_gwattrs (mwim, i, "format", Memc[str], SZ_LINE))
+ Memc[str] = EOS
+ call printf ("%8s ")
+ call pargstr (Memc[str])
+ }
+ call printf ("\n")
+ default:
+ call printf ("Unknown WCS parameter\n")
+ }
+ call printf ("\n")
+
+ call sfree (sp)
+end
+
+
+# WCS_DECODE_PARNO -- Decode the WCS parameter
+
+int procedure wcs_decode_parno (parameter, maxch)
+
+char parameter[ARB] # parameter name
+int maxch # maximum length of parameter name
+
+int parno
+int strdic()
+
+begin
+ # Get and check the wcs parameter to be edited.
+ call strupr (parameter)
+ parno = strdic (parameter, parameter, maxch, WCSPARS)
+ if (parno <= 0)
+ return (ERR)
+ else
+ return (parno)
+end
+
+
+# WCS_DECODE_AXES -- Decode the axes lists.
+
+int procedure wcs_decode_axlist (parno, ax1list, ax2list, max_naxes, axes1,
+ naxes1, axes2, naxes2)
+
+int parno # parameter to be edited
+char ax1list[ARB] # principal axes list
+char ax2list[ARB] # secondary axes list
+int max_naxes # maximum number of axes to decode
+int axes1[ARB] # list of principal axes to be edited
+int naxes1 # number of principal axes to be edited
+int axes2[ARB] # list of secondary axes to be edited
+int naxes2 # number of secondary axes to be edited
+
+int wcs_getaxes()
+
+begin
+ naxes1 = wcs_getaxes (ax1list, axes1, max_naxes)
+ if (naxes1 <= 0 || naxes1 > max_naxes)
+ return (ERR)
+ else if ((axes1[1] < 1) || (axes1[naxes1] > max_naxes))
+ return (ERR)
+
+ # Get the second list of axes.
+ if ((parno == WCS_CD) || (parno == WCS_LTM)) {
+ naxes2 = wcs_getaxes (ax2list, axes2, max_naxes)
+ if (ax2list[1] == EOS)
+ return (OK)
+ else if (naxes2 == 0)
+ return (ERR)
+ else if ((axes2[1] < 0) || (axes2[naxes2] > max_naxes))
+ return (ERR)
+ } else {
+ naxes2 = naxes1
+ call amovi (axes1, axes2, naxes1)
+ }
+
+ return (OK)
+end
+
+
+define MAX_NRANGES 10
+
+# WCS_GETAXES -- Decode the input axis list.
+
+int procedure wcs_getaxes (axlist, axes, max_naxes)
+
+char axlist[ARB] # the axis list to be decoded
+int axes[ARB] # the output decode axes
+int max_naxes # the maximum number of output axes
+
+int naxes, axis, ranges[3,MAX_NRANGES+1]
+int decode_ranges(), get_next_number()
+
+begin
+ # Clear the axes array.
+ call aclri (axes, max_naxes)
+
+ # Check for a blank string.
+ if (axlist[1] == EOS)
+ return (0)
+
+ # Check for an illegal axis list string.
+ if (decode_ranges (axlist, ranges, MAX_NRANGES, naxes) == ERR)
+ return (0)
+
+ naxes = 0
+ axis = 0
+ while ((naxes < max_naxes) && (get_next_number (ranges, axis) != EOF)) {
+ naxes = naxes + 1
+ axes[naxes] = axis
+ }
+
+ return (naxes)
+end
diff --git a/pkg/images/imcoords/src/t_wcsreset.x b/pkg/images/imcoords/src/t_wcsreset.x
new file mode 100644
index 00000000..d7c24f27
--- /dev/null
+++ b/pkg/images/imcoords/src/t_wcsreset.x
@@ -0,0 +1,142 @@
+include <error.h>
+include <imhdr.h>
+include <mwset.h>
+
+# T_WCSRESET -- Initialize the image wcs. The user can initialize the
+# pre-defined "physical" or "world" coodinate systems, or a named
+# user world coordinate system, for example the "multipsec" world
+# coordinate system. If the image does not have a previously defined wcs
+# then wcsreset will create the identify wcs.
+
+procedure t_wcsreset ()
+
+bool verbose
+int ndim
+pointer sp, imnamelist, image, wcs, system
+pointer r, w, cd, ncd, nr, ltv, iltm, ltm
+pointer imlist, im, mwim, mw
+bool clgetb(), streq()
+int imtgetim(), mw_stati()
+pointer imtopen(), immap(), mw_openim(), mw_open()
+errchk mw_openim()
+
+begin
+ # Allocate working space.
+ call smark (sp)
+ call salloc (imnamelist, SZ_FNAME, TY_CHAR)
+ call salloc (image, SZ_FNAME, TY_CHAR)
+ call salloc (wcs, SZ_FNAME, TY_CHAR)
+ call salloc (system, SZ_FNAME, TY_CHAR)
+
+ # Get the parameters.
+ call clgstr ("image", Memc[imnamelist], SZ_FNAME)
+ call clgstr ("wcs", Memc[wcs], SZ_FNAME)
+ verbose = clgetb ("verbose")
+
+ # Loop through the list of images.
+ imlist = imtopen (Memc[imnamelist])
+ while (imtgetim (imlist, Memc[image], SZ_FNAME) != EOF) {
+
+ # Remove any image section.
+ call imgimage (Memc[image], Memc[image], SZ_FNAME)
+
+ # Open the image.
+ im = immap (Memc[image], READ_WRITE, 0)
+ iferr {
+ if (verbose) {
+ call printf ("Initializing wcs %s for image %s\n")
+ call pargstr (Memc[wcs])
+ call pargstr (Memc[image])
+ }
+ mwim = mw_openim (im)
+ } then {
+ mwim = NULL
+ } else {
+ call mw_gsystem (mwim, Memc[system], SZ_FNAME)
+ }
+
+ # Reset the lterm only if the wcs is "physical".
+ if (streq (Memc[wcs], "physical") && mwim != NULL) {
+
+ # Allocate space for the transforms.
+ ndim = mw_stati (mwim, MW_NPHYSDIM)
+ call malloc (r, ndim * ndim, TY_DOUBLE)
+ call malloc (w, ndim * ndim, TY_DOUBLE)
+ call malloc (cd, ndim * ndim, TY_DOUBLE)
+ call malloc (ltm, ndim * ndim, TY_DOUBLE)
+ call malloc (ltv, ndim, TY_DOUBLE)
+ call malloc (iltm, ndim * ndim, TY_DOUBLE)
+ call malloc (nr, ndim * ndim, TY_DOUBLE)
+ call malloc (ncd, ndim * ndim, TY_DOUBLE)
+
+ call mw_gwtermd (mwim, Memd[r], Memd[w], Memd[cd], ndim)
+ call mw_gltermd (mwim, Memd[ltm], Memd[ltv], ndim)
+ call mwvmuld (Memd[ltm], Memd[r], Memd[nr], ndim)
+ call aaddd (Memd[nr], Memd[ltv], Memd[nr], ndim)
+ call mwinvertd (Memd[ltm], Memd[iltm], ndim)
+ call mwmmuld (Memd[cd], Memd[iltm], Memd[ncd], ndim)
+ call mw_swtermd (mwim, Memd[nr], Memd[w], Memd[ncd], ndim)
+ call wcs_terminit (Memd[ltm], Memd[ltv], ndim)
+ call mw_sltermd (mwim, Memd[ltm], Memd[ltv], ndim)
+ call mw_saveim (mwim, im)
+
+ # Free the space.
+ call mfree (r, TY_DOUBLE)
+ call mfree (w, TY_DOUBLE)
+ call mfree (cd, TY_DOUBLE)
+ call mfree (ncd, TY_DOUBLE)
+ call mfree (nr, TY_DOUBLE)
+ call mfree (ltm, TY_DOUBLE)
+ call mfree (ltv, TY_DOUBLE)
+ call mfree (iltm, TY_DOUBLE)
+
+ # Cannot replace physical system for unknown world system.
+ } else if (streq (Memc[wcs], "physical") && mwim == NULL) {
+ if (verbose) {
+ call printf ("\tCannot initialize wcs %s for image %s\n")
+ call pargstr (Memc[wcs])
+ call pargstr (Memc[image])
+ }
+ } else if (streq (Memc[wcs], "world") || streq (Memc[wcs],
+ Memc[system])) {
+
+ ndim = IM_NDIM(im)
+ mw = mw_open (NULL, ndim)
+ call mw_saveim (mw, im)
+ call mw_close (mw)
+
+ # The named wcs is not present.
+ } else {
+ call eprintf ("\tCannot find wcs %s\n")
+ call pargstr (Memc[wcs])
+ }
+
+ if (mwim != NULL)
+ call mw_close (mwim)
+
+ call imunmap (im)
+
+ }
+
+ call imtclose (imlist)
+
+ call sfree (sp)
+end
+
+
+# WCS_TERMINIT -- Initialize the shift term and rotation matrix.
+
+procedure wcs_terminit (ltm, ltv, ndim)
+
+double ltm[ndim,ndim] # the rotation matrix
+double ltv[ndim] # the shift vector
+int ndim # the number of dimensions
+
+int i
+
+begin
+ call aclrd (ltm, ndim * ndim)
+ do i = 1, ndim
+ ltm[i,i] = 1.0d0
+ call aclrd (ltv, ndim)
+end
diff --git a/pkg/images/imcoords/src/ttycur.key b/pkg/images/imcoords/src/ttycur.key
new file mode 100644
index 00000000..f91b2185
--- /dev/null
+++ b/pkg/images/imcoords/src/ttycur.key
@@ -0,0 +1,49 @@
+ INTERACTIVE KEYSTROKE COMMANDS
+
+The following commands must be terminated by a carriage return.
+
+? Print help
+: Execute colon command
+data Measure object
+q Exit task
+
+
+ VALID DATA STRING
+
+x/ra/long y/dec/lat [pmra pmdec [parallax radial velocity]]
+
+... x/ra/long y/dec/lat must be in pixels or the input units
+... pmra and pmdec must be in " / year
+... parallax must be in "
+... radial velocity must be in km / sec
+
+ COLON COMMANDS
+
+The following commands must be terminated by a carriage return.
+
+:show Show the input and output coordinate systems
+:isystem [string] Show / set the input coordinate system
+:osystem [string] Show / set the output coordinate system
+:iunits [string string] Show / set the input coordinate units
+:ounits [string string] Show / set the output coordinate units
+:oformat [string string] Show / set the output coordinate format
+
+ VALID INPUT AND OUTPUT COORDINATE SYSTEMS
+
+image [logical/tv/physical/world]
+equinox [epoch]
+noefk4 [equinox [epoch]]
+fk4 [equinox [epoch]]
+fk5 [equinox [epoch]]
+icrs [equinox [epoch]]
+apparent epoch
+ecliptic epoch
+galactic [epoch]
+supergalactic [epoch]
+
+ VALID INPUT AND OUTPUT CELESTIAL COORDINATE UNITS
+ AND THEIR DEFAULT FORMATS
+
+hours %12.3h
+degrees %12.2h
+radians %13.7g
diff --git a/pkg/images/imcoords/src/wcsedit.key b/pkg/images/imcoords/src/wcsedit.key
new file mode 100644
index 00000000..61d98ceb
--- /dev/null
+++ b/pkg/images/imcoords/src/wcsedit.key
@@ -0,0 +1,24 @@
+ WCSEDIT COMMANDS
+
+ BASIC COMMANDS
+
+
+? Print the WCSEDIT commands
+show Print out the current WCS
+update Quit WCSEDIT and update the image WCS
+quit Quit WCSEDIT without updating the image wcs
+
+
+ PARAMETER DISPLAY AND EDITING COMMANDS
+
+crval [value axes1] Show/set the FITS crval parameter(s)
+crpix [value axes1] Show/set the FITS crpix parameter(s)
+cd [value axes1 [axes2]] Show/set the FITS cd parameter(s)
+ltv [value axes1] Show/set the IRAF ltv parameter(s)
+ltm [value axes1 [axes2]] Show/set the IRAF ltm parameter(s)
+wtype [value axes1] Show/set the FITS/IRAF axes transform(s)
+axtype [value axes1] Show/set the FITS/IRAF axis type(s)
+units [value axes1] Show/set the IRAF axes units(s)
+label [value axes1] Show/set the IRAF axes label(s)
+format [value axes1] Show/set the IRAF axes coordinate format(s)
+
diff --git a/pkg/images/imcoords/src/x_starfind.x b/pkg/images/imcoords/src/x_starfind.x
new file mode 100644
index 00000000..865a795d
--- /dev/null
+++ b/pkg/images/imcoords/src/x_starfind.x
@@ -0,0 +1 @@
+task starfind = t_starfind
diff --git a/pkg/images/imcoords/starfind.par b/pkg/images/imcoords/starfind.par
new file mode 100644
index 00000000..73d80255
--- /dev/null
+++ b/pkg/images/imcoords/starfind.par
@@ -0,0 +1,25 @@
+# STARFIND
+
+image,f,a,,,,Input image
+output,f,a,default,,,Output star list
+hwhmpsf,r,a,1.0,,,HWHM of the PSF in pixels
+threshold,r,a,100.0,0.0,,Detection threshold in ADU
+datamin,r,h,INDEF,,,Minimum good data value in ADU
+datamax,r,h,INDEF,,,Maximum good data value in ADU
+fradius,r,h,2.5,1.0,,Fitting radius in HWHM
+sepmin,r,h,5.0,1.0,,Minimum separation in HWHM
+npixmin,i,h,5,5,,Minimum number of good pixels above background
+maglo,r,h,INDEF,,,Lower magnitude limit
+maghi,r,h,INDEF,,,Upper magnitude limit
+roundlo,r,h,0.0,0.0,,Lower ellipticity limit
+roundhi,r,h,0.2,0.0,1.0,Upper ellipticity limit
+sharplo,r,h,0.5,,,Lower sharpness limit
+sharphi,r,h,2.0,,,Upper sharpness limit
+wcs,s,h,"",,,"World coordinate system (logical,physical,world)"
+wxformat,s,h,"",,,The x axis world coordinate format
+wyformat,s,h,"",,,The y axis world coordinate format
+boundary,s,h,nearest,"|nearest|constant|reflect|wrap",,"Boundary extension (nearest,constant,reflect,wrap)"
+constant,r,h,0.0,,,Constant for constant boundary extension
+nxblock,i,h,INDEF,,,X dimension of working block size in pixels
+nyblock,i,h,256,,,Y dimension of working block size in pixels
+verbose,b,h,no,,,Print messages about the progress of the task
diff --git a/pkg/images/imcoords/wcsctran.par b/pkg/images/imcoords/wcsctran.par
new file mode 100644
index 00000000..ec8ad4ad
--- /dev/null
+++ b/pkg/images/imcoords/wcsctran.par
@@ -0,0 +1,12 @@
+# Parameter file for the WCSTRAN task.
+
+input,s,a,"",,,The input coordinate files
+output,s,a,"",,,The output coordinate files
+image,f,a,"",,,The input images
+inwcs,s,a,"logical","|logical|tv|physical|world|",,The input coordinate system
+outwcs,s,a,"world","|logical|tv|physical|world|",,The output coordinate system
+columns,s,h,"1 2 3 4 5 6 7",,,List of input file columns
+units,s,h,"",,,List of input coordinate units
+formats,s,h,"",,,List of output coordinate formats
+min_sigdigits,i,h,7,,,Minimum precision of output coordinates
+verbose,b,h,yes,,,Write comments to the output file ?
diff --git a/pkg/images/imcoords/wcsedit.par b/pkg/images/imcoords/wcsedit.par
new file mode 100644
index 00000000..3b40ef98
--- /dev/null
+++ b/pkg/images/imcoords/wcsedit.par
@@ -0,0 +1,13 @@
+# Parameter file for WCSEDIT
+
+image,f,a,,,,"List of input images"
+parameter,s,a,,,,"The wcs parameter to be edited"
+value,s,a,,,,"The new parameter value"
+axes1,s,a,"",,,"Independent axes for which parameter is to be edited"
+axes2,s,a,"",,,"Dependent axes for which parameter is to be edited"
+wcs,s,h,"world",,,"Default world coordinate system to be edited"
+wcsdim,i,h,2,1,,"WCS dimensionality for new images"
+interactive,b,h,no,,,"Interactive mode ?"
+commands,*s,h,,,,"wcsedit"
+verbose,b,h,yes,,,"Print messages about actions taken ?"
+update,b,h,yes,,,"Update the image header ?"
diff --git a/pkg/images/imcoords/wcsreset.par b/pkg/images/imcoords/wcsreset.par
new file mode 100644
index 00000000..6a12652a
--- /dev/null
+++ b/pkg/images/imcoords/wcsreset.par
@@ -0,0 +1,5 @@
+# Parameter file for WCSRESET
+
+image,f,a,,,,"List of input images"
+wcs,s,a,physical,,,"Name of wcs to be initialized"
+verbose,b,h,yes,,,"Print messages about actions taken ?"