Changeset 5818
- Timestamp:
- Dec 20, 2005, 12:41:06 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psMinimize.c (modified) (20 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMinimize.c
r5655 r5818 10 10 * @author EAM, IfA 11 11 * 12 * @version $Revision: 1.14 7$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-12- 01 23:36:23$12 * @version $Revision: 1.148 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-12-20 22:41:06 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 113 113 } 114 114 115 // XXX: Check error codes! 115 116 psGaussJordan(Alpha, Beta); 116 117 psFree(A); … … 1441 1442 } 1442 1443 1443 // here is the definition for BuildSums4D. ifdef'ed away until it is used 1444 // by psPolynomial4DFit.. 1445 # if (0) 1446 /****************************************************************************** 1444 /****************************************************************************** 1445 BuildSums3D(sums, x, y, z, nXterm, nYterm, nZterm): this routine calculates the powers of 1446 input parameter "x", "y", and "z" between 0 and input parameter nXterms*2, 1447 nYterm*2, and nZterm*2. The result is returned as a psImage sums. 1448 *****************************************************************************/ 1449 static psF64 ***BuildSums3D( 1450 psF64 ***sums, 1451 psF64 x, 1452 psF64 y, 1453 psF64 z, 1454 psS32 nXterm, 1455 psS32 nYterm, 1456 psS32 nZterm) 1457 { 1458 psS32 nXsum = 0; 1459 psS32 nYsum = 0; 1460 psS32 nZsum = 0; 1461 psF64 xSum = 1.0; 1462 psF64 ySum = 1.0; 1463 psF64 zSum = 1.0; 1464 1465 nXsum = 2*nXterm; 1466 nYsum = 2*nYterm; 1467 nZsum = 2*nZterm; 1468 if (sums == NULL) { 1469 sums = (psF64 ***) psAlloc (nXsum*sizeof(psF64)); 1470 for (int i = 0; i < nXsum; i++) { 1471 sums[i] = (psF64 **) psAlloc (nYsum*sizeof(psF64)); 1472 for (int j = 0; j < nYsum; j++) { 1473 sums[i][j] = (psF64 *) psAlloc (nZsum*sizeof(psF64)); 1474 } 1475 } 1476 } 1477 // careful with this function: there is no size checking and realloc for reuse 1478 1479 zSum = 1.0; 1480 for (int k = 0; k < nZsum; k++) { 1481 ySum = zSum; 1482 for (int j = 0; j < nYsum; j++) { 1483 xSum = ySum; 1484 for (int i = 0; i < nXsum; i++) { 1485 sums[i][j][k] = xSum; 1486 xSum *= x; 1487 } 1488 ySum *= y; 1489 } 1490 zSum *= z; 1491 } 1492 return (sums); 1493 } 1494 1495 /****************************************************************************** 1447 1496 BuildSums4D(sums, x, y, z, t, nXterm, nYterm, nZterm, nTterm). equiv to 1448 1497 BuildSums2D(). The result is returned as a double **** 1449 *****************************************************************************/1450 static double****BuildSums4D(1451 psF64 ****sums,1452 psF64 x,1453 psF64 y,1454 psF64 z,1455 psF64 t,1456 psS32 nXterm,1457 psS32 nYterm,1458 psS32 nZterm,1459 psS32 nTterm)1498 *****************************************************************************/ 1499 static psF64 ****BuildSums4D( 1500 psF64 ****sums, 1501 psF64 x, 1502 psF64 y, 1503 psF64 z, 1504 psF64 t, 1505 psS32 nXterm, 1506 psS32 nYterm, 1507 psS32 nZterm, 1508 psS32 nTterm) 1460 1509 { 1461 1510 psS32 nXsum = 0; … … 1505 1554 return (sums); 1506 1555 } 1507 # endif /* BuildSums4D */1508 1556 1509 1557 /****************************************************************************** … … 1556 1604 1557 1605 /****************************************************************************** 1558 vectorFitPolynomial1DCheb (): This routine will fit a Chebyshev polynomial of1559 degree myPoly to the data points (x, y) and return the coefficients of that1606 vectorFitPolynomial1DChebSlow(): This routine will fit a Chebyshev polynomial 1607 of degree myPoly to the data points (x, y) and return the coefficients of that 1560 1608 polynomial. 1609 1610 NOTE: We currently have implemented two algorithms. This one is 1611 non-standard. It ignores the orthogonal properties of the Chebyshev 1612 polys, and their known zero values. Instead, we do build a system of 1613 linear equations based on minimizing the chi-squared for all data points 1614 and we then solve those equations. This method is significantly slower 1615 than the other algorithm. It was explicitly requested that we implement 1616 this algorithm. 1561 1617 1562 1618 XXX: mask, maskValue, yErr are currently ignored. … … 1564 1620 XXX: Change arg order to that of the psLib function. 1565 1621 *****************************************************************************/ 1566 static psPolynomial1D *vectorFitPolynomial1DCheby (1622 static psPolynomial1D *vectorFitPolynomial1DChebySlow( 1567 1623 psPolynomial1D* myPoly, 1568 1624 const psVector *mask, … … 1572 1628 const psVector* x) 1573 1629 { 1574 // XXX: these ASSERTS are redundant. 1630 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 1631 PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(myPoly->nX, 0, NULL); 1632 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 1633 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 1634 if (yErr != NULL) { 1635 PS_ASSERT_VECTORS_SIZE_EQUAL(y, yErr, NULL); 1636 PS_ASSERT_VECTOR_TYPE(yErr, PS_TYPE_F64, NULL); 1637 } 1638 if (x != NULL) { 1639 PS_ASSERT_VECTORS_SIZE_EQUAL(y, x, NULL); 1640 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 1641 } 1642 psS32 NUM_POLY = myPoly->nX+1; 1643 psS32 NUM_DATA = x->n; 1644 psPolynomial1D **chebPolys = createChebyshevPolys(NUM_POLY); 1645 if (0) { 1646 for (psS32 j = 0; j < NUM_POLY; j++) { 1647 PS_POLY_PRINT_1D(chebPolys[j]); 1648 } 1649 } 1650 1651 // Pre-compute the various Chebyshev polys T_i(x[j]) for all x[] 1652 psImage *tMatrix = psImageAlloc(NUM_DATA, NUM_POLY, PS_TYPE_F64); 1653 for (psS32 p = 0 ; p < NUM_POLY ; p++) { 1654 for (psS32 d = 0 ; d < NUM_DATA ; d++) { 1655 tMatrix->data.F64[p][d] = psPolynomial1DEval(chebPolys[p], x->data.F64[d]); 1656 } 1657 } 1658 1659 // Compute the A matrix 1660 psImage *A = psImageAlloc(NUM_POLY, NUM_POLY, PS_TYPE_F64); 1661 for (psS32 i = 0 ; i < NUM_POLY ; i++) { 1662 for (psS32 j = 0 ; j < NUM_POLY ; j++) { 1663 A->data.F64[i][j] = 0.0; 1664 for (psS32 d = 0 ; d < NUM_DATA ; d++) { 1665 A->data.F64[i][j]+= (tMatrix->data.F64[j][d] * tMatrix->data.F64[i][d]); 1666 } 1667 } 1668 // This is because of the last term in: f(x) = SUM[c_i * T_i(x)] - c_0/2 1669 for (psS32 d = 0 ; d < NUM_DATA ; d++) { 1670 A->data.F64[i][0] -= (tMatrix->data.F64[i][d]/2.0); 1671 } 1672 } 1673 1674 // Compute the B vector 1675 psVector *B = psVectorAlloc(NUM_POLY, PS_TYPE_F64); 1676 for (psS32 i = 0 ; i < NUM_POLY ; i++) { 1677 B->data.F64[i] = 0.0; 1678 for (psS32 d = 0 ; d < NUM_DATA ; d++) { 1679 B->data.F64[i] += (y->data.F64[d] * tMatrix->data.F64[i][d]); 1680 1681 } 1682 } 1683 1684 // GaussJordan version 1685 if (0) { 1686 // does the solution in place 1687 // XXX: Check error codes! 1688 psGaussJordan (A, B); 1689 1690 // the first nTerm entries in B correspond directly to the desired 1691 // polynomial coefficients. this is only true for the 1D case 1692 for (psS32 k = 0; k < NUM_POLY; k++) { 1693 myPoly->coeff[k] = B->data.F64[k]; 1694 } 1695 } else { 1696 // LUD version of the fit 1697 psImage *ALUD = NULL; 1698 psVector* outPerm = NULL; 1699 psVector* coeffs = NULL; 1700 1701 ALUD = psImageAlloc(NUM_POLY, NUM_POLY, PS_TYPE_F64); 1702 ALUD = psMatrixLUD(ALUD, &outPerm, A); 1703 coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm); 1704 for (psS32 k = 0; k < NUM_POLY; k++) { 1705 myPoly->coeff[k] = coeffs->data.F64[k]; 1706 } 1707 1708 psFree(ALUD); 1709 psFree(coeffs); 1710 psFree(outPerm); 1711 } 1712 1713 psFree(A); 1714 psFree(B); 1715 psFree(tMatrix); 1716 for (psS32 i=0;i<NUM_POLY;i++) { 1717 psFree(chebPolys[i]); 1718 } 1719 psFree(chebPolys); 1720 1721 return(myPoly); 1722 } 1723 1724 /****************************************************************************** 1725 vectorFitPolynomial1DChebFast(): This routine will fit a Chebyshev polynomial 1726 of degree myPoly to the data points (x, y) and return the coefficients of that 1727 polynomial. 1728 1729 NOTE: We currently have two algorithms. This is standard method which 1730 uses the orthogonal properties of the Chebyshev polys, and their known 1731 zero values. This is significantly faster than the chi-squared approach. 1732 1733 XXX: mask, maskValue, yErr are currently ignored. 1734 1735 XXX: Change arg order to that of the psLib function. 1736 1737 XXX: This function will not work properly if the x-vector does not fully span 1738 the [-1:1] interval. 1739 *****************************************************************************/ 1740 static psPolynomial1D *vectorFitPolynomial1DChebyFast( 1741 psPolynomial1D* myPoly, 1742 const psVector *mask, 1743 psMaskType maskValue, 1744 const psVector* y, 1745 const psVector* yErr, 1746 const psVector* x) 1747 { 1575 1748 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 1576 1749 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL); … … 1614 1787 for (psS32 i=0;i<n;i++) { 1615 1788 // NR 5.8.4 1789 // NR 5.8.4 1616 1790 psF64 Y = cos(M_PI * (0.5 + ((psF32) i)) / ((psF32) n)); 1617 1791 psF64 X = (Y + bma + bpa) - 1.0; … … 1620 1794 // We interpolate against the tabluated x,y vectors to determine the 1621 1795 // function value at X. 1622 fScalar = p_psVectorInterpolate((psVector *) x, 1623 (psVector *) y, 1624 3, 1625 &tmpScalar); 1626 1627 f->data.F64[i] = fScalar->data.F64; 1628 psFree(fScalar); 1796 // XXX: This is somewhat of a hack to handle cases where the x vector does 1797 // not fully span the [-1.0:1.0] interval. We set the values of f[] to the 1798 // values of y[] at those endpoints. 1799 // XXX: This only works if x[] is increasing. 1800 1801 if (X <= x->data.F64[0]) { 1802 f->data.F64[i] = y->data.F64[0]; 1803 } else if (X >= x->data.F64[x->n-1]) { 1804 f->data.F64[i] = y->data.F64[x->n-1]; 1805 } else { 1806 fScalar = p_psVectorInterpolate((psVector *) x, (psVector *) y, 1807 3, &tmpScalar); 1808 f->data.F64[i] = fScalar->data.F64; 1809 psFree(fScalar); 1810 } 1629 1811 1630 1812 psTrace(".psLib.dataManip.vectorFitPolynomial1DCheby", 6, … … 1650 1832 return(myPoly); 1651 1833 } 1834 1835 1652 1836 1653 1837 /****************************************************************************** … … 1759 1943 if (0) { 1760 1944 // does the solution in place 1945 // XXX: Check error codes! 1761 1946 psGaussJordan (A, B); 1762 1947 … … 1859 2044 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 1860 2045 } 2046 if (fErr != NULL) { 2047 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring error vector with Chebyshev polynomials.\n"); 2048 } 1861 2049 if (x == NULL) { 1862 2050 // If x==NULL, create an x64 vector with x values set to (-1:1). 1863 2051 PS_VECTOR_GEN_CHEBY_INDEX(x64, f64->n); 1864 2052 } 1865 // XXX: Change arg order. 1866 // XXX: Must modify this routine so that x64 or fErr64 can be NULL. 1867 poly = vectorFitPolynomial1DCheby(poly, NULL, 0, f64, fErr64, x64); 2053 2054 if (1) { 2055 poly = vectorFitPolynomial1DChebySlow(poly, NULL, 0, f64, fErr64, x64); 2056 } else { 2057 poly = vectorFitPolynomial1DChebyFast(poly, NULL, 0, f64, fErr64, x64); 2058 } 1868 2059 if (x == NULL) { 1869 2060 psFree(x64); … … 2102 2293 2103 2294 // does the solution in place 2295 // XXX: Check error codes! 2104 2296 psGaussJordan (A, B); 2105 2297 … … 2475 2667 } 2476 2668 2669 2477 2670 /****************************************************************************** 2478 2671 ****************************************************************************** 2479 3-D Vector Fit tingCode.2672 3-D Vector Fit Code. 2480 2673 ****************************************************************************** 2481 2674 *****************************************************************************/ … … 2526 2719 } 2527 2720 2528 psError(PS_ERR_UNKNOWN, true, "3-D Polynomial Fitting is not Implemented.\n"); 2529 return (NULL); 2721 psImage *A = NULL; 2722 psVector *B = NULL; 2723 psF64 ***Sums = NULL; 2724 psF64 wt; 2725 psS32 nTerm; 2726 2727 // XXX:Watch for changes to the psPolys: nTerm != nOrder. 2728 psS32 nXterm = 1 + myPoly->nX; 2729 psS32 nYterm = 1 + myPoly->nY; 2730 psS32 nZterm = 1 + myPoly->nZ; 2731 nTerm = nXterm * nYterm * nZterm; 2732 2733 A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); 2734 B = psVectorAlloc(nTerm, PS_TYPE_F64); 2735 2736 // Initialize data structures. 2737 psVectorInit (B, 0.0); 2738 psImageInit (A, 0.0); 2739 2740 // Sums look like: 1, x, x^2, ... x^(2n+1), y, xy, x^2y, ... x^(2n+1)*y, ... 2741 2742 // Build the B and A data structs. 2743 for (int k = 0; k < x->n; k++) { 2744 if ((mask != NULL) && (mask->data.U8[k] & maskValue)) { 2745 continue; 2746 } 2747 2748 Sums = BuildSums3D(Sums, x->data.F64[k], y->data.F64[k], z->data.F64[k], nXterm, nYterm, nZterm); 2749 2750 if (fErr == NULL) { 2751 wt = 1.0; 2752 } else { 2753 // this filters fErr == 0 values 2754 wt = (fErr->data.F64[k] == 0.0) ? 0.0 : 1.0 / PS_SQR(fErr->data.F64[k]); 2755 } 2756 2757 // we could skip half of the array and assign at the end 2758 // we must handle masked orders 2759 for (int ix = 0; ix < nXterm; ix++) { 2760 for (int iy = 0; iy < nYterm; iy++) { 2761 for (int iz = 0; iz < nZterm; iz++) { 2762 if (myPoly->mask[ix][iy][iz]) 2763 continue; 2764 int nx = ix+iy*nXterm+iz*nXterm*nYterm; 2765 B->data.F64[nx] += f->data.F64[k] * Sums[ix][iy][iz] * wt; 2766 } 2767 } 2768 } 2769 2770 for (int ix = 0; ix < nXterm; ix++) { 2771 for (int iy = 0; iy < nYterm; iy++) { 2772 for (int iz = 0; iz < nZterm; iz++) { 2773 if (myPoly->mask[ix][iy][iz]) 2774 continue; 2775 int nx = ix+iy*nXterm+iz*nXterm*nYterm; 2776 for (int jx = 0; jx < nXterm; jx++) { 2777 for (int jy = 0; jy < nYterm; jy++) { 2778 for (int jz = 0; jz < nZterm; jz++) { 2779 if (myPoly->mask[jx][jy][jz]) 2780 continue; 2781 int ny = jx+jy*nXterm+jz*nXterm*nYterm; 2782 A->data.F64[nx][ny] += Sums[ix+jx][iy+jy][iz+jz] * wt; 2783 } 2784 } 2785 } 2786 } 2787 } 2788 } 2789 } 2790 2791 for (int ix = 0; ix < nXterm; ix++) { 2792 for (int iy = 0; iy < nYterm; iy++) { 2793 for (int iz = 0; iz < nZterm; iz++) { 2794 if (!myPoly->mask[ix][iy][iz]) 2795 continue; 2796 int nx = ix+iy*nXterm+iz*nXterm*nYterm; 2797 B->data.F64[nx] = 0; 2798 for (int jx = 0; jx < nXterm; jx++) { 2799 for (int jy = 0; jy < nYterm; jy++) { 2800 for (int jz = 0; jz < nZterm; jz++) { 2801 int ny = jx+jy*nXterm+jz*nXterm*nYterm; 2802 A->data.F64[nx][ny] = (nx == ny) ? 1 : 0; 2803 } 2804 } 2805 } 2806 } 2807 } 2808 } 2809 2810 // PS_IMAGE_PRINT_F64(A); 2811 // PS_VECTOR_PRINT_F64(B); 2812 // does the solution in place 2813 if (false == psGaussJordan (A, B)) { 2814 psFree(A); 2815 psFree(B); 2816 2817 for (int ix = 0; ix < 2*nXterm; ix++) { 2818 for (int iy = 0; iy < 2*nYterm; iy++) { 2819 psFree(Sums[ix][iy]); 2820 } 2821 psFree(Sums[ix]); 2822 } 2823 psFree(Sums); 2824 psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n"); 2825 return(NULL); 2826 } 2827 2828 // select the appropriate solution entries 2829 for (int ix = 0; ix < nXterm; ix++) { 2830 for (int iy = 0; iy < nYterm; iy++) { 2831 for (int iz = 0; iz < nZterm; iz++) { 2832 int nx = ix+iy*nXterm+iz*nXterm*nYterm; 2833 myPoly->coeff[ix][iy][iz] = B->data.F64[nx]; 2834 myPoly->coeffErr[ix][iy][iz] = sqrt(A->data.F64[nx][nx]); 2835 } 2836 } 2837 } 2838 2839 psFree(A); 2840 psFree(B); 2841 2842 for (int ix = 0; ix < 2*nXterm; ix++) { 2843 for (int iy = 0; iy < 2*nYterm; iy++) { 2844 psFree(Sums[ix][iy]); 2845 } 2846 psFree(Sums[ix]); 2847 } 2848 psFree(Sums); 2849 2850 psTrace(".psLib.dataManip.VectorFitPolynomial3DOrd", 4, 2851 "---- VectorFitPolynomial3DOrd() begin ----\n"); 2852 return (myPoly); 2530 2853 } 2531 2854 … … 2599 2922 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL); 2600 2923 if (z->type.type != PS_TYPE_F64) { 2601 PS_VECTOR_GEN_F64_FROM_F32( y64, z);2924 PS_VECTOR_GEN_F64_FROM_F32(z64, z); 2602 2925 } else { 2603 2926 z64 = (psVector *) z; … … 2714 3037 PS_ASSERT_PTR_NON_NULL(stats, NULL); 2715 3038 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2716 PS_ASSERT_VECTOR_TYPE (f, PS_TYPE_F32, NULL);3039 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL); 2717 3040 if (mask != NULL) { 2718 3041 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); … … 2721 3044 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2722 3045 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2723 PS_ASSERT_VECTOR_TYPE (x, PS_TYPE_F32, NULL);3046 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL); 2724 3047 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2725 3048 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2726 PS_ASSERT_VECTOR_TYPE (y, PS_TYPE_F32, NULL);3049 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL); 2727 3050 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2728 PS_ASSERT_VECTORS_SIZE_EQUAL(f, f, NULL);2729 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);3051 // PS_ASSERT_VECTORS_SIZE_EQUAL(f, f, NULL); 3052 // PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL); 2730 3053 if (fErr != NULL) { 2731 3054 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL); 2732 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2733 } 2734 2735 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2736 return(NULL); 3055 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 3056 } 3057 3058 // clipping range defined by min and max and/or clipSigma 3059 float minClipSigma; 3060 float maxClipSigma; 3061 if (isfinite(stats->max)) { 3062 maxClipSigma = fabs(stats->max); 3063 } else { 3064 maxClipSigma = fabs(stats->clipSigma); 3065 } 3066 if (isfinite(stats->min)) { 3067 minClipSigma = fabs(stats->min); 3068 } else { 3069 minClipSigma = fabs(stats->clipSigma); 3070 } 3071 psVector *fit = NULL; 3072 psVector *resid = psVectorAlloc (x->n, PS_TYPE_F64); 3073 3074 // eventual expansion: user supplies one of various stats option pairs, 3075 // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to 3076 // evaluate the clipping sigma 3077 // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used 3078 stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 3079 3080 for (int N = 0; N < stats->clipIter; N++) { 3081 int Nkeep = 0; 3082 3083 poly = psVectorFitPolynomial3D (poly, mask, maskValue, f, fErr, x, y, z); 3084 fit = psPolynomial3DEvalVector (poly, x, y, z); 3085 resid = (psVector *) psBinaryOp (resid, (void *) f, "-", (void *) fit); 3086 3087 stats = psVectorStats (stats, resid, NULL, mask, maskValue); 3088 float minClipValue = -minClipSigma*stats->sampleStdev; 3089 float maxClipValue = +maxClipSigma*stats->sampleStdev; 3090 psTrace (".psphot.VectorClipFit", 5, "resid stats: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev); 3091 psTrace (".psphot.VectorClipFit", 5, "min clip: %f, max clip: %f\n", minClipValue, maxClipValue); 3092 3093 // set mask if pts are not valid 3094 // we are masking out any point which is out of range 3095 // recovery is not allowed with this scheme 3096 for (int i = 0; i < resid->n; i++) { 3097 if ((mask != NULL) && (mask->data.U8[i] & maskValue)) { 3098 continue; 3099 } 3100 if (resid->data.F64[i] - stats->sampleMedian > maxClipValue) { 3101 if (mask != NULL) { 3102 mask->data.U8[i] |= 0x01; 3103 } 3104 continue; 3105 } 3106 if (resid->data.F64[i] - stats->sampleMedian < minClipValue) { 3107 if (mask != NULL) { 3108 mask->data.U8[i] |= 0x01; 3109 } 3110 continue; 3111 } 3112 Nkeep ++; 3113 } 3114 3115 psTrace (".psphot.VectorClipFit", 4, "keeping %d of %d pts for fit\n", 3116 Nkeep, x->n); 3117 3118 psFree (fit); 3119 } 3120 // Free local temporary variables 3121 psFree (resid); 3122 3123 if (poly == NULL) { 3124 psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data. Returning NULL.\n"); 3125 return(NULL); 3126 } 3127 return(poly); 2737 3128 } 2738 2739 3129 2740 3130 /****************************************************************************** … … 2792 3182 } 2793 3183 2794 psError(PS_ERR_UNKNOWN, true, "4-D Polynomial Fitting is not Implemented.\n"); 2795 return (NULL); 3184 // I think this is 1 dimension down 3185 psImage *A = NULL; 3186 psVector *B = NULL; 3187 psF64 ****Sums = NULL; 3188 psF64 wt; 3189 psS32 nTerm; 3190 3191 // XXX:Watch for changes to the psPolys: nTerm != nOrder. 3192 psS32 nXterm = 1 + myPoly->nX; 3193 psS32 nYterm = 1 + myPoly->nY; 3194 psS32 nZterm = 1 + myPoly->nZ; 3195 psS32 nTterm = 1 + myPoly->nZ; 3196 nTerm = nXterm * nYterm * nZterm * nTterm; 3197 3198 A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); 3199 B = psVectorAlloc(nTerm, PS_TYPE_F64); 3200 3201 // Initialize data structures. 3202 psVectorInit (B, 0.0); 3203 psImageInit (A, 0.0); 3204 3205 // Sums look like: 1, x, x^2, ... x^(2n+1), y, xy, x^2y, ... x^(2n+1)*y, ... 3206 3207 // Build the B and A data structs. 3208 for (int k = 0; k < x->n; k++) { 3209 if ((mask != NULL) && (mask->data.U8[k] & maskValue)) { 3210 continue; 3211 } 3212 3213 Sums = BuildSums4D(Sums, x->data.F64[k], y->data.F64[k], z->data.F64[k], t->data.F64[k], nXterm, nYterm, nZterm, nTterm); 3214 3215 if (fErr == NULL) { 3216 wt = 1.0; 3217 } else { 3218 // this filters fErr == 0 values 3219 wt = (fErr->data.F64[k] == 0.0) ? 0.0 : 1.0 / PS_SQR(fErr->data.F64[k]); 3220 } 3221 3222 // we could skip half of the array and assign at the end 3223 // we must handle masked orders 3224 for (int ix = 0; ix < nXterm; ix++) { 3225 for (int iy = 0; iy < nYterm; iy++) { 3226 for (int iz = 0; iz < nZterm; iz++) { 3227 for (int it = 0; it < nTterm; it++) { 3228 if (myPoly->mask[ix][iy][iz][it]) 3229 continue; 3230 int nx = ix+iy*nXterm+iz*nXterm*nYterm+it*nXterm*nYterm*nZterm; 3231 B->data.F64[nx] += f->data.F64[k] * Sums[ix][iy][iz][it] * wt; 3232 } 3233 } 3234 } 3235 } 3236 3237 for (int ix = 0; ix < nXterm; ix++) { 3238 for (int iy = 0; iy < nYterm; iy++) { 3239 for (int iz = 0; iz < nZterm; iz++) { 3240 for (int it = 0; it < nTterm; it++) { 3241 if (myPoly->mask[ix][iy][iz][it]) 3242 continue; 3243 int nx = ix+iy*nXterm+iz*nXterm*nYterm+it*nXterm*nYterm*nZterm; 3244 for (int jx = 0; jx < nXterm; jx++) { 3245 for (int jy = 0; jy < nYterm; jy++) { 3246 for (int jz = 0; jz < nZterm; jz++) { 3247 for (int jt = 0; jt < nTterm; jt++) { 3248 if (myPoly->mask[jx][jy][jz][jt]) 3249 continue; 3250 int ny = jx+jy*nXterm+jz*nXterm*nYterm+jt*nXterm*nYterm*nZterm; 3251 A->data.F64[nx][ny]+= Sums[ix+jx][iy+jy][iz+jz][it+jt] * wt; 3252 } 3253 } 3254 } 3255 } 3256 } 3257 } 3258 } 3259 } 3260 } 3261 3262 for (int ix = 0; ix < nXterm; ix++) { 3263 for (int iy = 0; iy < nYterm; iy++) { 3264 for (int iz = 0; iz < nZterm; iz++) { 3265 for (int it = 0; it < nTterm; it++) { 3266 if (!myPoly->mask[ix][iy][iz][it]) 3267 continue; 3268 int nx = ix+iy*nXterm+iz*nXterm*nYterm+it*nXterm*nYterm*nZterm; 3269 B->data.F64[nx] = 0; 3270 for (int jx = 0; jx < nXterm; jx++) { 3271 for (int jy = 0; jy < nYterm; jy++) { 3272 for (int jz = 0; jz < nZterm; jz++) { 3273 for (int jt = 0; jt < nTterm; jt++) { 3274 int ny = jx+jy*nXterm+jz*nXterm*nYterm+jt*nXterm*nYterm*nZterm; 3275 A->data.F64[nx][ny] = (nx == ny) ? 1 : 0; 3276 } 3277 } 3278 } 3279 } 3280 } 3281 } 3282 } 3283 } 3284 3285 // does the solution in place 3286 3287 if (false == psGaussJordan(A, B)) { 3288 psFree(A); 3289 psFree(B); 3290 for (int ix = 0; ix < 2*nXterm; ix++) { 3291 for (int iy = 0; iy < 2*nYterm; iy++) { 3292 for (int iz = 0; iz < 2*nZterm; iz++) { 3293 psFree(Sums[ix][iy][iz]); 3294 } 3295 psFree(Sums[ix][iy]); 3296 } 3297 psFree(Sums[ix]); 3298 } 3299 psFree(Sums); 3300 psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n"); 3301 return(NULL); 3302 } 3303 3304 // select the appropriate solution entries 3305 for (int ix = 0; ix < nXterm; ix++) { 3306 for (int iy = 0; iy < nYterm; iy++) { 3307 for (int iz = 0; iz < nZterm; iz++) { 3308 for (int it = 0; it < nTterm; it++) { 3309 int nx = ix+iy*nXterm+iz*nXterm*nYterm+it*nXterm*nYterm*nZterm; 3310 myPoly->coeff[ix][iy][iz][it] = B->data.F64[nx]; 3311 myPoly->coeffErr[ix][iy][iz][it] = sqrt(A->data.F64[nx][nx]); 3312 } 3313 } 3314 } 3315 } 3316 3317 psFree(A); 3318 psFree(B); 3319 3320 for (int ix = 0; ix < 2*nXterm; ix++) { 3321 for (int iy = 0; iy < 2*nYterm; iy++) { 3322 for (int iz = 0; iz < 2*nZterm; iz++) { 3323 psFree(Sums[ix][iy][iz]); 3324 } 3325 psFree(Sums[ix][iy]); 3326 } 3327 psFree(Sums[ix]); 3328 } 3329 psFree(Sums); 3330 3331 psTrace(".psLib.dataManip.VectorFitPolynomial3DOrd", 4, 3332 "---- VectorFitPolynomial3DOrd() begin ----\n"); 3333 return (myPoly); 2796 3334 } 2797 3335 … … 3029 3567 } 3030 3568 3031 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 3032 3033 return(NULL); 3569 // clipping range defined by min and max and/or clipSigma 3570 float minClipSigma; 3571 float maxClipSigma; 3572 if (isfinite(stats->max)) { 3573 maxClipSigma = fabs(stats->max); 3574 } else { 3575 maxClipSigma = fabs(stats->clipSigma); 3576 } 3577 if (isfinite(stats->min)) { 3578 minClipSigma = fabs(stats->min); 3579 } else { 3580 minClipSigma = fabs(stats->clipSigma); 3581 } 3582 psVector *fit = NULL; 3583 psVector *resid = psVectorAlloc (x->n, PS_TYPE_F64); 3584 3585 // eventual expansion: user supplies one of various stats option pairs, 3586 // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to 3587 // evaluate the clipping sigma 3588 // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used 3589 stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 3590 3591 for (int N = 0; N < stats->clipIter; N++) { 3592 int Nkeep = 0; 3593 3594 poly = psVectorFitPolynomial4D (poly, mask, maskValue, f, fErr, x, y, z, t); 3595 fit = psPolynomial4DEvalVector (poly, x, y, z, t); 3596 resid = (psVector *) psBinaryOp (resid, (void *) f, "-", (void *) fit); 3597 3598 stats = psVectorStats (stats, resid, NULL, mask, maskValue); 3599 float minClipValue = -minClipSigma*stats->sampleStdev; 3600 float maxClipValue = +maxClipSigma*stats->sampleStdev; 3601 psTrace (".psphot.VectorClipFit", 5, "resid stats: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev); 3602 psTrace (".psphot.VectorClipFit", 5, "min clip: %f, max clip: %f\n", minClipValue, maxClipValue); 3603 3604 // set mask if pts are not valid 3605 // we are masking out any point which is out of range 3606 // recovery is not allowed with this scheme 3607 for (int i = 0; i < resid->n; i++) { 3608 if ((mask != NULL) && (mask->data.U8[i] & maskValue)) { 3609 continue; 3610 } 3611 if (resid->data.F64[i] - stats->sampleMedian > maxClipValue) { 3612 if (mask != NULL) { 3613 mask->data.U8[i] |= 0x01; 3614 } 3615 continue; 3616 } 3617 if (resid->data.F64[i] - stats->sampleMedian < minClipValue) { 3618 if (mask != NULL) { 3619 mask->data.U8[i] |= 0x01; 3620 } 3621 continue; 3622 } 3623 Nkeep ++; 3624 } 3625 3626 psTrace (".psphot.VectorClipFit", 4, "keeping %d of %d pts for fit\n", 3627 Nkeep, x->n); 3628 3629 psFree (fit); 3630 } 3631 // Free local temporary variables 3632 psFree (resid); 3633 3634 if (poly == NULL) { 3635 psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data. Returning NULL.\n"); 3636 return(NULL); 3637 } 3638 return(poly); 3034 3639 } 3035 3036
Note:
See TracChangeset
for help on using the changeset viewer.
