Here we consider a family of OTW codes that deal with one fairly simple task: linear XY coordinate transformation. By this I mean we apply a rotation, translation, and/or scale adjustment using two linearly indpendent trasformation equations of the form:
The set2 coordinates are transformed to the set1 system via the relations: Xset1 = avals(1) + avals(2)*Xset2 + avals(3)*Yset2 Yset1 = avals(4) + avals(5)*Xset2 + avals(6)*Yset2
% xy_tranrot_res.sh --help Help Information for: xy_tranrot_res.sh Usage: xy_tranrot_res.sh xy.1 xy.2 Y arg1 - name of input XY file 1 arg2 - name of input XY file 2 arg3 - Do files have "# data" headers? (Y or N) I will show: /home/sco/sco/codes/bash/HELP_FILES/xy_tranrot_res.sh.help Enter any key to roceed with the view of help: Return xy_tranrot_res.sh Compare two files of XY values by computing X,Y residusals. Each file must have X (in column 1) and Y (in column 2). The files may or may not have "# data" headers. The third argument on the command line identifies this header state. It is true that the files must be the same in this regard: eith they both have headers, or they both do not.
This collection of routines were built to handle simple files of X,Y lists. The files have no headers, and are usually generated on the fly by other scripts. The scripts (shown below) allow you to derive a linear XY transormation (xy_tranrot_fit.sh), then you can apply this transormation to a set of XY coordiantes (xy_tranrot_apply.sh). Finally, to acess how well the transofmation works, there is a module that computed residuals between the original and predicted XY sets (xy_tranrot_res.sh). Here are some more verbose descriptions of each routine:
xy_tranrot_fit.sh == derive the 6 transformation coefficents (i.e. fill the avals(i=1,6) array. xy_tranrot_apply.sh == Convert a file of X,Y value using the expressions derived with xy_tranrot_fit.sh xy_tranrot_res.sh == compute residuals and mean statistics for two sets of (X,Y). We can use this to evaluate the "goodness of fit" from xy_tranrot_fit.sh. xy_tranrot_image.sh == Very much like xy_tranrot_apply.sh, except the transformations are applied to pixel position in Image_1 to predict positions in Image_2. In this way we can replace pixels in Image_1 with the Image_2 and hence computed a spatially transformed image. This is commonly used for image registration and stacking procedures.Below I present usage messages for these routines.
% xy_tranrot_fit.sh list1.xy_define list2.xy_to_transform Usage: xy_tranrot_fit.sh list1.xy_define list2.xy_to_transform arg1 - name of input XY_1 file (XY defining system to be transformed to, set1) arg2 - name of input XY_2 file (XY to be transformed, set2) NOTE: THis creates the coefficients file called xy_tranrot_fit.out_explain % xy_tranrot_apply.sh list.xy xy_tranrot_fit.out_explain Usage: xy_tranrot_apply.sh list.xy xy_tranrot_fit.out_explain arg1 - name of input XY file arg2 - name of solution file (from xy_tranrot_fit.sh) % xy_tranrot_res.sh xy.1 xy.2 Y Usage: xy_tranrot_res.sh xy.1 xy.2 Y arg1 - name of input XY file 1 arg2 - name of input XY file 2 arg3 - Do files have "# data" headers? (Y or N) % xy_tranrot_image.sh acam_empty.fits dss.fits xy_tranrot_fit.out_explain acam_dss.fits Usage: xy_tranrot_image.sh acam_empty.fits dss.fits xy_tranrot_fit.out_explain acam_dss.fits arg1 - input FITS image to be filled arg2 - FITS image contributing pixel values arg3 - XY transform to go from arg1 to arg2 arg4 - output image name
Below I show some practical runs with the data files and script (FIT) thate does everything. One point that is not too clear above is that I wriote this stuff to use simple X,Y data files, just pasted columns with no "# data" headers or anything. The second set of corrdinates (set2 or list2 above) are the ones TO BE TRANSFORMED to the system defined by the set1 coordinates. Below is a script that might make this clear. I also show some out put and data files.
The script (FIT): #!/bin/bash # Check command line arguments if [ -z "$1" ] then printf "Usage: FIT R\n" printf "arg1 - Fit R or B data (for files Table.R or Table.B) \n" exit fi chan="$1" fdat="Table.$chan" printf "\nLRS2-$chan Transformations \n" printf "Processing file = $fdat\n" # Build the column files colget.py $fdat 9 Xacam N colget.py $fdat 10 Yacam N colget.py $fdat 11 Xlrs2 N colget.py $fdat 12 Ylrs2 N # paste together the XY sets paste Xacam Yacam > XY.acam paste Xlrs2 Ylrs2 > XY.lrs2 #================================================================================== # Fit the ACAM to LRS2 transform xy_tranrot_fit.sh XY.lrs2 XY.acam > junk.1 mv xy_tranrot_fit.out_explain coefs.ACAM_to_LRS2 # Use the fit to convert acam XY to the lrs2 XY xy_tranrot_apply.sh XY.acam coefs.ACAM_to_LRS2 > XY.lrs2_predicted mv coefs.ACAM_to_LRS2 coefs.ACAM_to_LRS2_$chan # Now compare the two sets of lrs2 coordinates xy_tranrot_res.sh XY.lrs2 XY.lrs2_predicted > stats read sigx sigy np < stats printf "\nFor the XY_acam to XY_lrs2 transformations: \n" printf "X sigma in LRS2 coordinates = $sigx (arcseconds) \n" printf "Y sigma in LRS2 coordinates = $sigy (arcseconds) \n" printf "Number of points in fit = $np \n" #================================================================================== #================================================================================== # Fit the LRS2 to ACAM transform xy_tranrot_fit.sh XY.acam XY.lrs2 > junk.1 mv xy_tranrot_fit.out_explain coefs.LRS2_to_ACAM # Use the fit to convert lrs2 XY to the acam XY xy_tranrot_apply.sh XY.lrs2 coefs.LRS2_to_ACAM > XY.acam_predicted mv coefs.LRS2_to_ACAM coefs.LRS2_to_ACAM_$chan # Now compare the two sets of acam coordinates xy_tranrot_res.sh XY.acam XY.acam_predicted > stats read sigx sigy np < stats printf "\nFor the XY_lrs2 to XY_acam transformations: \n" printf "X sigma in ACAM coordinates = $sigx (pixel) \n" printf "Y sigma in ACAM coordinates = $sigy (pixels) \n" printf "Number of points in fit = $np \n" #================================================================================== # clean up \rm -f coefs.acam_to_lrs2 head.lines junk.1 pars.in stats Xacam Xlrs2 XY.acam XY.acam_predicted XY.lrs2 XY.lrs2_predicted Yacam Ylrs2 Here is the initial file: % cat Table.B p# chan obs exp Date dx_ang dy_ang Associated ACAM image Xacam Yacam Xlrs2 Ylrs2 # data 10 B 009 01 20160816 0.0 0.0 20160816T041516.4_acm_sci.fits 710.69 185.59 +0.395 -0.217 11 B 009 02 20160816 +3.0 +2.0 20160816T042017.0_acm_sci.fits 716.97 174.16 +3.448 -2.255 12 B 009 03 20160816 -3.0 -2.0 20160816T043321.8_acm_sci.fits 710.74 184.59 +0.643 -0.326 13 B 009 04 20160816 +4.0 +2.0 20160816T044347.1_acm_sci.fits 715.33 169.19 +4.630 -2.038 14 B 009 05 20160816 -4.0 -2.0 20160816T045108.1_acm_sci.fits 709.05 184.86 +0.450 -0.054 15 B 009 06 20160816 -3.0 -1.0 20160816T045727.2_acm_sci.fits 704.45 194.34 -2.492 +1.060 16 B 009 07 20160816 +3.0 +1.0 20160816T050508.3_acm_sci.fits 708.69 184.94 +0.450 +0.163 17 B 009 08 20160816 +3.0 +2.0 20160816T051740.8_acm_sci.fits 711.96 170.56 +4.190 -1.223 For the initial files the script builds: % cat XY.acam 710.69 185.59 716.97 174.16 710.74 184.59 715.33 169.19 709.05 184.86 704.45 194.34 708.69 184.94 711.96 170.56 % cat XY.lrs2 +0.395 -0.217 +3.448 -2.255 +0.643 -0.326 +4.630 -2.038 +0.450 -0.054 -2.492 +1.060 +0.450 +0.163 +4.190 -1.223 When I make the run I get fit info: % FIT B LRS2-B Transformations Processing file = Table.B For the XY_acam to XY_lrs2 transformations: X sigma in LRS2 coordinates = 0.117 (arcseconds) Y sigma in LRS2 coordinates = 0.129 (arcseconds) Number of points in fit = 8 For the XY_lrs2 to XY_acam transformations: X sigma in ACAM coordinates = 0.674 (pixel) Y sigma in ACAM coordinates = 0.571 (pixels) Number of points in fit = 8 The files that are important (that can be used to do tranformations with the xy_tranrot_apply.sh code) are then: coefs.LRS2_to_ACAM_B coefs.ACAM_to_LRS2_BLater I added to the FIT script and had it save the XY data files. If I was running B data, then I would create the files XY.acam_B and XY.lrs2_B. In addition, I modified the xy_tranrot_res.sh code so that a detailed list of residuals is created. Here is the list from my processing of the B data (i.e.the Table.B data):
% cat xy_tranrot_res.resids_list # List of XY residuals from xy_tranrot_res.sh line X1 Y1 X2 Y2 dX dY Res Res_norm 1 0.297 -0.363 0.395 -0.217 -0.098 -0.146 0.176 1.0055 2 3.554 -2.119 3.448 -2.255 0.106 0.136 0.172 0.9839 3 0.552 -0.414 0.643 -0.326 -0.091 -0.088 0.127 0.7254 4 4.708 -1.989 4.630 -2.038 0.078 0.049 0.092 0.5284 5 0.383 -0.057 0.450 -0.054 -0.067 -0.003 0.067 0.3849 6 -2.282 1.275 -2.492 1.060 0.210 0.215 0.301 1.7224 7 0.341 0.020 0.450 0.163 -0.109 -0.143 0.180 1.0299 8 4.161 -1.242 4.190 -1.223 -0.029 -0.019 0.035 0.1998We can use this listing to find bad points that should be rejected in a subsequent refit of the data. The column labeled "Res" is the combined (dX,dY) residual. The column labeled "Res_norm" is the value of Res divided by the combined mean X,Y standard deviations. In the table above, the large values of Res and Res_norm for point 6 might lead me to reject it. In this case I did not since point 6 has a large residual beecause it is the only point at large negative X.