Changeset 42492
- Timestamp:
- Aug 15, 2023, 4:56:54 AM (3 years ago)
- Location:
- branches/eam_branches/ipp-20230313/psLib/src/math
- Files:
-
- 4 edited
-
psMinimizePolyFit.c (modified) (4 diffs)
-
psMinimizePolyFit.h (modified) (1 diff)
-
psPolynomial.c (modified) (2 diffs)
-
psPolynomial.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20230313/psLib/src/math/psMinimizePolyFit.c
r42491 r42492 48 48 /* DEFINE STATEMENTS */ 49 49 /*****************************************************************************/ 50 #define CZW 050 #define CZW 1 51 51 52 52 # define USE_GAUSS_JORDAN 1 … … 1030 1030 } 1031 1031 1032 // This function assumes the input vectors (f, fEval, fErr) all have the same type 1033 // This requirement is already enforced in the calling function (psVectorIRLSFitPolynomial1D) 1034 psVector *psVector_GetModifiedErrors_Caucy ( 1035 const psVector *f, 1036 const psVector *fEval, 1037 const psVector *fErr, 1038 const psVector *mask, 1039 psVectorMaskType maskValue) { 1040 1041 psVector *mErr = psVectorAlloc (f->n, f->type.type); 1042 1043 switch (f->type.type) { 1044 case PS_TYPE_F64: 1045 { 1046 psF64 *fPtr = f->data.F64; 1047 psF64 *fErrPtr = fErr->data.F64; 1048 psF64 *mErrPtr = mErr->data.F64; 1049 psF64 *fEvalPtr = fEval->data.F64; 1050 for (int i = 0; i < f->n; i++, fPtr++, fEvalPtr++, fErrPtr++, mErrPtr++) { 1051 if (mask && (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskValue)) continue; 1052 double dF = (*fPtr - *fEvalPtr) / 2.385; 1053 double dV = PS_SQR(*fErrPtr) + PS_SQR(dF); 1054 *mErrPtr = sqrt(dV); 1055 } 1056 } 1057 break; 1058 case PS_TYPE_F32: 1059 { 1060 psF32 *fPtr = f->data.F32; 1061 psF32 *fErrPtr = fErr->data.F32; 1062 psF32 *mErrPtr = mErr->data.F32; 1063 psF32 *fEvalPtr = fEval->data.F32; 1064 for (int i = 0; i < f->n; i++, fPtr++, fEvalPtr++, fErrPtr++, mErrPtr++) { 1065 if (mask && (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskValue)) continue; 1066 double dF = (*fPtr - *fEvalPtr) / 2.385; 1067 double dV = PS_SQR(*fErrPtr) + PS_SQR(dF); 1068 *mErrPtr = sqrt(dV); 1069 } 1070 } 1071 break; 1072 default: 1073 psError(PS_ERR_UNKNOWN, false, "invalid input data type.\n"); 1074 return NULL; 1075 } 1076 return mErr; 1077 } 1078 1032 1079 // These should probably be tunable: 1033 1080 # define FIT_TOLERANCE 1e-4 … … 1036 1083 1037 1084 // This function accepts F32 and F64 input vectors. 1085 // 1038 1086 bool psVectorIRLSFitPolynomial1D( 1039 1087 psPolynomial1D *poly, 1088 psStats *stats, 1040 1089 const psVector *mask, 1041 1090 psVectorMaskType maskValue, … … 1078 1127 } 1079 1128 1080 // IRLS fitting is performed by adjusting the total weights for each point based on 1081 // the distance of the value from the last fit. start with weights set to 1.0 (the 1082 // max) and adjust as needed. 1083 1084 psVector *weights = psVectorAlloc(f->n, PS_TYPE_F64); 1085 psVectorInit (weights, 1.0); 1086 1087 // initial fit with weights set to 1.0 1129 // initial fit with nominal errors 1088 1130 if (!psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x)) { 1089 1131 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning false.\n"); 1090 1132 if (xIn == NULL) psFree(x); 1091 psFree (weights);1092 1133 return false; 1093 1134 } 1094 1135 1095 psVector *fEval = psPolynomial1DEvalVector (poly, x); 1096 1097 for (psS32 N = 0; N < stats->clipIter; N++) { 1136 // use polyOld to save the last fit 1137 psPolynomial1D *polyOld = NULL; 1138 1139 // use clipIter as max number of iterations 1140 bool converged = false; 1141 for (psS32 N = 0; !converged && (N < stats->clipIter); N++) { 1098 1142 psTrace("psLib.math", 6, "Loop iteration %d. Calling psVectorFitPolynomial1D()\n", N); 1099 psS32 Nkeep = 0; 1100 if (psTraceGetLevel("psLib.math") >= 6) { 1101 if (mask != NULL) { 1102 for (psS32 i = 0 ; i < mask->n ; i++) { 1103 psTrace("psLib.math", 6, "mask[%d] is %d\n", i, mask->data.PS_TYPE_VECTOR_MASK_DATA[i]); 1104 } 1105 } 1106 } 1107 if (!psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x)) { 1143 1144 // evaluate the fit at the input positions 1145 psVector *fEval = psPolynomial1DEvalVector (poly, x); 1146 1147 // calculate modified errors based on the deviation from the fit 1148 psVector *modErr = psVector_GetModifiedErrors_Caucy (f, fEval, fErr, mask, maskValue); 1149 psFree (fEval); 1150 1151 // save the last fit (recycle the structure once allocated) 1152 polyOld = psPolynomial1DCopy (polyOld, poly); 1153 1154 // calculate a new fit with modified errors: 1155 if (!psVectorFitPolynomial1D(poly, mask, maskValue, f, modErr, x)) { 1108 1156 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning false.\n"); 1109 if (xIn == NULL) { 1110 psFree(x); 1111 } 1112 psFree(resid); 1113 1157 if (xIn == NULL) psFree(x); 1158 psFree(modErr); 1114 1159 return false; 1115 1160 } 1116 1161 1117 psVector *fit = psPolynomial1DEvalVector(poly, x); 1118 if (fit == NULL) { 1119 psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector(). Returning false.\n"); 1120 if (xIn == NULL) { 1121 psFree(x); 1122 } 1123 psFree(resid); 1124 return false; 1125 } 1126 for (psS32 i = 0 ; i < f->n ; i++) { 1127 if (f->type.type == PS_TYPE_F64) { 1128 resid->data.F64[i] = f->data.F64[i] - fit->data.F64[i]; 1129 } else { 1130 resid->data.F64[i] = (psF64) (f->data.F32[i] - fit->data.F32[i]); 1131 } 1132 } 1133 if (psTraceGetLevel("psLib.math") >= 6) { 1134 if (mask != NULL) { 1135 for (psS32 i = 0 ; i < mask->n ; i++) { 1136 if (!((mask != NULL) && (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskValue))) { 1137 psTrace("psLib.math", 6, "(f, fit)[%d] is (%f, %f). resid is (%f)\n", 1138 i, f->data.F32[i], fit->data.F32[i], resid->data.F64[i]); 1139 } 1140 } 1141 } 1142 } 1143 1144 if (!psVectorStats(stats, resid, NULL, mask, maskValue)) { 1145 psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector. Returning false.\n"); 1146 psFree(resid); 1147 psFree(fit); 1148 return false; 1149 } 1150 1151 double meanValue = psStatsGetValue (stats, meanOption); 1152 double stdevValue = psStatsGetValue (stats, stdevOption); 1153 1154 psTrace("psLib.math", 5, "Mean is %f\n", meanValue); 1155 psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue); 1156 psF32 minClipValue = -minClipSigma*stdevValue; 1157 psF32 maxClipValue = +maxClipSigma*stdevValue; 1158 1159 // set mask if pts are not valid 1160 // we are masking out any point which is out of range 1161 // recovery is not allowed with this scheme 1162 for (psS32 i = 0; i < resid->n; i++) { 1163 if ((mask != NULL) && (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskValue)) { 1164 continue; 1165 } 1166 1167 if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) { 1168 if (f->type.type == PS_TYPE_F64) { 1169 psTrace("psLib.math", 6, "Masking element %d (%f). resid->data.F64[%d] is %f\n", 1170 i, fit->data.F64[i], i, resid->data.F64[i]); 1171 } else { 1172 psTrace("psLib.math", 6, "Masking element %d (%f). resid->data.F64[%d] is %f\n", 1173 i, fit->data.F32[i], i, resid->data.F64[i]); 1174 } 1175 1176 if (mask != NULL) { 1177 mask->data.PS_TYPE_VECTOR_MASK_DATA[i] |= 0x01; 1178 } 1179 continue; 1180 } 1181 Nkeep++; 1182 } 1183 1184 // 1185 // We should probably exit this loop if no new elements were masked 1186 // since the polynomial fit won't change. 1187 // 1188 psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n); 1189 stats->clippedNvalues = Nkeep; 1190 psFree(fit); 1191 } 1192 1193 // Free psVectors that were created for NULL arguments. 1194 if (xIn == NULL) { 1195 psFree(x); 1196 } 1197 // Free other local temporary variables 1198 psFree(resid); 1162 // has the solution converged? 1163 converged = true; 1164 for (int ix = 0; ix <= poly->nX; ix++) { 1165 if ((fabs(poly->coeff[ix] - polyOld->coeff[ix]) > FIT_TOLERANCE * fabs(poly->coeff[ix])) && 1166 (fabs(poly->coeff[ix] - polyOld->coeff[ix]) > FLT_TOLERANCE)) 1167 converged = false; 1168 } 1169 1170 psFree (modErr); 1171 } 1172 1173 // Free local temporary variables 1174 if (xIn == NULL) psFree(x); 1175 psFree(polyOld); 1199 1176 1200 1177 psTrace("psLib.math", 3, "---- %s() end ----\n", __func__); -
branches/eam_branches/ipp-20230313/psLib/src/math/psMinimizePolyFit.h
r21183 r42492 134 134 ); 135 135 136 bool psVectorIRLSFitPolynomial1D( 137 psPolynomial1D *poly, 138 psStats *stats, 139 const psVector *mask, 140 psVectorMaskType maskValue, 141 const psVector *f, 142 const psVector *fErr, 143 const psVector *x 144 ); 145 136 146 /// @} 137 147 #endif // #ifndef PS_MINIMIZE_POLYFIT_H -
branches/eam_branches/ipp-20230313/psLib/src/math/psPolynomial.c
r41896 r42492 806 806 } 807 807 808 // XXX add 1D, 3D, 4D versions809 bool psPolynomial2DRecycle(psPolynomial2D *poly,810 psPolynomialType type,811 unsigned int nX,812 unsigned int nY)813 {814 PS_ASSERT_INT_NONNEGATIVE(nX, NULL);815 PS_ASSERT_INT_NONNEGATIVE(nY, NULL);816 817 bool match = true;818 match &= (poly->type == type);819 match &= (poly->nX == type);820 match &= (poly->nY == type);821 822 if (!match) {823 for (int i = 0; i < poly->nX + 1; i++) {824 psFree (poly->coeff[i]);825 psFree (poly->coeffErr[i]);826 psFree (poly->coeffMask[i]);827 }828 psFree (poly->coeff);829 psFree (poly->coeffErr);830 psFree (poly->coeffMask);831 832 poly->type = type;833 poly->nX = nX;834 poly->nY = nY;835 836 poly->coeff = psAlloc((1 + nX) * sizeof(psF64 *));837 poly->coeffErr = psAlloc((1 + nX) * sizeof(psF64 *));838 poly->coeffMask = (psMaskType **)psAlloc((1 + nX) * sizeof(psMaskType *));839 for (int i = 0; i < (1 + nX); i++) {840 poly->coeff[i] = psAlloc((1 + nY) * sizeof(psF64));841 poly->coeffErr[i] = psAlloc((1 + nY) * sizeof(psF64));842 poly->coeffMask[i] = (psMaskType *)psAlloc((1 + nY) * sizeof(psMaskType));843 }844 }845 for (int i = 0; i < (1 + nX); i++) {846 for (int j = 0; j < (1 + nY); j++) {847 poly->coeff[i][j] = 0.0;848 poly->coeffErr[i][j] = 0.0;849 poly->coeffMask[i][j] = PS_POLY_MASK_NONE;850 }851 }852 return(true);853 }854 855 // XXX add 1D, 3D, 4D versions856 psPolynomial2D *psPolynomial2DCopy(psPolynomial2D *out,857 psPolynomial2D *poly)858 {859 if (out == NULL) {860 out = psPolynomial2DAlloc (poly->type, poly->nX, poly->nY);861 } else {862 psPolynomial2DRecycle (out, poly->type, poly->nX, poly->nY);863 }864 865 for (int i = 0; i < (1 + poly->nX); i++) {866 for (int j = 0; j < (1 + poly->nY); j++) {867 out->coeff[i][j] = poly->coeff[i][j];868 out->coeffErr[i][j] = poly->coeffErr[i][j];869 out->coeffMask[i][j] = poly->coeffMask[i][j];870 }871 }872 return(out);873 }874 875 808 psPolynomial3D* psPolynomial3DAlloc( 876 809 psPolynomialType type, … … 1002 935 } 1003 936 937 // XXX add 3D, 4D versions 938 bool psPolynomial1DRecycle(psPolynomial1D *poly, 939 psPolynomialType type, 940 unsigned int nX) 941 { 942 PS_ASSERT_INT_NONNEGATIVE(nX, NULL); 943 944 bool match = true; 945 match &= (poly->type == type); 946 match &= (poly->nX == type); 947 948 if (!match) { 949 psFree (poly->coeff); 950 psFree (poly->coeffErr); 951 psFree (poly->coeffMask); 952 953 poly->type = type; 954 poly->nX = nX; 955 956 poly->coeff = psAlloc((1 + nX) * sizeof(psF64)); 957 poly->coeffErr = psAlloc((1 + nX) * sizeof(psF64)); 958 poly->coeffMask = (psMaskType *)psAlloc((1 + nX) * sizeof(psMaskType)); 959 } 960 for (int i = 0; i < (1 + nX); i++) { 961 poly->coeff[i] = 0.0; 962 poly->coeffErr[i] = 0.0; 963 poly->coeffMask[i] = PS_POLY_MASK_NONE; 964 } 965 return(true); 966 } 967 968 bool psPolynomial2DRecycle(psPolynomial2D *poly, 969 psPolynomialType type, 970 unsigned int nX, 971 unsigned int nY) 972 { 973 PS_ASSERT_INT_NONNEGATIVE(nX, NULL); 974 PS_ASSERT_INT_NONNEGATIVE(nY, NULL); 975 976 bool match = true; 977 match &= (poly->type == type); 978 match &= (poly->nX == type); 979 match &= (poly->nY == type); 980 981 if (!match) { 982 for (int i = 0; i < poly->nX + 1; i++) { 983 psFree (poly->coeff[i]); 984 psFree (poly->coeffErr[i]); 985 psFree (poly->coeffMask[i]); 986 } 987 psFree (poly->coeff); 988 psFree (poly->coeffErr); 989 psFree (poly->coeffMask); 990 991 poly->type = type; 992 poly->nX = nX; 993 poly->nY = nY; 994 995 poly->coeff = psAlloc((1 + nX) * sizeof(psF64 *)); 996 poly->coeffErr = psAlloc((1 + nX) * sizeof(psF64 *)); 997 poly->coeffMask = (psMaskType **)psAlloc((1 + nX) * sizeof(psMaskType *)); 998 for (int i = 0; i < (1 + nX); i++) { 999 poly->coeff[i] = psAlloc((1 + nY) * sizeof(psF64)); 1000 poly->coeffErr[i] = psAlloc((1 + nY) * sizeof(psF64)); 1001 poly->coeffMask[i] = (psMaskType *)psAlloc((1 + nY) * sizeof(psMaskType)); 1002 } 1003 } 1004 for (int i = 0; i < (1 + nX); i++) { 1005 for (int j = 0; j < (1 + nY); j++) { 1006 poly->coeff[i][j] = 0.0; 1007 poly->coeffErr[i][j] = 0.0; 1008 poly->coeffMask[i][j] = PS_POLY_MASK_NONE; 1009 } 1010 } 1011 return(true); 1012 } 1013 1014 // XXX 3D, 4D versions 1015 psPolynomial1D *psPolynomial1DCopy(psPolynomial1D *out, 1016 psPolynomial1D *poly) 1017 { 1018 if (out == NULL) { 1019 out = psPolynomial1DAlloc (poly->type, poly->nX); 1020 } else { 1021 psPolynomial1DRecycle (out, poly->type, poly->nX); 1022 } 1023 1024 for (int i = 0; i < (1 + poly->nX); i++) { 1025 out->coeff[i] = poly->coeff[i]; 1026 out->coeffErr[i] = poly->coeffErr[i]; 1027 out->coeffMask[i] = poly->coeffMask[i]; 1028 } 1029 return(out); 1030 } 1031 psPolynomial2D *psPolynomial2DCopy(psPolynomial2D *out, 1032 psPolynomial2D *poly) 1033 { 1034 if (out == NULL) { 1035 out = psPolynomial2DAlloc (poly->type, poly->nX, poly->nY); 1036 } else { 1037 psPolynomial2DRecycle (out, poly->type, poly->nX, poly->nY); 1038 } 1039 1040 for (int i = 0; i < (1 + poly->nX); i++) { 1041 for (int j = 0; j < (1 + poly->nY); j++) { 1042 out->coeff[i][j] = poly->coeff[i][j]; 1043 out->coeffErr[i][j] = poly->coeffErr[i][j]; 1044 out->coeffMask[i][j] = poly->coeffMask[i][j]; 1045 } 1046 } 1047 return(out); 1048 } 1049 1004 1050 /* note these functions accept unscaled values and apply the scaling saved on poly */ 1005 1051 psF64 psPolynomial1DEval(const psPolynomial1D* poly, -
branches/eam_branches/ipp-20230313/psLib/src/math/psPolynomial.h
r42336 r42492 161 161 ) PS_ATTR_MALLOC; 162 162 163 bool psPolynomial1DRecycle(psPolynomial1D *poly, 164 psPolynomialType type, 165 unsigned int nX); 166 163 167 bool psPolynomial2DRecycle(psPolynomial2D *poly, 164 168 psPolynomialType type, 165 169 unsigned int nX, 166 170 unsigned int nY); 171 172 psPolynomial1D *psPolynomial1DCopy(psPolynomial1D *out, 173 psPolynomial1D *poly); 167 174 168 175 psPolynomial2D *psPolynomial2DCopy(psPolynomial2D *out,
Note:
See TracChangeset
for help on using the changeset viewer.
