- Timestamp:
- May 3, 2010, 8:50:52 AM (16 years ago)
- Location:
- branches/simtest_nebulous_branches
- Files:
-
- 4 edited
-
. (modified) (1 prop)
-
psphot (modified) (1 prop)
-
psphot/src (modified) (1 prop)
-
psphot/src/psphotApResid.c (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/simtest_nebulous_branches
- Property svn:mergeinfo changed
-
branches/simtest_nebulous_branches/psphot
-
Property svn:mergeinfo
set to (toggle deleted branches)
/trunk/psphot merged eligible /branches/eam_branches/stackphot.20100406/psphot 27622-27655 /branches/pap_delete/psphot 27530-27595
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
branches/simtest_nebulous_branches/psphot/src
- Property svn:ignore
-
old new 18 18 psphotVersionDefinitions.h 19 19 psphotMomentsStudy 20 psphotPetrosianStudy 21 psphotForced 22 psphotMakePSF 23 psphotStack
-
- Property svn:ignore
-
branches/simtest_nebulous_branches/psphot/src/psphotApResid.c
r24878 r27840 4 4 // measure the aperture residual statistics and 2D variations 5 5 6 bool psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf) 6 // for now, let's store the detections on the readout->analysis for each readout 7 bool psphotApResid (pmConfig *config, const pmFPAview *view) 8 { 9 bool status = true; 10 11 // select the appropriate recipe information 12 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 13 psAssert (recipe, "missing recipe?"); 14 15 int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM"); 16 psAssert (status, "programming error: must define PSPHOT.INPUT.NUM"); 17 18 // skip the chisq image (optionally?) 19 int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM"); 20 if (!status) chisqNum = -1; 21 22 // loop over the available readouts 23 for (int i = 0; i < num; i++) { 24 if (i == chisqNum) continue; // skip chisq image 25 if (!psphotApResidReadout (config, view, "PSPHOT.INPUT", i, recipe)) { 26 psError (PSPHOT_ERR_CONFIG, false, "failed to measure aperture residual for PSPHOT.INPUT entry %d", i); 27 return false; 28 } 29 } 30 return true; 31 } 32 33 bool psphotApResidReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) 7 34 { 8 35 int Nfail = 0; … … 13 40 pmSource *source; 14 41 15 PS_ASSERT_PTR_NON_NULL(config, false);16 PS_ASSERT_PTR_NON_NULL(readout, false);17 PS_ASSERT_PTR_NON_NULL(sources, false);18 PS_ASSERT_PTR_NON_NULL(psf, false);19 20 42 psTimerStart ("psphot.apresid"); 21 43 22 // select the appropriate recipe information 23 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 24 assert (recipe); 44 // find the currently selected readout 45 pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest 46 psAssert (file, "missing file?"); 47 48 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); 49 psAssert (readout, "missing readout?"); 50 51 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 52 psAssert (detections, "missing detections?"); 53 54 psArray *sources = detections->allSources; 55 psAssert (sources, "missing sources?"); 56 57 if (!sources->n) { 58 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping ap resid"); 59 return true; 60 } 61 62 pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF"); 63 psAssert (psf, "missing psf?"); 25 64 26 65 // determine the number of allowed threads … … 33 72 if (!measureAptrend) { 34 73 // save nan values since these were not calculated 35 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", NAN); 36 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", NAN); 37 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 38 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 39 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN); 40 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 74 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 75 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 76 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 77 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN); 41 78 return true; 42 79 } … … 53 90 maskVal |= markVal; 54 91 55 // S/N limit to perform full non-linear fits 92 // clipping for extreme outliers 93 // XXX this is not currently defined in the recipe 56 94 float MAX_AP_OFFSET = psMetadataLookupF32 (&status, recipe, "MAX_AP_OFFSET"); 57 95 58 // this is the smallest radius allowed: need to at least extend growth curve down to this... 96 // options for how the photometry is calculated 97 // XXX are these sensible? 59 98 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH"); 60 99 bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); … … 100 139 PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32); 101 140 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 141 PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK); 102 142 103 143 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nskip … … 110 150 } 111 151 psFree(job); 112 113 # if (0)114 int nskip = 0;115 int nfail = 0;116 117 if (!psphotApResidMags_Unthreaded (&nskip, &nfail, sources, psf, photMode, maskVal)) {118 psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");119 return false;120 }121 Nskip += nskip;122 Nfail += nfail;123 # endif124 125 152 } 126 153 … … 138 165 } else { 139 166 psScalar *scalar = NULL; 140 scalar = job->args->data[ 4];167 scalar = job->args->data[5]; 141 168 Nskip += scalar->data.S32; 142 scalar = job->args->data[ 5];169 scalar = job->args->data[6]; 143 170 Nfail += scalar->data.S32; 144 171 } … … 150 177 151 178 // gather the stats to assess the aperture residuals 152 psVector *mask = psVectorAllocEmpty (300, PS_TYPE_VECTOR_MASK);153 179 psVector *mag = psVectorAllocEmpty (300, PS_TYPE_F32); 154 180 psVector *xPos = psVectorAllocEmpty (300, PS_TYPE_F32); … … 158 184 Npsf = 0; 159 185 186 # ifdef DEBUG 187 FILE *f = fopen ("apresid.dat", "w"); 188 psAssert (f, "failed open"); 189 # endif 190 160 191 for (int i = 0; i < sources->n; i++) { 161 192 source = sources->data[i]; … … 170 201 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) SKIPSTAR ("EXTENDED"); 171 202 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) SKIPSTAR ("COSMIC RAY"); 203 if (source->mode & PM_SOURCE_MODE_DEFECT) SKIPSTAR ("DEFECT"); 172 204 173 205 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 174 206 continue; 175 207 } 208 209 // XXX make this user-configurable? 210 if (source->errMag > 0.01) continue; 176 211 177 212 // aperture residual for this source … … 185 220 } 186 221 187 mag->data.F32[Npsf] = source->psfMag; 188 apResid->data.F32[Npsf] = dap; 189 xPos->data.F32[Npsf] = model->params->data.F32[PM_PAR_XPOS]; 190 yPos->data.F32[Npsf] = model->params->data.F32[PM_PAR_YPOS]; 191 192 mask->data.PS_TYPE_VECTOR_MASK_DATA[Npsf] = 0; 193 194 dMag->data.F32[Npsf] = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0]; 195 196 psVectorExtend (mag, 100, 1); 197 psVectorExtend (mask, 100, 1); 198 psVectorExtend (xPos, 100, 1); 199 psVectorExtend (yPos, 100, 1); 200 psVectorExtend (dMag, 100, 1); 201 psVectorExtend (apResid, 100, 1); 222 # ifdef DEBUG 223 fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n", 224 source->peak->xf, source->peak->yf, 225 source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS], 226 source->psfMag, source->apMag, source->errMag, 227 source->modelPSF->params->data.F32[PM_PAR_I0], 228 source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY], source->modelPSF->params->data.F32[PM_PAR_SYY], 229 source->modelPSF->params->data.F32[PM_PAR_7]); 230 # endif 231 if (!isfinite(source->psfMag)) psAbort ("nan in psfMag"); 232 if (!isfinite(source->errMag)) psAbort ("nan in errMag"); 233 if (!isfinite(source->apMag)) psAbort ("nan in apMag"); 234 if (!isfinite(model->params->data.F32[PM_PAR_XPOS])) psAbort ("nan in xPos"); 235 if (!isfinite(model->params->data.F32[PM_PAR_YPOS])) psAbort ("nan in yPos"); 236 237 psVectorAppend (mag, source->psfMag); 238 psVectorAppend (dMag,source->errMag); 239 psVectorAppend (apResid, dap); 240 psVectorAppend (xPos, model->params->data.F32[PM_PAR_XPOS]); 241 psVectorAppend (yPos, model->params->data.F32[PM_PAR_YPOS]); 202 242 Npsf ++; 203 243 } … … 205 245 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "measure aperture residuals for %d objects (%d skipped, %d failed, %ld invalid)\n", 206 246 Npsf, Nskip, Nfail, sources->n - Npsf - Nskip - Nfail); 247 248 # ifdef DEBUG 249 fclose (f); 250 # endif 207 251 208 252 // XXX choose a better value here? … … 212 256 } 213 257 214 // XXX deprecating the old code which allowed the ApResid to be fitted as a function of flux and r^2/flux 215 // XXX is this asymmetric clipping still needed? this analysis should come after neighbors are subtracted... 216 // 3hi/1lo sigma clipping on the rflux vs metric fit 217 // systematic error information 218 float errorScale = 0.0; 219 float errorFloor = 0.0; 220 258 // this is a bit tricky, because we have two cases (MAP vs POLY), and they have a different 259 // definition for 'order' (order_MAP = order_POLY + 1). in addition, we have a 260 // user-specified MAX order, which we should respect, regardless of the mode 261 262 // set the max order (0 = constant) which the number of psf stars can support: 263 // rule of thumb: require 3 stars per 'cell' (order+1)^2 264 int MaxOrderForStars = 0; 265 if (Npsf >= 12) MaxOrderForStars = 1; // 4 cells 266 if (Npsf >= 27) MaxOrderForStars = 2; // 9 cells 267 if (Npsf >= 48) MaxOrderForStars = 3; // 16 cells 268 if (Npsf > 75) MaxOrderForStars = 4; // 25 cells 269 270 pmTrend2DMode mode = PM_TREND_MAP; 271 if (mode == PM_TREND_MAP) { 272 MaxOrderForStars ++; 273 } 274 APTREND_ORDER_MAX = PS_MIN (APTREND_ORDER_MAX, MaxOrderForStars); 275 276 psFree (psf->ApTrend); 277 psf->ApTrend = NULL; 221 278 float errorFloorMin = FLT_MAX; 222 int entryMin = -1; 223 224 // Fit out the dap vs mag trend, iterate over spatial scale until error Floor increases. 225 // Stop if Npsf / (Nx * Ny) < 3 279 280 // as we loop over orders, we need to refer to the initial selection, but we modify the 281 // option values to match the current guess: save the max values here: 282 int NX = readout->image->numCols; 283 int NY = readout->image->numRows; 226 284 for (int i = 1; i <= APTREND_ORDER_MAX; i++) { 227 228 if (!psphotApResidTrend (readout, psf, Npsf, i, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag)) { 229 break; 230 } 231 232 // store the resulting errorFloor values and the scales, redo the best 285 286 int Nx, Ny; 287 if (NX > NY) { 288 Nx = i; 289 Ny = PS_MAX (1, (int)(i * (NY / (float)(NX)) + 0.5)); 290 } else { 291 Ny = i; 292 Nx = PS_MAX (1, (int)(i * (NX / (float)(NY)) + 0.5)); 293 } 294 295 float errorFloor; 296 pmTrend2D *apTrend = psphotApResidTrend (&errorFloor, readout, Nx, Ny, xPos, yPos, apResid, dMag); 297 if (!apTrend) { 298 continue; 299 } 300 301 // apply ApTrend results 302 // float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 303 // float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 304 // float ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 305 // if (!isfinite(ApResid)) psAbort("nan apresid @ center"); 306 307 // store the minimum errorFloor and best ApTrend to keep 233 308 if (errorFloor < errorFloorMin) { 234 309 errorFloorMin = errorFloor; 235 entryMin = i; 310 psFree (psf->ApTrend); 311 psf->ApTrend = psMemIncrRefCounter(apTrend); 236 312 } 237 } 238 if (entryMin == -1) { 313 psFree (apTrend); 314 } 315 if (psf->ApTrend == NULL) { 239 316 psWarning("Failed to find a valid aperture residual value"); 240 317 goto escape; 241 318 } 242 319 243 // XXX catch error condition 244 psphotApResidTrend (readout, psf, Npsf, entryMin, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag); 320 // apply ApTrend results 321 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 322 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 323 324 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 325 psf->dApResid = errorFloorMin; 326 psf->nApResid = Npsf; 327 328 // save results for later output 329 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", psf->ApResid); 330 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid); 331 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid); 332 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss); 333 334 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid); 335 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid")); 336 337 psFree (xPos); 338 psFree (yPos); 339 psFree (apResid); 340 psFree (mag); 341 psFree (dMag); 342 343 psphotVisualPlotApResid (sources, psf->ApResid, psf->dApResid); 344 345 return true; 346 347 escape: 348 // save nan values since these were not calculated 349 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 350 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 351 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 352 psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN); 353 354 psFree (xPos); 355 psFree (yPos); 356 psFree (apResid); 357 psFree (mag); 358 psFree (dMag); 359 return true; 360 // this is a quality error, not a programming error 361 } 362 363 pmTrend2D *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) { 364 365 // the mask marks the values not used to calculate the ApTrend 366 psVector *mask = psVectorAlloc(xPos->n, PS_TYPE_VECTOR_MASK); 367 psVectorInit (mask, 0); 368 369 // XXX allow user to set this optionally? 370 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 371 372 // measure Trend2D for the current spatial scale 373 pmTrend2D *apTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats); 374 375 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate: 376 // XXX use this or not? probably not, since this is the point of the systematic error analysis 377 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32); 378 for (int i = 0; i < dMag->n; i++) { 379 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.005); 380 } 381 382 // XXX test for errors here 383 if (!pmTrend2DFit (apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) { 384 psWarning("Failed to fit trend for %d x %d map", Nx, Ny); 385 psFree (apTrend); 386 return NULL; 387 } 388 if (apTrend->mode == PM_TREND_MAP) { 389 // p_psImagePrint (2, apTrend->map->map, "ApTrend Before"); // XXX TEST: 390 psImageMapRepair (apTrend->map->map); 391 // p_psImagePrint (2, apTrend->map->map, "ApTrend After"); // XXX TEST: 392 } 245 393 246 394 // construct the fitted values and the residuals 247 psVector *apResidFit = pmTrend2DEvalVector ( psf->ApTrend, mask, 0xff, xPos, yPos);395 psVector *apResidFit = pmTrend2DEvalVector (apTrend, mask, 0xff, xPos, yPos); 248 396 psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit); 249 psVector *dMagSys = (psVector *) psBinaryOp (NULL, (void *) dMag, "*", (void *) psScalarAlloc(errorScale, PS_TYPE_F32)); 250 251 if (psTraceGetLevel("psphot") >= 2) { 252 FILE *dumpFile = fopen ("apresid.dat", "w"); 397 398 // measure systematic error 399 *apResidSysErr = psVectorSystematicError (apResidRes, dMag, 0.10); 400 if (!isfinite(*apResidSysErr)) { 401 psWarning("Failed to find systematic error for %d x %d map", Nx, Ny); 402 psFree (apTrend); 403 return NULL; 404 } 405 406 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid\n", Nx, Ny); 407 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *apResidSysErr); 408 409 if (psTraceGetLevel("psphot") >= 4) { 410 char filename[64]; 411 snprintf (filename, 64, "apresid.%dx%d.dat", Nx, Ny); 412 FILE *dumpFile = fopen (filename, "w"); 253 413 for (int i = 0; i < xPos->n; i++) { 254 fprintf (dumpFile, "%f %f %f %f %f%f %f %x\n",414 fprintf (dumpFile, "%f %f %f %f %f %f %x\n", 255 415 xPos->data.F32[i], yPos->data.F32[i], 256 mag->data.F32[i], dMag->data.F32[i], dMagSys->data.F32[i],416 dMag->data.F32[i], hypot(dMag->data.F32[i], *apResidSysErr), 257 417 apResid->data.F32[i], apResidRes->data.F32[i], 258 418 mask->data.PS_TYPE_VECTOR_MASK_DATA[i]); … … 261 421 } 262 422 263 // apply ApTrend results264 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5;265 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5;266 267 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center268 psf->dApResid = errorFloor;269 psf->nApResid = Npsf;270 271 // save results for later output272 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", 0.0);273 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", 0.0);274 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", psf->ApResid);275 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid);276 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss);277 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid);278 279 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid);280 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid"));281 282 psFree (mag);283 423 psFree (mask); 284 psFree (xPos);285 psFree (yPos);286 287 psFree (apResid);288 psFree (apResidFit);289 psFree (apResidRes);290 291 psFree (dMagSys);292 psFree (dMag);293 294 psphotVisualPlotApResid (sources);295 296 return true;297 298 escape:299 // save nan values since these were not calculated300 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", NAN);301 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", NAN);302 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN);303 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);304 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);305 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);306 307 psFree (mag);308 psFree (mask);309 psFree (xPos);310 psFree (yPos);311 psFree (apResid);312 psFree (dMag);313 return false;314 }315 316 /*317 (aprMag' - fitMag) = rflux*skyBias + ApTrend(x,y)318 (aprMag - rflux*skyBias) - fitMag = ApTrend(x,y)319 (aprMag - rflux*skyBias) = fitMag + ApTrend(x,y)320 */321 322 // XXX this still sucks... need a better way to estimate the error floor...323 bool psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup) {324 325 psStats *statsS = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);326 psStats *statsM = psStatsAlloc (PS_STAT_SAMPLE_MEAN);327 328 // measure the trend in bins with 10 values each; if < 10 total, use them all329 int nBin = PS_MAX (dMag->n / nGroup, 1);330 331 // output vectors for ApResid trend332 psVector *dSo = psVectorAlloc (nBin, PS_TYPE_F32);333 psVector *dMo = psVectorAlloc (nBin, PS_TYPE_F32);334 psVector *dRo = psVectorAlloc (nBin, PS_TYPE_F32);335 336 // use dMag to group the dMag and dap vectors337 psVector *index = psVectorSortIndex (NULL, dMag);338 339 // subset vectors for dMag and dap values within the given range340 psVector *dMSubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);341 psVector *dASubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);342 psVector *mkSubset = psVectorAllocEmpty (nGroup, PS_TYPE_VECTOR_MASK);343 344 int n = 0;345 for (int i = 0; i < dMo->n; i++) {346 int j;347 for (j = 0; (j < nGroup) && (n < dMag->n); j++, n++) {348 int N = index->data.U32[n];349 dMSubset->data.F32[j] = dMag->data.F32[N];350 dASubset->data.F32[j] = dap->data.F32[N];351 mkSubset->data.PS_TYPE_VECTOR_MASK_DATA[j] = mask->data.PS_TYPE_VECTOR_MASK_DATA[N];352 }353 dMSubset->n = j;354 dASubset->n = j;355 mkSubset->n = j;356 357 psStatsInit (statsS);358 psStatsInit (statsM);359 360 if (j > 2) {361 if (!psVectorStats (statsS, dASubset, NULL, mkSubset, 0xff)) {362 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");363 return false;364 }365 if (!psVectorStats (statsM, dMSubset, NULL, mkSubset, 0xff)) {366 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");367 return false;368 }369 dSo->data.F32[i] = statsS->robustStdev;370 dMo->data.F32[i] = statsM->sampleMean;371 dRo->data.F32[i] = statsS->robustStdev / statsM->sampleMean;372 } else {373 dSo->data.F32[i] = NAN;374 dMo->data.F32[i] = NAN;375 dRo->data.F32[i] = NAN;376 }377 }378 psFree (dMSubset);379 psFree (dASubset);380 psFree (mkSubset);381 382 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);383 if (!psVectorStats (stats, dRo, NULL, NULL, 0)) {384 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");385 return false;386 }387 388 *errorScale = stats->sampleMedian;389 for (int i = 0; i < dSo->n; i++) {390 *errorFloor = dSo->data.F32[i];391 if (fabs(*errorFloor) <= FLT_EPSILON) continue;392 if (isfinite(*errorFloor)) break;393 }394 395 psFree (stats);396 psFree (index);397 398 psFree (dRo);399 psFree (dMo);400 psFree (dSo);401 402 psFree (statsS);403 psFree (statsM);404 405 return true;406 }407 408 bool psphotApResidTrend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) {409 410 int Nx, Ny;411 412 if (readout->image->numCols > readout->image->numRows) {413 Nx = scale;414 float AR = readout->image->numRows / (float) readout->image->numCols;415 Ny = (int) (Nx * AR + 0.5);416 Ny = PS_MAX (1, Ny);417 } else {418 Ny = scale;419 float AR = readout->image->numRows / (float) readout->image->numCols;420 Nx = (int) (Ny * AR + 0.5);421 Nx = PS_MAX (1, Nx);422 }423 424 // require at least 10 stars per spatial bin425 if (Npsf < 10*Nx*Ny) {426 return false;427 }428 429 // the mask marks the values not used to calculate the ApTrend430 psVectorInit (mask, 0);431 432 // XXX stats structure for use by ApTrend : make parameters user setable433 psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);434 stats->min = 2.0;435 stats->max = 3.0;436 437 // measure Trend2D for the current spatial scale438 psFree (psf->ApTrend);439 psf->ApTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats);440 441 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate:442 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32);443 for (int i = 0; i < dMag->n; i++) {444 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.01);445 }446 447 // XXX test for errors here448 pmTrend2DFit (psf->ApTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft);449 450 // construct the fitted values and the residuals451 psVector *apResidFit = pmTrend2DEvalVector (psf->ApTrend, mask, 0xff, xPos, yPos);452 psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit);453 454 // measure systematic errorFloor & systematic / photon scale factor455 // XXX this is a bit arbitrary, but it forces ~3 stars from the bright bin per spatial bin456 int nGroup = PS_MAX (3*Nx*Ny, 10);457 psphotMagErrorScale (errorScale, errorFloor, dMag, apResidRes, mask, nGroup);458 459 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid (%d stars per bin)\n", Nx, Ny, nGroup);460 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic error / photon error: %f\n", *errorScale);461 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *errorFloor);462 463 424 psFree (stats); 464 425 psFree (dMagSoft); … … 466 427 psFree (apResidRes); 467 428 468 return true;429 return apTrend; 469 430 } 470 431 … … 480 441 pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[2],S32); 481 442 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA); 443 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); 482 444 483 445 for (int i = 0; i < sources->n; i++) { … … 490 452 if (source->mode & PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR"); 491 453 492 if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) { 493 Nskip ++; 494 psTrace ("psphot", 3, "skip : bad source mag"); 495 continue; 454 // replace object in image 455 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 456 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 496 457 } 497 458 498 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 499 Nfail ++; 500 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 501 continue; 502 } 503 source->mode |= PM_SOURCE_MODE_AP_MAGS; 459 // clear the mask bit and set the circular mask pixels 460 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 461 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal); 462 463 bool status = pmSourceMagnitudes (source, psf, photMode, maskVal); 464 465 // clear the mask bit 466 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 467 468 // re-subtract the object, leave local sky 469 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 470 471 if (!status) { 472 Nskip ++; 473 psTrace ("psphot", 3, "skip : bad source mag"); 474 continue; 475 } 476 477 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 478 Nfail ++; 479 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 480 continue; 481 } 482 source->mode |= PM_SOURCE_MODE_AP_MAGS; 504 483 } 505 484 506 485 // change the value of a scalar on the array (wrap this and put it in psArray.h) 507 scalar = job->args->data[ 4];486 scalar = job->args->data[5]; 508 487 scalar->data.S32 = Nskip; 509 488 510 scalar = job->args->data[ 5];489 scalar = job->args->data[6]; 511 490 scalar->data.S32 = Nfail; 512 491 513 492 return true; 514 493 } 515 516 # if (0)517 bool psphotApResidMags_Unthreaded (int *nskip, int *nfail, psArray *sources, pmPSF *psf, pmSourcePhotometryMode photMode, psImageMaskType maskVal) {518 519 int Nskip = 0;520 int Nfail = 0;521 522 for (int i = 0; i < sources->n; i++) {523 pmSource *source = (pmSource *) sources->data[i];524 525 if (source->type != PM_SOURCE_TYPE_STAR) SKIPSTAR ("NOT STAR");526 if (source->mode & PM_SOURCE_MODE_SATSTAR) SKIPSTAR ("SATSTAR");527 if (source->mode & PM_SOURCE_MODE_BLEND) SKIPSTAR ("BLEND");528 if (source->mode & PM_SOURCE_MODE_FAIL) SKIPSTAR ("FAIL STAR");529 if (source->mode & PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR");530 531 if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) {532 Nskip ++;533 psTrace ("psphot", 3, "skip : bad source mag");534 continue;535 }536 537 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {538 Nfail ++;539 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag);540 continue;541 }542 }543 544 // change the value of a scalar on the array (wrap this and put it in psArray.h)545 *nskip = Nskip;546 *nfail = Nfail;547 548 return true;549 }550 # endif
Note:
See TracChangeset
for help on using the changeset viewer.
