Changeset 41896 for trunk/psLib/src/math/psMinimizePolyFit.c
- Timestamp:
- Nov 4, 2021, 6:10:51 PM (5 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psMinimizePolyFit.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMinimizePolyFit.c
r41532 r41896 35 35 36 36 #include "psMinimizePolyFit.h" 37 #include "psAbort.h" 37 38 #include "psAssert.h" 38 39 #include "psMinimizeLMM.h" // For Gauss-Jordan routines … … 1225 1226 1226 1227 /****************************************************************************** 1228 VectorFitPolynomial2DCheb(myPoly, *mask, maskValue, *f, *fErr, *x, *y): This is 1229 a private routine which will fit a 2-D polynomial to a set of (x, y)-(f) 1230 pairs. All non-NULL vectors must be of type PS_TYPE_F64. 1231 1232 *****************************************************************************/ 1233 static bool VectorFitPolynomial2DCheb( 1234 psPolynomial2D* myPoly, 1235 const psVector *f, 1236 const psVector *x, 1237 const psVector *y) 1238 { 1239 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); 1240 PS_ASSERT_POLY_NON_NULL(myPoly, false); 1241 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false); 1242 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false); 1243 PS_ASSERT_VECTOR_NON_NULL(f, false); 1244 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false); 1245 PS_ASSERT_VECTOR_NON_NULL(x, false); 1246 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false); 1247 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1248 PS_ASSERT_VECTOR_NON_NULL(y, false); 1249 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false); 1250 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1251 1252 // Number of polynomial terms 1253 int nXterm = 1 + myPoly->nX; // Number of terms in x 1254 int nYterm = 1 + myPoly->nY; // Number of terms in y 1255 int nTerm = nXterm * nYterm; // Total number of terms 1256 if (nXterm > 9) { 1257 psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n"); 1258 return false; 1259 } 1260 if (nYterm > 9) { 1261 psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n"); 1262 return false; 1263 } 1264 1265 // determine scale factors 1266 if (!psChebyshevSetScale (myPoly, x, 0)) { psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit.\n"); return false; } 1267 if (!psChebyshevSetScale (myPoly, y, 1)) { psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit.\n"); return false; } 1268 1269 // generate normalized vectors 1270 psVector *xNorm = psChebyshevNormVector (myPoly, x, 0); 1271 psVector *yNorm = psChebyshevNormVector (myPoly, y, 1); 1272 1273 // generate the N cheb polynomials based on xNorm, yNorm 1274 psArray *xPolySet = psArrayAlloc (nXterm); 1275 for (int i = 0; i < nXterm; i++) { 1276 xPolySet->data[i] = psChebyshevPolyVector (xNorm, i); 1277 } 1278 psArray *yPolySet = psArrayAlloc (nYterm); 1279 for (int i = 0; i < nYterm; i++) { 1280 yPolySet->data[i] = psChebyshevPolyVector (yNorm, i); 1281 } 1282 1283 psF64 *fData = f->data.F64; // Dereference f 1284 1285 psImage *A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); // Least-squares matrix 1286 psVector *B = psVectorAlloc(nTerm, PS_TYPE_F64); // Least-squares vector 1287 1288 // Initialize data structures (should not be able to fail) 1289 psAssert (psImageInit(A, 0.0), "Could initialize data structures A"); 1290 psAssert (psVectorInit(B, 0.0), "Could initialize data structures B"); 1291 1292 // Dereference stuff, to make the loop go faster 1293 psF64 **matrix = A->data.F64; // Dereference the least-squares matrix 1294 psF64 *vector = B->data.F64; // Dereference the least-squares vector 1295 1296 // loop over all elements of the data vector 1297 for (int k = 0; k < x->n; k++) { 1298 1299 if (!finite(fData[k])) continue; 1300 1301 // XXX can we only calculate the upper diagonal? 1302 int nelem = 0; 1303 for (int jx = 0; jx < nXterm; jx++) { 1304 psVector *jxCheb = xPolySet->data[jx]; 1305 for (int jy = 0; jy < nYterm; jy++) { 1306 psVector *jyCheb = yPolySet->data[jy]; 1307 psF64 chebValue = jxCheb->data.F64[k] * jyCheb->data.F64[k]; 1308 1309 vector[nelem] += fData[k] * chebValue; 1310 1311 int melem = 0; 1312 for (int kx = 0; kx < nXterm; kx++) { 1313 psVector *kxCheb = xPolySet->data[kx]; 1314 for (int ky = 0; ky < nYterm; ky++) { 1315 psVector *kyCheb = yPolySet->data[ky]; 1316 matrix[nelem][melem] += chebValue * kxCheb->data.F64[k]*kyCheb->data.F64[k]; 1317 melem++; 1318 } 1319 } 1320 nelem++; 1321 } 1322 } 1323 } 1324 1325 if (psTraceGetLevel("psLib.math") >= 4) { 1326 printf("Least-squares vector:\n"); 1327 for (int i = 0; i < nTerm; i++) { 1328 printf("%f ", B->data.F64[i]); 1329 } 1330 printf("\n"); 1331 printf("Least-squares matrix:\n"); 1332 for (int i = 0; i < nTerm; i++) { 1333 for (int j = 0; j < nTerm; j++) { 1334 printf("%f ", A->data.F64[i][j]); 1335 } 1336 printf("\n"); 1337 } 1338 } 1339 1340 bool status = false; 1341 if (USE_GAUSS_JORDAN) { 1342 status = psMatrixGJSolve(A, B); 1343 } else { 1344 status = psMatrixLUSolve(A, B); 1345 } 1346 if (!status) { 1347 psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.\n"); 1348 goto escape; 1349 } 1350 1351 // unroll the result: 1352 int nelem = 0; 1353 for (int jx = 0; jx < nXterm; jx++) { 1354 for (int jy = 0; jy < nYterm; jy++) { 1355 myPoly->coeff[jx][jy] = B->data.F64[nelem]; 1356 myPoly->coeffErr[jx][jy] = sqrt(A->data.F64[nelem][nelem]); 1357 nelem ++; 1358 } 1359 } 1360 psFree(A); 1361 psFree(B); 1362 1363 psFree (xNorm); 1364 psFree (yNorm); 1365 psFree (xPolySet); 1366 psFree (yPolySet); 1367 1368 return true; 1369 1370 escape: 1371 psFree (A); 1372 psFree (B); 1373 return false; 1374 } 1375 1376 /****************************************************************************** 1227 1377 psVectorFitPolynomial2D(): This routine fits a 2D polynomial of arbitrary 1228 1378 degree (specified in poly) to the data points (x, y)-(f) and returns that … … 1240 1390 { 1241 1391 PS_ASSERT_POLY_NON_NULL(poly, false); 1242 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);1392 // PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false); 1243 1393 1244 1394 PS_ASSERT_VECTOR_NON_NULL(f, false); … … 1277 1427 break; 1278 1428 case PS_POLYNOMIAL_CHEB: 1279 if (mask != NULL) { 1280 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 1281 } 1282 psError(PS_ERR_UNKNOWN, true, "2-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 1283 result = false; 1284 break; 1429 if (mask != NULL) { 1430 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 1431 } 1432 if (fErr != NULL) { 1433 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring error values for Chebyshev polynomials.\n"); 1434 } 1435 result = VectorFitPolynomial2DCheb(poly, f64, x64, y64); 1436 if (!result) { 1437 psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial. Returning NULL.\n"); 1438 } 1439 break; 1285 1440 default: 1286 1441 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n");
Note:
See TracChangeset
for help on using the changeset viewer.
