Changeset 42491
- Timestamp:
- Aug 13, 2023, 2:05:42 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20230313/psLib/src/math/psMinimizePolyFit.c
r41896 r42491 1030 1030 } 1031 1031 1032 // These should probably be tunable: 1033 # define FIT_TOLERANCE 1e-4 1034 # define FLT_TOLERANCE 1e-6 1035 # define WEIGHT_THRESHOLD 0.3 1036 1037 // This function accepts F32 and F64 input vectors. 1038 bool psVectorIRLSFitPolynomial1D( 1039 psPolynomial1D *poly, 1040 const psVector *mask, 1041 psVectorMaskType maskValue, 1042 const psVector *f, 1043 const psVector *fErr, 1044 const psVector *xIn) 1045 { 1046 psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__); 1047 PS_ASSERT_POLY_NON_NULL(poly, false); 1048 PS_ASSERT_VECTOR_NON_NULL(f, false); 1049 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 1050 PS_ASSERT_VECTOR_NON_NULL(mask, false); 1051 PS_ASSERT_VECTORS_SIZE_EQUAL(mask, f, false); 1052 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_VECTOR_MASK, false); 1053 1054 if (fErr != NULL) { 1055 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, f, false); 1056 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false); 1057 } 1058 1059 // Internal pointers for possibly NULL vectors. 1060 psVector *x = NULL; 1061 if (xIn != NULL) { 1062 PS_ASSERT_VECTORS_SIZE_EQUAL(xIn, f, false); 1063 PS_ASSERT_VECTOR_TYPE(xIn, f->type.type, false); 1064 x = (psVector *) xIn; 1065 } else { 1066 if (poly->type == PS_POLYNOMIAL_ORD) { 1067 x = psVectorCreate(NULL, 0, f->n, 1, f->type.type); 1068 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 1069 if (f->type.type == PS_TYPE_F32) { 1070 PS_VECTOR_GEN_CHEBY_INDEX(x, f->n, PS_TYPE_F32); 1071 } else if (f->type.type == PS_TYPE_F64) { 1072 PS_VECTOR_GEN_CHEBY_INDEX(x, f->n, PS_TYPE_F64); 1073 } 1074 } else { 1075 psError(PS_ERR_UNKNOWN, true, "Error, bad poly type.\n"); 1076 return false; 1077 } 1078 } 1079 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 1088 if (!psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x)) { 1089 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning false.\n"); 1090 if (xIn == NULL) psFree(x); 1091 psFree (weights); 1092 return false; 1093 } 1094 1095 psVector *fEval = psPolynomial1DEvalVector (poly, x); 1096 1097 for (psS32 N = 0; N < stats->clipIter; N++) { 1098 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)) { 1108 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning false.\n"); 1109 if (xIn == NULL) { 1110 psFree(x); 1111 } 1112 psFree(resid); 1113 1114 return false; 1115 } 1116 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); 1199 1200 psTrace("psLib.math", 3, "---- %s() end ----\n", __func__); 1201 return true; 1202 } 1032 1203 1033 1204 /******************************************************************************
Note:
See TracChangeset
for help on using the changeset viewer.
