Changeset 42842 for trunk/psphot/src/psphotMakeResiduals.c
- Timestamp:
- May 9, 2025, 11:21:40 AM (15 months ago)
- Location:
- trunk/psphot
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
src/psphotMakeResiduals.c (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot
- Property svn:mergeinfo changed
/branches/eam_branches/ipp-20230313/psphot (added) merged: 42435,42439,42507-42510,42529,42582,42612,42707,42711
- Property svn:mergeinfo changed
-
trunk/psphot/src/psphotMakeResiduals.c
r35559 r42842 1 1 # include "psphotInternal.h" 2 pmConfig *psphotGetConfig (); 3 bool _psphotSaveCube (char *basename, char *extname, psArray *cube); 2 4 3 5 # define RESIDUAL_SOFTENING 0.005 … … 93 95 psVector *yC = psVectorAllocEmpty (100, PS_TYPE_F32); 94 96 97 # define TESTRESID 0 98 # if (TESTRESID) 99 psArray *sourceRawCube = psArrayAllocEmpty (1); 100 psArray *sourceSigCube = psArrayAllocEmpty (1); 101 psArray *sourceVarCube = psArrayAllocEmpty (1); 102 psArray *sourceMskCube = psArrayAllocEmpty (1); 103 104 psImage *refImage = NULL; 105 # endif 106 95 107 // build (DATA - MODEL) [an image] for each psf star 96 108 psArray *input = psArrayAllocEmpty (100); … … 108 120 psImage *mask = psImageCopy (NULL, source->maskView ? source->maskView : source->maskObj, PS_TYPE_IMAGE_MASK); 109 121 psImage *variance = psImageCopy (NULL, source->variance ? source->variance : source->pixels, PS_TYPE_F32); 122 123 # if (TESTRESID) 124 psImage *tmpImage = psImageCopy(NULL, image, PS_TYPE_F32); 125 if (refImage == NULL) { 126 refImage = tmpImage; 127 psArrayAdd (sourceRawCube, 1, tmpImage); 128 } else { 129 if (tmpImage->numCols != refImage->numCols) { 130 fprintf (stderr, "mismatched image sizes (%d : %f, %f)\n", i, model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]); 131 continue; 132 } 133 if (tmpImage->numRows != refImage->numRows) { 134 fprintf (stderr, "mismatched image sizes (%d : %f, %f)\n", i, model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]); 135 continue; 136 } 137 psArrayAdd (sourceRawCube, 1, tmpImage); 138 psFree (tmpImage); 139 } 140 # endif 141 110 142 pmModelSub (image, mask, model, PM_MODEL_OP_FUNC, maskVal); 111 143 … … 114 146 psBinaryOp (image, image, "/", psScalarAlloc(Io, PS_TYPE_F32)); 115 147 psBinaryOp (variance, variance, "/", psScalarAlloc(Io*Io, PS_TYPE_F32)); 148 149 # if (TESTRESID) 150 psArrayAdd (sourceSigCube, 1, image); 151 psArrayAdd (sourceVarCube, 1, variance); 152 psArrayAdd (sourceMskCube, 1, mask); 153 # endif 116 154 117 155 // we interpolate the image and variance - include the mask or not? … … 142 180 psImageInit (resid->mask, 0); 143 181 182 183 # if (TESTRESID) 184 psArray *inputSigCube = psArrayAllocEmpty (1); 185 psArray *inputVarCube = psArrayAllocEmpty (1); 186 psArray *inputMskCube = psArrayAllocEmpty (1); 187 188 // below, we are generating the residual images with interpolation 189 // to save these in an output cube, I need to generate place-holder images here 190 for (int i = 0; i < input->n; i++) { 191 psImage *inputSig = psImageAlloc (resid->Ro->numCols, resid->Ro->numRows, PS_TYPE_F32); 192 psImage *inputVar = psImageAlloc (resid->Ro->numCols, resid->Ro->numRows, PS_TYPE_F32); 193 psImage *inputMsk = psImageAlloc (resid->Ro->numCols, resid->Ro->numRows, PS_TYPE_IMAGE_MASK); 194 195 psImageInit (inputSig, NAN); 196 psImageInit (inputVar, NAN); 197 psImageInit (inputMsk, 0); 198 199 psArrayAdd (inputSigCube, 1, inputSig); 200 psArrayAdd (inputVarCube, 1, inputVar); 201 psArrayAdd (inputMskCube, 1, inputMsk); 202 203 // XXX free these here, right? 204 psFree (inputSig); 205 psFree (inputVar); 206 psFree (inputMsk); 207 } 208 # endif 209 144 210 // x(resid) = (x(image) - Xo)*xBin + xCenter 145 211 … … 148 214 psVector *fmasks = psVectorAlloc (input->n, PS_TYPE_VECTOR_MASK); 149 215 150 // statistic to use to determine baseline for clipping151 psStats *fluxClip = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);152 psStats *fluxClipDef = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);153 216 // statistic to use to determine output flux 154 217 // XXX make API to convert statOption for MEAN/MEDIAN in to corresponding STDEV? … … 156 219 psStats *fluxStatsDef = psStatsAlloc (statOption | PS_STAT_SAMPLE_STDEV); 157 220 221 // use this for the IRLS fitting below (defines niter) 222 psStats *statsIRLS = psStatsAlloc(PS_STAT_CLIPPED_MEAN); statsIRLS->clipIter = 10; // max number of iterations 223 psPolynomial2D *polyIRLS = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 1, 1); 224 158 225 // Use psF64 to minimize overflow problems? 159 226 psImage *A = psImageAlloc(3, 3, PS_TYPE_F64); // Least-squares matrix … … 166 233 167 234 int nGoodPixel = 0; // pixel is off the image 235 236 // skip pixels outside of the requested radius 237 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows)); 238 if (radius > radiusMax) { 239 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 240 continue; 241 } 168 242 169 243 // build the vector of data values for this output pixel … … 194 268 nGoodPixel ++; 195 269 } 270 271 # if (TESTRESID) 272 psImage *inputSig = inputSigCube->data[i]; inputSig->data.F32[oy][ox] = flux; 273 psImage *inputVar = inputVarCube->data[i]; inputVar->data.F32[oy][ox] = flux; 274 psImage *inputMsk = inputMskCube->data[i]; inputMsk->data.PS_TYPE_IMAGE_MASK_DATA[oy][ox] = fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i]; 275 # endif 196 276 } 277 278 if (nGoodPixel < 0.05*input->n) { 279 fprintf (stderr, "warning: %d, %d : residual pixel with few input pixels: %d vs %d\n", ox, oy, nGoodPixel, (int) input->n); 280 } 197 281 198 282 // skip pixels with insufficient data … … 207 291 208 292 // measure the robust median to determine a baseline reference value 209 *fluxClip = *fluxClipDef;293 psStats *fluxClip = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 210 294 if (!psVectorStats (fluxClip, fluxes, NULL, fmasks, fmaskVal)) { 211 295 psError(PSPHOT_ERR_CONFIG, false, "Error calculating residual stats"); 296 psFree (fluxClip); 212 297 return false; 213 298 } 214 if (isnan(fluxClip-> robustMedian)) {299 if (isnan(fluxClip->sampleMedian)) { 215 300 resid->Ro->data.F32[oy][ox] = 0.0; 216 301 resid->Rx->data.F32[oy][ox] = 0.0; 217 302 resid->Ry->data.F32[oy][ox] = 0.0; 218 303 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = badMask; 304 psFree (fluxClip); 219 305 continue; 306 } 307 308 if (fabs(fluxClip->sampleMedian) > 1.5) { 309 fprintf (stderr, "warning: %d, %d : residual pixel has funny initial median value: %f\n", ox, oy, fluxClip->sampleMedian); 220 310 } 221 311 … … 223 313 int nKeep = 0; 224 314 for (int i = 0; i < fluxes->n; i++) { 225 float delta = fluxes->data.F32[i] - fluxClip-> robustMedian;315 float delta = fluxes->data.F32[i] - fluxClip->sampleMedian; 226 316 float sigma = sqrt (dfluxes->data.F32[i]); 227 317 float swing = fabs(delta) / sigma; … … 233 323 if (!fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i]) nKeep++; 234 324 } 325 psFree (fluxClip); 326 327 if (nKeep < 5) { 328 fprintf (stderr, "warning: %d, %d : residual pixel with few good pixels: %d vs %d\n", ox, oy, nKeep, (int) input->n); 329 } 235 330 236 331 if (SPATIAL_ORDER == 0) { … … 242 337 } 243 338 244 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows)); 245 if (radius > radiusMax) { 246 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 247 continue; 248 } 339 resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0; 249 340 250 341 resid->Ro->data.F32[oy][ox] = psStatsGetValue(fluxStats, statOption); 251 resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0;252 253 342 if (isnan(resid->Ro->data.F32[oy][ox])) { 254 343 resid->Ro->data.F32[oy][ox] = 0.0; 255 resid->Rx->data.F32[oy][ox] = 0.0;256 resid->Ry->data.F32[oy][ox] = 0.0;257 344 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = badMask; 258 345 continue; … … 265 352 assert (SPATIAL_ORDER == 1); 266 353 267 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows)); 268 if (radius > radiusMax) { 269 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 270 continue; 271 } 272 273 psImageInit(A, 0.0); 274 psVectorInit(B, 0.0); 275 for (int i = 0; i < fluxes->n; i++) { 276 if (fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i]) continue; 277 B->data.F64[0] += fluxes->data.F32[i]/dfluxes->data.F32[i]; 278 B->data.F64[1] += fluxes->data.F32[i]*xC->data.F32[i]/dfluxes->data.F32[i]; 279 B->data.F64[2] += fluxes->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i]; 280 281 A->data.F64[0][0] += 1.0/dfluxes->data.F32[i]; 282 A->data.F64[1][0] += xC->data.F32[i]/dfluxes->data.F32[i]; 283 A->data.F64[2][0] += yC->data.F32[i]/dfluxes->data.F32[i]; 284 285 A->data.F64[1][1] += PS_SQR(xC->data.F32[i])/dfluxes->data.F32[i]; 286 A->data.F64[2][2] += PS_SQR(yC->data.F32[i])/dfluxes->data.F32[i]; 287 A->data.F64[1][2] += xC->data.F32[i]*yC->data.F32[i]/dfluxes->data.F32[i]; 288 } 289 290 A->data.F64[0][1] = A->data.F64[1][0]; 291 A->data.F64[0][2] = A->data.F64[2][0]; 292 A->data.F64[2][1] = A->data.F64[1][2]; 293 294 if (!psMatrixGJSolve(A, B)) { 295 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 296 psWarning("Singular matrix solving for (y,x) = (%d,%d)'s residuals, masking", oy, ox); 297 continue; 298 } 299 300 resid->Ro->data.F32[oy][ox] = B->data.F64[0]; 301 resid->Rx->data.F32[oy][ox] = B->data.F64[1]; 302 resid->Ry->data.F32[oy][ox] = B->data.F64[2]; 303 304 float dRo = sqrt(A->data.F32[0][0]); 354 // we have the following vectors to describe this pixel: 355 // fluxes, dfluxes, fmasks, xC, yC 356 357 psVectorIRLSFitPolynomial2D (polyIRLS, statsIRLS, fmasks, fmaskVal, fluxes, dfluxes, xC, yC); 358 359 resid->Ro->data.F32[oy][ox] = polyIRLS->coeff[0][0]; 360 resid->Rx->data.F32[oy][ox] = polyIRLS->coeff[1][0]; 361 resid->Ry->data.F32[oy][ox] = polyIRLS->coeff[0][1]; 362 363 // is the error well-defined? 364 float dRo = polyIRLS->coeffErr[0][0]; 365 366 if (fabs(resid->Ro->data.F32[oy][ox]) > 1.5) { 367 fprintf (stderr, "warning: %d, %d : residual pixel has funny fit value: %f\n", ox, oy, resid->Ro->data.F32[oy][ox]); 368 } 305 369 306 370 if (fabs(resid->Ro->data.F32[oy][ox]) < pixelSN*dRo/sqrt(nKeep)) { 371 // fprintf (stderr, "mask : %d, %d : %f +/- %f (%f for %d) : %d\n", ox, oy, resid->Ro->data.F32[oy][ox], dRo, dRo/sqrt(nKeep), nKeep, resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox]); 307 372 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 308 373 resid->Ro->data.F32[oy][ox] = 0.0; 309 374 resid->Rx->data.F32[oy][ox] = 0.0; 310 375 resid->Ry->data.F32[oy][ox] = 0.0; 311 } 376 } else { 377 // fprintf (stderr, "keep : %d, %d : %f +/- %f (%f for %d) : %d\n", ox, oy, resid->Ro->data.F32[oy][ox], dRo, dRo/sqrt(nKeep), nKeep, resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox]); 378 } 312 379 } 313 380 } 314 381 } 382 383 # if (TESTRESID) 384 385 pmConfig *config = psphotGetConfig(); 386 char *output = psMetadataLookupStr (&status, config->arguments, "OUTPUT"); 387 388 // XXX // save the star coordinate vectors 389 // XXX 390 // XXX psString filename = NULL; 391 // XXX psStringAppend (&filename, "%s.instar.dat", output); 392 393 char filename[1024]; 394 sprintf (filename, "%s.instar.dat", output); 395 396 FILE *fout = fopen (filename, "w"); 397 for (int i = 0; i < xC->n; i++) { 398 fprintf (fout, "%d %f %f\n", i, xC->data.F32[i], yC->data.F32[i]); 399 } 400 fclose (fout); 401 402 _psphotSaveCube (output, "raw.raw.fits", sourceRawCube); 403 _psphotSaveCube (output, "sig.raw.fits", sourceSigCube); 404 _psphotSaveCube (output, "var.raw.fits", sourceVarCube); 405 _psphotSaveCube (output, "msk.raw.fits", sourceMskCube); 406 407 _psphotSaveCube (output, "sig.fits", inputSigCube); 408 _psphotSaveCube (output, "var.fits", inputVarCube); 409 _psphotSaveCube (output, "msk.fits", inputMskCube); 410 411 psFree (sourceRawCube); 412 psFree (sourceSigCube); 413 psFree (sourceVarCube); 414 psFree (sourceMskCube); 415 416 psFree (inputSigCube); 417 psFree (inputVarCube); 418 psFree (inputMskCube); 419 420 # endif 315 421 316 422 psFree (A); … … 329 435 psFree (fluxStats); 330 436 psFree (fluxStatsDef); 331 psFree (fluxClip);332 psFree (fluxClipDef);333 437 334 438 if (resid != NULL && psTraceGetLevel("psphot") > 5) { … … 340 444 } 341 445 446 psFree (statsIRLS); 447 psFree (polyIRLS); 448 342 449 psf->residuals = resid; 343 450 return (resid != NULL) ? true : false; 344 451 } 452 453 bool _psphotSaveCube (char *basename, char *extname, psArray *cube) { 454 455 psString filename = NULL; 456 psStringAppend (&filename, "%s.%s", basename, extname); 457 458 psFits *fits = psFitsOpen (filename, "w"); 459 if (!psFitsWriteImageCube (fits, NULL, cube, NULL)) { 460 fprintf (stderr, "failed to write the cube %s\n", filename); 461 } 462 psFitsClose (fits); 463 464 psFree (filename); 465 466 return true; 467 }
Note:
See TracChangeset
for help on using the changeset viewer.
