Changeset 4858
- Timestamp:
- Aug 23, 2005, 3:04:37 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psMinimize.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMinimize.c
r4760 r4858 9 9 * @author GLG, MHPCC 10 10 * 11 * @version $Revision: 1.13 0$ $Name: not supported by cvs2svn $12 * @date $Date: 2005-08- 11 23:04:32$11 * @version $Revision: 1.131 $ $Name: not supported by cvs2svn $ 12 * @date $Date: 2005-08-24 01:04:37 $ 13 13 * 14 14 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 28 28 #include "psImage.h" 29 29 #include "psImageStructManip.h" 30 #include "psBinaryOp.h" 30 31 /*****************************************************************************/ 31 32 /* DEFINE STATEMENTS */ … … 2131 2132 2132 2133 2134 /****************************************************************************** 2135 EAM Code: 2136 *****************************************************************************/ 2137 2138 // XXX EAM : my alternate EAMBuildSums1D 2139 static psVector *EAMBuildSums1D( 2140 psVector* sums, 2141 psF64 x, 2142 psS32 nTerm) 2143 { 2144 psS32 nSum = 0; 2145 psF64 xSum = 0.0; 2146 2147 nSum = 2*nTerm; 2148 if (sums == NULL) { 2149 sums = psVectorAlloc(nSum, PS_TYPE_F64); 2150 } 2151 if (nSum > sums->n) { 2152 sums = psVectorRealloc(sums, nSum); 2153 } 2154 2155 xSum = 1.0; 2156 for (int i = 0; i < nSum; i++) { 2157 sums->data.F64[i] = xSum; 2158 xSum *= x; 2159 } 2160 return (sums); 2161 } 2162 2163 // XXX EAM : test version of 1d fitting 2164 psPolynomial1D* VectorFitPolynomial1DOrd_EAM( 2165 psPolynomial1D* myPoly, 2166 psVector *mask, 2167 const psVector *x, 2168 const psVector *y, 2169 const psVector *yErr 2170 ) 2171 { 2172 // I think this is 1 dimension down 2173 psImage* A = NULL; 2174 psVector* B = NULL; 2175 psVector* xSums = NULL; 2176 psS32 nTerm; 2177 psS32 nOrder; 2178 psF64 wt; 2179 2180 psTrace(".psLib.dataManip.VectorFitPolynomial1DOrd", 4, 2181 "---- VectorFitPolynomial1DOrd() begin ----\n"); 2182 2183 if (psTraceGetLevel (".psLib.dataManip.VectorFitPolynomial1DOrd") >= 5) { 2184 FILE *f = psTraceGetDestination (); 2185 fprintf (f, "VectorFitPolynomial1D()\n"); 2186 for (int i = 0; i < x->n; i++) { 2187 fprintf (f, "(x, y, yErr) is (%f, %f, %f)\n", x->data.F64[i], y->data.F64[i], yErr->data.F64[i]); 2188 } 2189 } 2190 2191 nTerm = myPoly->n; 2192 nOrder = nTerm - 1; 2193 2194 A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); 2195 B = psVectorAlloc(nTerm, PS_TYPE_F64); 2196 2197 // 2198 // Initialize data structures. 2199 // XXX: Use psLib function. 2200 // 2201 PS_VECTOR_SET_F64(B, 0.0); 2202 PS_IMAGE_SET_F64(A, 0.0); 2203 2204 // xSums look like: 1, x, x^2, ... x^(2n+1) 2205 // Build the B and A data structs. 2206 for (int k = 0; k < x->n; k++) { 2207 if ((mask != NULL) && mask->data.U8[k]) 2208 continue; 2209 xSums = EAMBuildSums1D(xSums, x->data.F64[k], nTerm); 2210 2211 if (yErr == NULL) { 2212 wt = 1.0; 2213 } else { 2214 // this should filter yErr == 0 values 2215 wt = 1.0 / PS_SQR(yErr->data.F64[k]); 2216 } 2217 for (int i = 0; i < nTerm; i++) { 2218 B->data.F64[i] += y->data.F64[k] * xSums->data.F64[i] * wt; 2219 } 2220 2221 // we could skip half of the array and assign at the end 2222 // we must handle masked orders 2223 for (int i = 0; i < nTerm; i++) { 2224 for (int j = 0; j < nTerm; j++) { 2225 A->data.F64[i][j] += xSums->data.F64[i + j] * wt; 2226 } 2227 } 2228 } 2229 2230 // GaussJordan version 2231 if (0) { 2232 // does the solution in place 2233 psGaussJordan (A, B); 2234 2235 // the first nTerm entries in B correspond directly to the desired 2236 // polynomial coefficients. this is only true for the 1D case 2237 for (int k = 0; k < nTerm; k++) { 2238 myPoly->coeff[k] = B->data.F64[k]; 2239 } 2240 } else 2241 // LUD version of the fit 2242 { 2243 psImage *ALUD = NULL; 2244 psVector* outPerm = NULL; 2245 psVector* coeffs = NULL; 2246 2247 ALUD = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); 2248 ALUD = psMatrixLUD(ALUD, &outPerm, A); 2249 coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm); 2250 for (int k = 0; k < nTerm; k++) { 2251 myPoly->coeff[k] = coeffs->data.F64[k]; 2252 } 2253 } 2254 2255 psFree(A); 2256 psFree(B); 2257 psFree(xSums); 2258 2259 psTrace(".psLib.dataManip.VectorFitPolynomial1DOrd", 4, 2260 "---- VectorFitPolynomial1DOrd() begin ----\n"); 2261 return (myPoly); 2262 } 2263 2264 // XXX EAM : this version uses the F64 vectors 2265 psVector *Polynomial2DEvalVectorD( 2266 const psPolynomial2D *myPoly, 2267 const psVector *x, 2268 const psVector *y 2269 ) 2270 { 2271 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 2272 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2273 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 2274 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2275 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 2276 2277 psVector *tmp; 2278 psS32 vecLen=x->n; 2279 2280 // Determine the length of the output vector to by the minimum of the x,y vectors 2281 if (y->n < vecLen) { 2282 vecLen = y->n; 2283 } 2284 2285 // Create output vector to return 2286 tmp = psVectorAlloc(vecLen, PS_TYPE_F64); 2287 2288 // Evaluate the polynomial at the specified points 2289 for (psS32 i=0; i<vecLen; i++) { 2290 tmp->data.F64[i] = psPolynomial2DEval(myPoly, x->data.F64[i], y->data.F64[i]); 2291 } 2292 2293 // Return output vector 2294 return(tmp); 2295 } 2296 2297 // XXX EAM : EAMBuildSums2D in analogy with EAMBuildSums1D 2298 static psImage *EAMBuildSums2D( 2299 psImage *sums, 2300 psF64 x, 2301 psF64 y, 2302 psS32 nXterm, 2303 psS32 nYterm 2304 ) 2305 { 2306 psS32 nXsum = 0; 2307 psS32 nYsum = 0; 2308 psF64 xSum = 1.0; 2309 psF64 ySum = 1.0; 2310 2311 nXsum = 2*nXterm; 2312 nYsum = 2*nYterm; 2313 if (sums == NULL) { 2314 sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64); 2315 } 2316 if ((nXsum != sums->numCols) || (nYsum != sums->numRows)) { 2317 psFree (sums); 2318 sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64); 2319 } 2320 2321 ySum = 1.0; 2322 for (int j = 0; j < nYsum; j++) { 2323 xSum = ySum; 2324 for (int i = 0; i < nXsum; i++) { 2325 sums->data.F64[i][j] = xSum; 2326 xSum *= x; 2327 } 2328 ySum *= y; 2329 } 2330 return (sums); 2331 } 2332 2333 // XXX EAM : test version of 2d fitting 2334 psPolynomial2D* VectorFitPolynomial2DOrd_EAM( 2335 psPolynomial2D* myPoly, 2336 psVector* mask, 2337 const psVector* x, 2338 const psVector* y, 2339 const psVector* z, 2340 const psVector* zErr 2341 ) 2342 { 2343 // I think this is 1 dimension down 2344 psImage* A = NULL; 2345 psVector* B = NULL; 2346 psImage* Sums = NULL; 2347 psF64 wt; 2348 psS32 nTerm; 2349 2350 // XXX:Watch for changes to the psPolys: nTerm != nOrder. 2351 psS32 nXterm = myPoly->nX; 2352 psS32 nYterm = myPoly->nY; 2353 nTerm = nXterm * nYterm; 2354 2355 A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); 2356 B = psVectorAlloc(nTerm, PS_TYPE_F64); 2357 2358 // 2359 // Initialize data structures. 2360 // XXX: Use psLib function. 2361 // 2362 PS_VECTOR_SET_F64(B, 0.0); 2363 PS_IMAGE_SET_F64(A, 0.0); 2364 2365 // Sums look like: 1, x, x^2, ... x^(2n+1), y, xy, x^2y, ... x^(2n+1) 2366 2367 // Build the B and A data structs. 2368 for (int k = 0; k < x->n; k++) { 2369 if ((mask != NULL) && mask->data.U8[k]) 2370 continue; 2371 Sums = EAMBuildSums2D(Sums, x->data.F64[k], y->data.F64[k], nXterm, nYterm); 2372 2373 if (zErr == NULL) { 2374 wt = 1.0; 2375 } else { 2376 // XXX: this should probably by zErr^2 !! 2377 // this should filter zErr == 0 values 2378 // XXX: Why isn't this zErr^2? 2379 wt = 1.0 / zErr->data.F64[k]; 2380 } 2381 2382 // we could skip half of the array and assign at the end 2383 // we must handle masked orders 2384 for (int n = 0; n < nXterm; n++) { 2385 for (int m = 0; m < nYterm; m++) { 2386 B->data.F64[n+m*nXterm] += z->data.F64[k] * Sums->data.F64[n][m] * wt; 2387 } 2388 } 2389 2390 for (int i = 0; i < nXterm; i++) { 2391 for (int j = 0; j < nYterm; j++) { 2392 for (int n = 0; n < nXterm; n++) { 2393 for (int m = 0; m < nYterm; m++) { 2394 A->data.F64[i+j*nXterm][n+m*nXterm] += Sums->data.F64[i+n][j+m] * wt; 2395 } 2396 } 2397 } 2398 } 2399 } 2400 2401 // does the solution in place 2402 // XXX: Check return codes! 2403 psGaussJordan (A, B); 2404 2405 // XXX: Check return codes! 2406 // ALUD = psMatrixLUD(ALUD, &outPerm, A); 2407 // coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm); 2408 2409 for (int n = 0; n < nXterm; n++) { 2410 for (int m = 0; m < nYterm; m++) { 2411 myPoly->coeff[n][m] = B->data.F64[n+m*nXterm]; 2412 } 2413 } 2414 2415 psFree(A); 2416 psFree(B); 2417 psFree(Sums); 2418 2419 psTrace(".psLib.dataManip.VectorFitPolynomial2DOrd", 4, 2420 "---- VectorFitPolynomial2DOrd() begin ----\n"); 2421 return (myPoly); 2422 } 2423 2424 2425 psPolynomial2D* RobustFit2D_nomask( 2426 psPolynomial2D* poly, 2427 const psVector* x, 2428 const psVector* y, 2429 const psVector* z, 2430 const psVector* dz 2431 ) 2432 { 2433 psVector *X; 2434 psVector *Y; 2435 psVector *Z; 2436 psVector *dZ; 2437 2438 psVector *zFit = NULL; 2439 psVector *zResid = NULL; 2440 psStats *stats = NULL; 2441 2442 X = psVectorCopy (NULL, x, PS_TYPE_F64); 2443 Y = psVectorCopy (NULL, y, PS_TYPE_F64); 2444 Z = psVectorCopy (NULL, z, PS_TYPE_F64); 2445 dZ = psVectorCopy (NULL, dz, PS_TYPE_F64); 2446 2447 for (int N = 0; N < 3; N++) { 2448 // XXX EAM : this would be better defined with an element mask 2449 poly = VectorFitPolynomial2DOrd_EAM(poly, NULL, X, Y, Z, dZ); 2450 zFit = Polynomial2DEvalVectorD(poly, x, y); 2451 zResid = (psVector *) psBinaryOp(NULL, (void *) z, "-", (void *) zFit); 2452 2453 stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV); 2454 stats = psVectorStats (stats, zResid, NULL, NULL, 0); 2455 psTrace (".psphot.RobustFit", 4, "residual stats for robust fit: %g +/- %g (%d pts)\n", stats->clippedMean, stats->clippedStdev, stats->clippedNvalues); 2456 2457 // re-create X, Y, Z, dZ if pts are valid 2458 int n = 0; 2459 for (int i = 0; i < zResid->n; i++) { 2460 if (fabs(zResid->data.F64[i] - stats->clippedMean) > 3*stats->clippedStdev) { 2461 continue; 2462 } 2463 X->data.F64[n] = x->data.F64[i]; 2464 Y->data.F64[n] = y->data.F64[i]; 2465 Z->data.F64[n] = z->data.F64[i]; 2466 dZ->data.F64[n] = dz->data.F64[i]; 2467 n++; 2468 } 2469 X->n = n; 2470 Y->n = n; 2471 Z->n = n; 2472 dZ->n = n; 2473 } 2474 return (poly); 2475 } 2476 2477 // XXX EAM : be careful here with F32 vs F64 vectors 2478 psPolynomial2D* RobustFit2D(psPolynomial2D* poly, 2479 psVector* mask, 2480 const psVector* x, 2481 const psVector* y, 2482 const psVector* z, 2483 const psVector* dz) 2484 { 2485 PS_ASSERT_VECTOR_NON_NULL(mask, NULL); 2486 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2487 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2488 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 2489 PS_ASSERT_VECTOR_NON_NULL(dz, NULL); 2490 2491 psVector *zFit = NULL; 2492 psVector *zResid = psVectorAlloc (x->n, PS_TYPE_F64); 2493 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV); 2494 2495 for (int N = 0; N < 3; N++) { 2496 poly = VectorFitPolynomial2DOrd_EAM (poly, mask, x, y, z, dz); 2497 zFit = Polynomial2DEvalVectorD (poly, x, y); 2498 zResid = (psVector *) psBinaryOp(zResid, (void *) z, "-", (void *) zFit); 2499 2500 stats = psVectorStats (stats, zResid, NULL, mask, 1); 2501 psTrace (".psphot.RobustFit", 4, "residual stats for robust fit: %g +/- %g\n", 2502 stats->sampleMean, stats->sampleStdev); 2503 2504 // set mask if pts are not valid 2505 // we are masking out any point which is out of range 2506 // recovery is not allowed with this scheme 2507 for (int i = 0; i < zResid->n; i++) { 2508 if (mask->data.U8[i]) 2509 continue; 2510 if (fabs(zResid->data.F64[i] - stats->sampleMean) > 3*stats->sampleStdev) { 2511 mask->data.U8[i] = 1; 2512 continue; 2513 } 2514 } 2515 psFree (zFit); 2516 } 2517 psFree (zResid); 2518 psFree (stats); 2519 return (poly); 2520 } 2521 2522
Note:
See TracChangeset
for help on using the changeset viewer.
