Changeset 3598 for trunk/psLib/src/astronomy/psAstrometry.c
- Timestamp:
- Mar 31, 2005, 1:01:46 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/astronomy/psAstrometry.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/astronomy/psAstrometry.c
r3559 r3598 8 8 * @author GLG, MHPCC 9 9 * 10 * @version $Revision: 1.6 2$ $Name: not supported by cvs2svn $11 * @date $Date: 2005-03-3 0 02:21:14$10 * @version $Revision: 1.63 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2005-03-31 23:01:46 $ 12 12 * 13 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 51 51 } 52 52 53 /*****************************************************************************54 isProjectionLinear(): this is a private function which simply determines55 if the supplied psPlaneTransform transform is linear: if any of the56 cooefficients of order 2 are higher are non-zero, then it is not linear.57 *****************************************************************************/58 static psS32 isProjectionLinear(psPlaneTransform *transform)59 {60 PS_PTR_CHECK_NULL(transform, 0);61 PS_PTR_CHECK_NULL(transform->x, 0);62 PS_PTR_CHECK_NULL(transform->y, 0);63 64 for (psS32 i=0;i<(transform->x->nX);i++) {65 for (psS32 j=0;j<(transform->x->nY);j++) {66 if (transform->x->coeff[i][j] != 0.0) {67 if (!(((i == 0) && (j == 0)) ||68 ((i == 0) && (j == 1)) ||69 ((i == 1) && (j == 0)))) {70 return(0);71 }72 }73 }74 }75 76 for (psS32 i=0;i<(transform->y->nX);i++) {77 for (psS32 j=0;j<(transform->y->nY);j++) {78 if (transform->y->coeff[i][j] != 0.0) {79 if (!(((i == 0) && (j == 0)) ||80 ((i == 0) && (j == 1)) ||81 ((i == 1) && (j == 0)))) {82 return(0);83 }84 }85 }86 }87 88 return(1);89 }90 91 /*****************************************************************************92 invertPlaneTransform(transform): : this is a private function which93 simply inverts the supplied psPlaneTransform transform. It assumes that94 "transform" is linear.95 96 This program assumes that the inverse of the following linear equations:97 X2 = A + (B * X1) + (C * Y1);98 Y2 = D + (E * X1) + (F * Y1);99 is100 Y1 = (Y2 - ((E/B) * X2) - D + ((E*A)/B)) / (F - ((C*E)/B));101 X1 = (Y2 - ((F/C) * X2) - D + ((F*A)/C)) / (E - ((F*B)/C));102 or103 X1 = (-D + ((F*A)/C)) / (E - ((F*B)/C)) +104 (X2 * -((F/C) / (E - ((F*B)/C)))) +105 (Y2 * (1.0 / (E - ((F*B)/C))));106 Y1 = (-D + ((E*A)/B))/(F - ((C*E)/B)) +107 (X2 * -((E/B) / (F - ((C*E)/B)))) +108 (Y2 * (1.0 / (F - ((C*E)/B))));109 110 XXX: Since thre is now a general psPlaneTransformInvert() function, we111 should rename this.112 113 *****************************************************************************/114 static psPlaneTransform *invertPlaneTransform(psPlaneTransform *transform)115 {116 PS_PTR_CHECK_NULL(transform, 0);117 PS_PTR_CHECK_NULL(transform->x, 0);118 PS_PTR_CHECK_NULL(transform->y, 0);119 120 psF64 A = 0.0;121 psF64 B = 0.0;122 psF64 C = 0.0;123 psF64 D = 0.0;124 psF64 E = 0.0;125 psF64 F = 0.0;126 127 // XXX: Test this for correctness.128 A = transform->x->coeff[0][0];129 if (transform->x->nX >= 2) {130 B = transform->x->coeff[1][0];131 }132 if (transform->x->nY >= 2) {133 C = transform->x->coeff[0][1];134 }135 D = transform->y->coeff[0][0];136 if (transform->y->nX >= 2) {137 E = transform->y->coeff[1][0];138 }139 if (transform->y->nY >= 2) {140 F = transform->y->coeff[0][1];141 }142 143 // XXX: Use the constructor here.144 psPlaneTransform *out = psPlaneTransformAlloc(2, 2);145 146 out->x->coeff[0][0] = -D + ((F*A)/C) / (E - ((F*B)/C));147 out->x->coeff[1][0] = -(F/C) / (E - ((F*B)/C));148 out->x->coeff[0][1] = 1.0 / (E - ((F*B)/C));149 out->y->coeff[0][0] = -D + ((E*A)/B) / (F - ((C*E)/B));150 out->y->coeff[1][0] = -(E/B) / (F - ((C*E)/B));151 out->y->coeff[0][1] = 1.0 / (F - ((C*E)/B));152 153 return(out);154 }155 53 156 54 static void FPAFree(psFPA* fpa) … … 914 812 915 813 // generate an error if cell->toTP is not linear. 916 if (0 == isProjectionLinear(cell->toTP)) {814 if (0 == p_psIsProjectionLinear(cell->toTP)) { 917 815 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 918 816 PS_ERRORTEXT_psAstrometry_NONLINEAR_TRANSFORM, … … 920 818 } 921 819 922 TPtoCell = invertPlaneTransform(cell->toTP);820 TPtoCell = p_psPlaneTransformLinearInvert(cell->toTP); 923 821 cellCoord = psPlaneTransformApply(cellCoord, TPtoCell, tpCoord); 924 822 … … 930 828 931 829 932 /***************************************************************************** 933 multiplyCoeffs(trans1, trans2): Takes two 2-D polynomials as input and 934 multiplies them. Basically, for each non-zero coeff in the trans1 coeff[][] 935 array, you must multiply by all non-zero coeffs in trans2. 936 937 XXX: Inefficient in that the out polynomial is allocated every time. 938 *****************************************************************************/ 939 psDPolynomial2D *multiplyDPoly2D(psDPolynomial2D *trans1, 940 psDPolynomial2D *trans2) 941 { 942 psS32 orderX = (trans1->nX + trans2->nX) - 1; 943 psS32 orderY = (trans1->nX + trans2->nX) - 1; 944 945 psDPolynomial2D *out = psDPolynomial2DAlloc(orderX, orderY, PS_POLYNOMIAL_ORD); 946 for (psS32 i = 0 ; i < out->nX; i++) { 947 for (psS32 j = 0 ; j < out->nY; j++) { 948 out->coeff[i][j] = 0.0; 949 out->mask[i][j] = 0; 950 } 951 } 952 953 for (psS32 t1x = 0 ; t1x < trans1->nX ; t1x++) { 954 for (psS32 t1y = 0 ; t1y < trans1->nY ; t1y++) { 955 if (0.0 != trans1->coeff[t1x][t1y]) { 956 for (psS32 t2x = 0 ; t2x < trans2->nX ; t2x++) { 957 for (psS32 t2y = 0 ; t2y < trans2->nY ; t2y++) { 958 out->coeff[t1x+t2x][t1y+t2y]+= (trans1->coeff[t1x][t1y] * trans2->coeff[t2x][t2y]); 959 } 960 } 961 } 962 } 963 } 964 return(out); 965 } 966 967 968 969 970 /***************************************************************************** 971 psPlaneTransformCombine(out, trans1, trans2) 972 973 XXX: Much room for optimization. Currently, we call the polyMultiply 974 routine far too many times. 975 *****************************************************************************/ 976 psPlaneTransform *psPlaneTransformCombine(psPlaneTransform *out, 977 const psPlaneTransform *trans1, 978 const psPlaneTransform *trans2) 979 { 980 PS_PTR_CHECK_NULL(trans1, NULL); 981 PS_PTR_CHECK_NULL(trans2, NULL); 982 983 // 984 // Determine the size of the new psPlaneTransform. 985 // 986 // PS_MAX( Number of x terms in T2->x * number of x terms in T1->x, 987 // Number of y terms in T2->x * number of x terms in T1->y, 988 psS32 orderXnX = PS_MAX((trans2->x->nX * trans1->x->nX), 989 (trans2->x->nY * trans1->y->nX)); 990 psS32 orderXnY = PS_MAX((trans2->x->nX * trans1->x->nY), 991 (trans2->x->nY * trans1->y->nY)); 992 993 psS32 orderYnX = PS_MAX((trans2->y->nX * trans1->x->nX), 994 (trans2->y->nY * trans1->y->nX)); 995 psS32 orderYnY = PS_MAX((trans2->y->nX * trans1->x->nY), 996 (trans2->y->nY * trans1->y->nY)); 997 psS32 orderX = PS_MAX(orderXnX, orderYnX); 998 psS32 orderY = PS_MAX(orderXnY, orderYnY); 999 1000 // 1001 // Allocate the new psPlaneTransform, if necessary. 1002 // 1003 psPlaneTransform *myPT = NULL; 1004 if (out == NULL) { 1005 myPT = psPlaneTransformAlloc(orderX, orderY); 1006 } else { 1007 if ((out->x->nX == orderX) && (out->x->nY == orderY) && 1008 (out->y->nX == orderX) && (out->y->nY == orderY)) { 1009 myPT = out; 1010 } else { 1011 psFree(out); 1012 myPT = psPlaneTransformAlloc(orderX, orderY); 1013 } 1014 } 1015 1016 // 1017 // Initialize the new psPlaneTransform, if necessary. 1018 // 1019 for (psS32 i = 0 ; i < orderX ; i++) { 1020 for (psS32 j = 0 ; j < orderY ; j++) { 1021 myPT->x->coeff[i][j] = 0.0; 1022 myPT->x->mask[i][j] = 0; 1023 myPT->y->coeff[i][j] = 0.0; 1024 myPT->y->mask[i][j] = 0; 1025 } 1026 } 1027 1028 // 1029 // For each term (a * x^i * y^j) in trans2, we substitute the appropriate 1030 // equation from trans1, and raise it to the appropriate power. This is 1031 // done via the multiplyDPoly2D(). The result is a polynomial (currPoly) 1032 // and its coefficients are added into the myPT coeff matrix. 1033 // 1034 // XXX: This is horribly inefficient in that the trans1 polys are repeatedly 1035 // multiplied against themselves. This can easily be improved. 1036 // 1037 for (psS32 t2x = 0 ; t2x < trans2->x->nX ; t2x++) { 1038 for (psS32 t2y = 0 ; t2y < trans2->x->nY ; t2y++) { 1039 psDPolynomial2D *currPoly = psDPolynomial2DAlloc(1, 1, PS_POLYNOMIAL_ORD); 1040 currPoly->coeff[0][0] = 1.0; 1041 currPoly->mask[0][0] = 0; 1042 psDPolynomial2D *newPoly = NULL; 1043 1044 if (trans2->x->mask[t2x][t2y] == 0) { 1045 1046 // Must raise trans1->y to the t2y-power. 1047 for (psS32 c = 0 ; c < t2y; c++) { 1048 newPoly = multiplyDPoly2D(currPoly, trans1->y); 1049 psFree(currPoly); 1050 currPoly = newPoly; 1051 } 1052 1053 // Must raise trans1->x to the t2x-power. 1054 for (psS32 c = 0 ; c < t2x; c++) { 1055 newPoly = multiplyDPoly2D(currPoly, trans1->x); 1056 psFree(currPoly); 1057 currPoly = newPoly; 1058 } 1059 1060 // Set the appropriate coeffs in myPT->x 1061 for (psS32 i = 0 ; i < currPoly->nX ; i++) { 1062 for (psS32 j = 0 ; j < currPoly->nY ; j++) { 1063 myPT->x->coeff[i][j]+= currPoly->coeff[i][j] * trans2->x->coeff[t2x][t2y]; 1064 } 1065 } 1066 } 1067 psFree(currPoly); 1068 } 1069 } 1070 1071 1072 1073 for (psS32 t2x = 0 ; t2x < trans2->y->nX ; t2x++) { 1074 for (psS32 t2y = 0 ; t2y < trans2->y->nY ; t2y++) { 1075 psDPolynomial2D *currPoly = psDPolynomial2DAlloc(1, 1, PS_POLYNOMIAL_ORD); 1076 currPoly->coeff[0][0] = 1.0; 1077 currPoly->mask[0][0] = 0; 1078 psDPolynomial2D *newPoly = NULL; 1079 1080 if (trans2->y->mask[t2x][t2y] == 0) { 1081 1082 // Must raise trans1->y to the t2y-power. 1083 for (psS32 c = 0 ; c < t2y; c++) { 1084 newPoly = multiplyDPoly2D(currPoly, trans1->y); 1085 psFree(currPoly); 1086 currPoly = newPoly; 1087 } 1088 1089 // Must raise trans1->x to the t2x-power. 1090 for (psS32 c = 0 ; c < t2x; c++) { 1091 newPoly = multiplyDPoly2D(currPoly, trans1->x); 1092 psFree(currPoly); 1093 currPoly = newPoly; 1094 } 1095 1096 // Set the appropriate coeffs in myPT->x 1097 for (psS32 i = 0 ; i < currPoly->nX ; i++) { 1098 for (psS32 j = 0 ; j < currPoly->nY ; j++) { 1099 myPT->y->coeff[i][j]+= currPoly->coeff[i][j] * trans2->y->coeff[t2x][t2y]; 1100 } 1101 } 1102 } 1103 psFree(currPoly); 1104 } 1105 } 1106 1107 return(myPT); 1108 } 1109 1110 /***************************************************************************** 1111 psPlaneTransformFit(trans, source, dest, nRejIter, sigmaClip) 1112 1113 XXX: What about nRejIter? Iterations? 1114 XXX: Use static vectors for internal data. 1115 *****************************************************************************/ 1116 bool psPlaneTransformFit(psPlaneTransform *trans, 1117 const psArray *source, 1118 const psArray *dest, 1119 int nRejIter, 1120 float sigmaClip) 1121 { 1122 PS_PTR_CHECK_NULL(trans, NULL); 1123 PS_PTR_CHECK_NULL(source, NULL); 1124 PS_PTR_CHECK_NULL(dest, NULL); 1125 1126 psS32 numCoords = PS_MIN(source->n, dest->n); 1127 // This is not really necessary because of above conditionals. 1128 psS32 order = PS_MAX(trans->x->nX, trans->x->nY); 1129 1130 // 1131 // Create fake polynomial to use in evaluation 1132 // 1133 psDPolynomial2D *fakePoly = psDPolynomial2DAlloc(order, order, PS_POLYNOMIAL_ORD); 1134 for (int i = 0; i < order; i++) { 1135 for (int j = 0; j < order; j++) { 1136 fakePoly->coeff[i][j] = 1.0; 1137 fakePoly->mask[i][j] = 1; // Mask all coefficients; unmask to evaluate 1138 } 1139 } 1140 1141 // 1142 // Initialize the matrix and vectors 1143 // 1144 psS32 nCoeff = order * (order + 1) / 2; // Number of polynomial coefficients 1145 psImage *matrix = psImageAlloc(nCoeff, nCoeff, PS_TYPE_F64); // Matrix for solution 1146 psVector *xVector = psVectorAlloc(nCoeff, PS_TYPE_F64); // Vector for solution in x 1147 psVector *yVector = psVectorAlloc(nCoeff, PS_TYPE_F64); // Vector for solution in y 1148 for (psS32 i = 0; i < nCoeff; i++) { 1149 for (psS32 j = 0; j < nCoeff; j++) { 1150 matrix->data.F64[i][j] = 0.0; 1151 } 1152 xVector->data.F64[i] = 0.0; 1153 yVector->data.F64[i] = 0.0; 1154 } 1155 1156 // 1157 // Iterate over the grid points 1158 // 1159 for (psS32 g = 0; g < numCoords; g++) { 1160 // Iterate over the polynomial coefficients, accumulating the matrix and vectors 1161 1162 for (psS32 i = 0, ijIndex = 0; i < order; i++) { 1163 for (psS32 j = 0; j < order - i; j++, ijIndex++) { 1164 fakePoly->mask[i][j] = 0; 1165 psF64 xIn = ((psPlane *) source->data[g])->x; 1166 psF64 yIn = ((psPlane *) source->data[g])->y; 1167 psF64 xOut = ((psPlane *) dest->data[g])->x; 1168 psF64 yOut = ((psPlane *) dest->data[g])->y; 1169 psF64 ijPoly = psDPolynomial2DEval(fakePoly, xIn, yIn); 1170 fakePoly->mask[i][j] = 1; 1171 1172 for (psS32 m = 0, mnIndex = 0; m < order; m++) { 1173 for (psS32 n = 0; n < order - m; n++, mnIndex++) { 1174 fakePoly->mask[m][n] = 0; 1175 psF64 mnPoly = psDPolynomial2DEval(fakePoly, xIn, yIn); 1176 fakePoly->mask[m][n] = 1; 1177 1178 matrix->data.F64[ijIndex][mnIndex] += ijPoly * mnPoly; 1179 } 1180 } 1181 1182 xVector->data.F64[ijIndex] += ijPoly * xOut; 1183 yVector->data.F64[ijIndex] += ijPoly * yOut; 1184 } 1185 } 1186 } 1187 1188 // 1189 // Solution via LU Decomposition 1190 // 1191 psVector *permutation = psVectorAlloc(nCoeff, PS_TYPE_F64); // Permutation vector for LU Decomposition 1192 psImage *luMatrix = psMatrixLUD(NULL, &permutation, matrix); // LU decomposed matrix 1193 psVector *xSolution = psMatrixLUSolve(NULL, luMatrix, xVector, permutation); // Solution in x 1194 psVector *ySolution = psMatrixLUSolve(NULL, luMatrix, yVector, permutation); // Solution in y 1195 1196 // 1197 // XXX: Should check the output of the matrix routines and return false if bad. 1198 // 1199 1200 // 1201 // Stuff coefficients into transformation 1202 // 1203 for (psS32 i = 0, ijIndex = 0; i < order; i++) { 1204 for (psS32 j = 0; j < order - i; j++, ijIndex++) { 1205 trans->x->coeff[i][j] = xSolution->data.F64[ijIndex]; 1206 trans->y->coeff[i][j] = ySolution->data.F64[ijIndex]; 1207 } 1208 } 1209 1210 psFree(fakePoly); 1211 psFree(permutation); 1212 psFree(luMatrix); 1213 psFree(xSolution); 1214 psFree(ySolution); 1215 psFree(matrix); 1216 psFree(xVector); 1217 psFree(yVector); 1218 1219 return(true); 1220 } 1221 1222 1223 /***************************************************************************** 1224 psPlaneTransformInvert(out, in, region, nSamples) 1225 1226 // XXX: Use static data structures. 1227 *****************************************************************************/ 1228 psPlaneTransform *psPlaneTransformInvert(psPlaneTransform *out, 1229 const psPlaneTransform *in, 1230 psRegion *region, 1231 int nSamples) 1232 { 1233 PS_PTR_CHECK_NULL(in, NULL); 1234 // 1235 // If the transform is linear, then invert it exactly and return. 1236 // 1237 if (isProjectionLinear((psPlaneTransform *) in)) { 1238 printf("COOL: is linear\n"); 1239 return(invertPlaneTransform((psPlaneTransform *) in)); 1240 } 1241 PS_PTR_CHECK_NULL(region, NULL); 1242 PS_INT_COMPARE(1, nSamples, NULL); 1243 1244 // Ensure that the input transformation is symmetrical. 1245 if ((in->x->nX != in->x->nY) || 1246 (in->y->nX != in->y->nY) || 1247 (in->x->nX != in->y->nX)) { 1248 psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Input transformation must have same nX==nY."); 1249 } 1250 psS32 order = PS_MAX(in->x->nX, in->x->nY); 1251 1252 psPlaneTransform *myPT = NULL; 1253 psPlane *inCoord = psPlaneAlloc(); 1254 psPlane *outCoord = psPlaneAlloc(); 1255 1256 // 1257 // Allocate a new psPlaneTransform if "out" is NULL, or has the wrong size. 1258 // 1259 if (out == NULL) { 1260 myPT = psPlaneTransformAlloc(order, order); 1261 } else { 1262 if ((out->x->nX == order) && (out->x->nY == order) && 1263 (out->y->nX == order) && (out->y->nY == order)) { 1264 myPT = out; 1265 } else { 1266 psFree(out); 1267 myPT = psPlaneTransformAlloc(order, order); 1268 } 1269 } 1270 1271 // 1272 // Copy the input transform to myPT. 1273 // 1274 for (psS32 i = 0 ; i < in->x->nX ; i++) { 1275 for (psS32 j = 0 ; j < in->x->nY ; j++) { 1276 myPT->x->coeff[i][j] = in->x->coeff[i][j]; 1277 } 1278 } 1279 for (psS32 i = 0 ; i < in->y->nX ; i++) { 1280 for (psS32 j = 0 ; j < in->y->nY ; j++) { 1281 myPT->y->coeff[i][j] = in->y->coeff[i][j]; 1282 } 1283 } 1284 1285 // 1286 // Create a grid of xin,yin --> xout,yout 1287 // 1288 psArray *inData = psArrayAlloc(nSamples * nSamples); 1289 psArray *outData = psArrayAlloc(nSamples * nSamples); 1290 for (psS32 i = 0 ; i < inData->n; i++) { 1291 inData->data[i] = (psPtr *) psPlaneAlloc(); 1292 outData->data[i] = (psPtr *) psPlaneAlloc(); 1293 } 1294 1295 // 1296 // Initialize the grid. 1297 // 1298 psS32 cnt = 0; 1299 for (int yint = 0; yint < nSamples; yint++) { 1300 inCoord->y = region->y0 + ((psF32) yint) * ((region->y1 - region->y0) / ((psF32) nSamples)); 1301 for (int xint = 0; xint < nSamples; xint++) { 1302 inCoord->x = region->x0 + ((psF32) xint) * ((region->x1 - region->x0) / ((psF32) nSamples)); 1303 (void)psPlaneTransformApply(outCoord, in, inCoord); 1304 1305 ((psPlane *) outData->data[cnt])->x = inCoord->x; 1306 ((psPlane *) outData->data[cnt])->y = inCoord->y; 1307 ((psPlane *) inData->data[cnt])->x = outCoord->x; 1308 ((psPlane *) inData->data[cnt])->y = outCoord->y; 1309 1310 cnt++; 1311 } 1312 } 1313 bool rc = psPlaneTransformFit(myPT, inData, outData, 10, 100.0); 1314 1315 psFree(inCoord); 1316 psFree(outCoord); 1317 psFree(inData); 1318 psFree(outData); 1319 1320 if (rc == true) { 1321 return(myPT); 1322 } 1323 1324 // XXX: Generate an error message, or warning message. 1325 return(NULL); 1326 } 830
Note:
See TracChangeset
for help on using the changeset viewer.
