IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42491


Ignore:
Timestamp:
Aug 13, 2023, 2:05:42 PM (3 years ago)
Author:
eugene
Message:

adding IRLS fitting to 1D vector fits

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20230313/psLib/src/math/psMinimizePolyFit.c

    r41896 r42491  
    10301030}
    10311031
     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.
     1038bool 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}
    10321203
    10331204/******************************************************************************
Note: See TracChangeset for help on using the changeset viewer.