diff options
Diffstat (limited to 'pkg/images/imcoords')
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 ?" |