Changeset 13976
- Timestamp:
- Jun 25, 2007, 3:04:56 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psphot/src/psphotModelWithPSF.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/psphotModelWithPSF.c
r13845 r13976 1 1 # include "psphot.h" 2 3 // XXX elevate the p_psMinLM_ functions to psMinLM_... 4 5 6 bool psphotModelWithPSF_LMM ( 7 psMinimization *min, 8 psImage *covar, 9 psVector *params, 10 psMinConstraint *constraint, 11 const pmSource *source, 12 const psKernel *psf, 13 psMinimizeLMChi2Func func) 14 { 15 psTrace("psLib.math", 3, "---- begin ----\n"); 16 PS_ASSERT_PTR_NON_NULL(min, false); 17 PS_ASSERT_VECTOR_NON_NULL(params, false); 18 PS_ASSERT_VECTOR_NON_EMPTY(params, false); 19 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false); 20 psVector *paramMask = NULL; 21 if (constraint != NULL) { 22 paramMask = constraint->paramMask; 23 if (paramMask != NULL) { 24 PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_U8, false); 25 PS_ASSERT_VECTORS_SIZE_EQUAL(params, paramMask, false); 26 } 27 } 28 PS_ASSERT_PTR_NON_NULL(func, false); 29 PS_ASSERT_PTR_NON_NULL(source, false); 30 31 psMinimizeLMLimitFunc checkLimits = NULL; 32 if (constraint) { 33 checkLimits = constraint->checkLimits; 34 } 35 36 // this function has test values and current values for several things 37 // the current value is in lower case 38 // the test value is in upper case 39 40 // allocate internal arrays (current vs Guess) 41 psImage *alpha = psImageAlloc(params->n, params->n, PS_TYPE_F32); 42 psImage *Alpha = psImageAlloc(params->n, params->n, PS_TYPE_F32); 43 psVector *beta = psVectorAlloc(params->n, PS_TYPE_F32); 44 psVector *Beta = psVectorAlloc(params->n, PS_TYPE_F32); 45 psVector *Params = psVectorAlloc(params->n, PS_TYPE_F32); 46 47 psF32 Chisq = 0.0; 48 psF32 lambda = 0.001; 49 50 // calculate initial alpha and beta, set chisq (min->value) 51 min->value = psphotModelWithPSF_SetABX(alpha, beta, params, paramMask, source, psf, func); 52 if (isnan(min->value)) { 53 min->iter = min->maxIter; 54 return(false); 55 } 56 // dump some useful info if trace is defined 57 if (psTraceGetLevel("psLib.math") >= 6) { 58 p_psImagePrint(psTraceGetDestination(), alpha, "alpha guess (0)"); 59 p_psVectorPrint(psTraceGetDestination(), beta, "beta guess (0)"); 60 } 61 if (psTraceGetLevel("psLib.math") >= 5) { 62 p_psVectorPrint(psTraceGetDestination(), params, "params guess (0)"); 63 } 64 65 // iterate until the tolerance is reached, or give up 66 while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) { 67 psTrace("psLib.math", 5, "Iteration number %d. (max iterations is %d).\n", min->iter, min->maxIter); 68 psTrace("psLib.math", 5, "Last delta is %f. Min->tol is %f.\n", min->lastDelta, min->tol); 69 70 // set a new guess for Alpha, Beta, Params 71 if (!p_psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda)) { 72 min->iter ++; 73 lambda *= 10.0; 74 continue; 75 } 76 77 // measure linear model prediction 78 psF32 dLinear = p_psMinLM_dLinear(Beta, beta, lambda); 79 80 // dump some useful info if trace is defined 81 if (psTraceGetLevel("psLib.math") >= 6) { 82 p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (1)"); 83 p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (1)"); 84 } 85 if (psTraceGetLevel("psLib.math") >= 5) { 86 p_psVectorPrint(psTraceGetDestination(), Params, "params guess (1)"); 87 } 88 89 // calculate Chisq for new guess, update Alpha & Beta 90 Chisq = p_psMinLM_SetABX(Alpha, Beta, Params, paramMask, source, func); 91 if (isnan(Chisq)) { 92 min->iter ++; 93 lambda *= 10.0; 94 continue; 95 } 96 97 // convergence criterion: 98 // compare the delta (min->value - Chisq) with the 99 // expected delta from the linear model (dLinear) 100 // accept new guess if it is an improvement (rho > 0), or else increase lambda 101 psF32 rho = (min->value - Chisq) / dLinear; 102 103 psTrace("psLib.math", 5, "last chisq: %f, new chisq %f, delta: %f, rho: %f\n", min->value, 104 Chisq, min->lastDelta, rho); 105 106 // dump some useful info if trace is defined 107 if (psTraceGetLevel("psLib.math") >= 6) { 108 p_psImagePrint(psTraceGetDestination(), Alpha, "alpha guess (2)"); 109 p_psVectorPrint(psTraceGetDestination(), Beta, "beta guess (2)"); 110 } 111 112 /* if (Chisq < min->value) { */ 113 if (rho > 0.0) { 114 min->lastDelta = (min->value - Chisq) / (dy->n - params->n); 115 min->value = Chisq; 116 alpha = psImageCopy(alpha, Alpha, PS_TYPE_F32); 117 beta = psVectorCopy(beta, Beta, PS_TYPE_F32); 118 params = psVectorCopy(params, Params, PS_TYPE_F32); 119 lambda *= 0.1; 120 } else { 121 lambda *= 10.0; 122 } 123 min->iter++; 124 } 125 psTrace("psLib.math", 5, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter); 126 127 // construct & return the covariance matrix (if requested) 128 if (covar != NULL) { 129 if (!p_psMinLM_GuessABP(covar, Beta, Params, alpha, beta, params, paramMask, NULL, 0.0)) { 130 psTrace ("psLib.math", 5, "failure to calculate covariance matrix\n"); 131 } 132 } 133 134 // free the internal temporary data 135 psFree(alpha); 136 psFree(Alpha); 137 psFree(beta); 138 psFree(Beta); 139 psFree(Params); 140 141 if (min->iter == min->maxIter) { 142 psTrace("psLib.math", 3, "---- end (false) ----\n"); 143 return(false); 144 } 145 146 psTrace("psLib.math", 3, "---- end (true) ----\n"); 147 return(true); 148 } 149 150 psF32 psphotModelWithPSF_SetABX( 151 psImage *alpha, 152 psVector *beta, 153 const psVector *params, 154 const psVector *paramMask, 155 const pmSource *source, 156 const psKernel *psf, 157 psMinimizeLMChi2Func func) 158 { 159 // XXX: Check vector sizes. 160 PS_ASSERT_IMAGE_NON_NULL(alpha, NAN); 161 PS_ASSERT_VECTOR_NON_NULL(beta, NAN); 162 PS_ASSERT_VECTOR_NON_NULL(params, NAN); 163 164 PS_ASSERT_PTR_NON_NULL(source, NAN); 165 PS_ASSERT_IMAGE_NON_NULL(source->pixels, NAN); 166 PS_ASSERT_IMAGE_NON_NULL(source->weight, NAN); 167 PS_ASSERT_IMAGE_NON_NULL(source->maskObj, NAN); 168 169 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false); 170 if (paramMask) { 171 PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_MASK, false); 172 } 173 174 psF32 chisq; 175 psF32 delta; 176 psF32 weight; 177 psF32 ymodel; 178 psVector *deriv = psVectorAlloc(params->n, PS_TYPE_F32); 179 180 // generate the model and derivative images for this parameter set 181 psImage *model = psImageAlloc (source->pixels->numCols, source->pixels->numRows, PS_TYPE_F32); 182 psArray *dmodels = psArrayAlloc (params->n); 183 for (psS32 n = 0; n < params->n; n++) { 184 if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; } 185 psImage *dmodel = psImageAlloc (source->pixels->numCols, source->pixels->numRows, PS_TYPE_F32); 186 dmodels->data[n] = dmodel; 187 } 188 189 // working vector to store local coordinate 190 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); 191 192 // fill in the coordinate and value entries 193 nPix = 0; 194 for (psS32 i = 0; i < source->pixels->numRows; i++) { 195 for (psS32 j = 0; j < source->pixels->numCols; j++) { 196 // skip masked points 197 // XXX probably should not skipped masked points: 198 // XXX skip if convolution of unmasked pixels will not see this pixel 199 if (source->maskObj->data.U8[i][j]) { 200 continue; 201 } 202 // skip zero-weight points 203 // XXX why is this not masked? 204 if (source->weight->data.F32[i][j] == 0) { 205 continue; 206 } 207 // skip nan value points 208 // XXX why is this not masked? 209 if (!isfinite(source->pixels->data.F32[i][j])) { 210 continue; 211 } 212 213 // Convert i/j to image space: 214 coord->data.F32[0] = (psF32) (j + source->pixels->col0); 215 coord->data.F32[1] = (psF32) (i + source->pixels->row0); 216 217 model->data.F32[i][j] = func (deriv, params, coord); 218 219 for (int n = 0; n < params->n; n++) { 220 if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; } 221 psImage *dmodel = dmodels->data[n]; 222 dmodel->data.F32[i][j] = deriv->data.F32[n]; 223 } 224 } 225 } 226 psFree (coord); 227 228 // convolve model and dmodel arrays with PSF 229 psImage *modelConv = psImageConvolveDirect (model, psf); 230 psArray *dmodelsConv = psArrayAlloc (params->n); 231 for (int n = 0; n < params->n; n++) { 232 if ((paramMask != NULL) && (paramMask->data.U8[n])) { continue; } 233 psImage *dmodel = dmodels->data[n]; 234 psImage *dmodelConv = psImageConvolveDirect (dmodel, psf); 235 dmodelsConv->data[n] = dmodelConv; 236 } 237 238 // zero alpha and beta for summing below 239 psImageInit (alpha, 0.0); 240 psVectorInit (beta, 0.0); 241 chisq = 0.0; 242 243 for (psS32 i = 0; i < source->pixels->numRows; i++) { 244 for (psS32 j = 0; j < source->pixels->numCols; j++) { 245 // XXX are we doing the right thing with the mask? 246 // skip masked points 247 if (source->maskObj->data.U8[i][j]) { 248 continue; 249 } 250 // skip zero-weight points 251 if (source->weight->data.F32[i][j] == 0) { 252 continue; 253 } 254 // skip nan value points 255 if (!isfinite(source->pixels->data.F32[i][j])) { 256 continue; 257 } 258 259 ymodel = modelConv->data.F32[i][j]; 260 yweight = 1.0 / source->weight->data.F32[i][j]; 261 delta = ymodel - source->pixels->data.F32[i][j]; 262 263 chisq += PS_SQR(delta) * var; 264 265 if (isnan(delta)) 266 psAbort("nan in delta"); 267 if (isnan(chisq)) 268 psAbort("nan in chisq"); 269 270 for (psS32 n1 = 0; n1 < params->n; n1++) { 271 if ((paramMask != NULL) && (paramMask->data.U8[n1])) { 272 continue; 273 } 274 psImage *dmodel = dmodelsConv->data[n1]; 275 weight = dmodel->data.F32[i][j] * yweight; 276 for (psS32 n2 = 0; n2 <= n1; n2++) { 277 if ((paramMask != NULL) && (paramMask->data.U8[n2])) { 278 continue; 279 } 280 dmodel = dmodelsConv->data[n2]; 281 alpha->data.F32[n1][n2] += weight * dmodel->data.F32[i][j]; 282 } 283 beta->data.F32[jn] += weight * delta; 284 } 285 } 286 } 287 288 // calculate lower-left half of alpha 289 for (psS32 j = 1; j < params->n; j++) { 290 for (psS32 k = 0; k < j; k++) { 291 alpha->data.F32[k][j] = alpha->data.F32[j][k]; 292 } 293 } 294 295 // fill in pivots if we apply a mask 296 if (paramMask != NULL) { 297 for (psS32 j = 0; j < params->n; j++) { 298 if (paramMask->data.U8[j]) { 299 alpha->data.F32[j][j] = 1; 300 beta->data.F32[j] = 1; 301 } 302 } 303 } 304 305 psFree (model); 306 psFree (dmodels); 307 psFree (modelConv); 308 psFree (dmodelsConv); 309 psFree(deriv); 310 311 return(chisq); 312 } 313 314 2 315 3 316 /* … … 7 320 * basic LMM: 8 321 9 * 322 - fill in the data (x, y) 323 324 chisq = SetABX (alpha, beta, params, paramMask, x, y, dy, func) 325 326 while () { 327 GuessABP (Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda) 328 dLinear = dLinear(Beta, beta, lambda); 329 chisq = SetABX (alpha, beta, params, paramMask, x, y, dy, func) 330 convergence tests... 331 } 332 333 334 335 ** GuessABP: 336 337 f_c = sum_i (kern_i * func (x_i; p_o)) 338 339 df_c/dp_o = d/dp_o [sum_i (kern_i * func (x_i; p_o))] 340 341 df_c/dp_o = sum_i (d/dp_o [kern_i * func (x_i; p_o)]) 342 343 df_c/dp_o = sum_i (kern_i * d/dp_o [func (x_i; p_o)]) 344 345 - generate image arrays for func, dfunc/dp_j (not masked) 346 - convolve each with psf 347 - measure delta = f_conv - data 348 - etc 349 */ 350 351
Note:
See TracChangeset
for help on using the changeset viewer.
