Changeset 25755 for trunk/psphot/src/psphotApResid.c
- Timestamp:
- Oct 2, 2009, 3:12:47 PM (17 years ago)
- Location:
- trunk/psphot/src
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
psphotApResid.c (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src
- Property svn:ignore
-
old new 18 18 psphotVersionDefinitions.h 19 19 psphotMomentsStudy 20 psphotPetrosianStudy
-
- Property svn:ignore
-
trunk/psphot/src/psphotApResid.c
r24878 r25755 33 33 if (!measureAptrend) { 34 34 // 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 35 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 38 36 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 37 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 39 38 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);41 39 return true; 42 40 } … … 53 51 maskVal |= markVal; 54 52 55 // S/N limit to perform full non-linear fits 53 // clipping for extreme outliers 54 // XXX this is not currently defined in the recipe 56 55 float MAX_AP_OFFSET = psMetadataLookupF32 (&status, recipe, "MAX_AP_OFFSET"); 57 56 58 // this is the smallest radius allowed: need to at least extend growth curve down to this... 57 // options for how the photometry is calculated 58 // XXX are these sensible? 59 59 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH"); 60 60 bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); … … 100 100 PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32); 101 101 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 102 PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK); 102 103 103 104 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nskip … … 110 111 } 111 112 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 113 } 126 114 … … 138 126 } else { 139 127 psScalar *scalar = NULL; 140 scalar = job->args->data[ 4];128 scalar = job->args->data[5]; 141 129 Nskip += scalar->data.S32; 142 scalar = job->args->data[ 5];130 scalar = job->args->data[6]; 143 131 Nfail += scalar->data.S32; 144 132 } … … 150 138 151 139 // gather the stats to assess the aperture residuals 152 psVector *mask = psVectorAllocEmpty (300, PS_TYPE_VECTOR_MASK);153 140 psVector *mag = psVectorAllocEmpty (300, PS_TYPE_F32); 154 141 psVector *xPos = psVectorAllocEmpty (300, PS_TYPE_F32); … … 158 145 Npsf = 0; 159 146 147 # ifdef DEBUG 148 FILE *f = fopen ("apresid.dat", "w"); 149 psAssert (f, "failed open"); 150 # endif 151 160 152 for (int i = 0; i < sources->n; i++) { 161 153 source = sources->data[i]; … … 170 162 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) SKIPSTAR ("EXTENDED"); 171 163 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) SKIPSTAR ("COSMIC RAY"); 164 if (source->mode & PM_SOURCE_MODE_DEFECT) SKIPSTAR ("DEFECT"); 172 165 173 166 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 174 167 continue; 175 168 } 169 170 // XXX make this user-configurable? 171 if (source->errMag > 0.01) continue; 176 172 177 173 // aperture residual for this source … … 185 181 } 186 182 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); 183 # ifdef DEBUG 184 fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n", 185 source->peak->xf, source->peak->yf, 186 source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS], 187 source->psfMag, source->apMag, source->errMag, 188 source->modelPSF->params->data.F32[PM_PAR_I0], 189 source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY], source->modelPSF->params->data.F32[PM_PAR_SYY], 190 source->modelPSF->params->data.F32[PM_PAR_7]); 191 # endif 192 if (!isfinite(source->psfMag)) psAbort ("nan in psfMag"); 193 if (!isfinite(source->errMag)) psAbort ("nan in errMag"); 194 if (!isfinite(source->apMag)) psAbort ("nan in apMag"); 195 if (!isfinite(model->params->data.F32[PM_PAR_XPOS])) psAbort ("nan in xPos"); 196 if (!isfinite(model->params->data.F32[PM_PAR_YPOS])) psAbort ("nan in yPos"); 197 198 psVectorAppend (mag, source->psfMag); 199 psVectorAppend (dMag,source->errMag); 200 psVectorAppend (apResid, dap); 201 psVectorAppend (xPos, model->params->data.F32[PM_PAR_XPOS]); 202 psVectorAppend (yPos, model->params->data.F32[PM_PAR_YPOS]); 202 203 Npsf ++; 203 204 } … … 205 206 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "measure aperture residuals for %d objects (%d skipped, %d failed, %ld invalid)\n", 206 207 Npsf, Nskip, Nfail, sources->n - Npsf - Nskip - Nfail); 208 209 # ifdef DEBUG 210 fclose (f); 211 # endif 207 212 208 213 // XXX choose a better value here? … … 212 217 } 213 218 214 // XXX deprecating the old code which allowed the ApResid to be fitted as a function of flux and r^2/flux215 // 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 fit217 // systematic error information218 float errorScale = 0.0; 219 float errorFloor = 0.0;220 219 // XXX set the min number of needed source more carefully 220 if ((Npsf < 15) && (APTREND_ORDER_MAX >= 4)) APTREND_ORDER_MAX = 3; 221 if ((Npsf < 11) && (APTREND_ORDER_MAX >= 3)) APTREND_ORDER_MAX = 2; 222 if ((Npsf < 8) && (APTREND_ORDER_MAX >= 2)) APTREND_ORDER_MAX = 1; 223 224 psFree (psf->ApTrend); 225 psf->ApTrend = NULL; 221 226 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 227 228 // as we loop over orders, we need to refer to the initial selection, but we modify the 229 // option values to match the current guess: save the max values here: 230 int NX = readout->image->numCols; 231 int NY = readout->image->numRows; 226 232 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 233 234 int Nx, Ny; 235 if (NX > NY) { 236 Nx = i; 237 Ny = PS_MAX (1, (int)(i * (NY / (float)(NX)) + 0.5)); 238 } else { 239 Ny = i; 240 Nx = PS_MAX (1, (int)(i * (NX / (float)(NY)) + 0.5)); 241 } 242 243 float errorFloor; 244 pmTrend2D *apTrend = psphotApResidTrend (&errorFloor, readout, Nx, Ny, xPos, yPos, apResid, dMag); 245 if (!apTrend) { 246 continue; 247 } 248 249 // apply ApTrend results 250 // float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 251 // float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 252 // float ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 253 // if (!isfinite(ApResid)) psAbort("nan apresid @ center"); 254 255 // store the minimum errorFloor and best ApTrend to keep 233 256 if (errorFloor < errorFloorMin) { 234 257 errorFloorMin = errorFloor; 235 entryMin = i; 258 psFree (psf->ApTrend); 259 psf->ApTrend = psMemIncrRefCounter(apTrend); 236 260 } 237 } 238 if (entryMin == -1) { 261 psFree (apTrend); 262 } 263 if (psf->ApTrend == NULL) { 239 264 psWarning("Failed to find a valid aperture residual value"); 240 265 goto escape; 241 266 } 242 267 243 // XXX catch error condition 244 psphotApResidTrend (readout, psf, Npsf, entryMin, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag); 268 // apply ApTrend results 269 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 270 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 271 272 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 273 psf->dApResid = errorFloorMin; 274 psf->nApResid = Npsf; 275 276 // save results for later output 277 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", psf->ApResid); 278 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid); 279 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid); 280 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss); 281 282 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid); 283 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid")); 284 285 psFree (xPos); 286 psFree (yPos); 287 psFree (apResid); 288 psFree (mag); 289 psFree (dMag); 290 291 psphotVisualPlotApResid (sources, psf->ApResid, psf->dApResid); 292 293 return true; 294 295 escape: 296 // save nan values since these were not calculated 297 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 298 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 299 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 300 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN); 301 302 psFree (xPos); 303 psFree (yPos); 304 psFree (apResid); 305 psFree (mag); 306 psFree (dMag); 307 return false; 308 } 309 310 pmTrend2D *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) { 311 312 // the mask marks the values not used to calculate the ApTrend 313 psVector *mask = psVectorAlloc(xPos->n, PS_TYPE_VECTOR_MASK); 314 psVectorInit (mask, 0); 315 316 // XXX allow user to set this optionally? 317 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 318 319 // measure Trend2D for the current spatial scale 320 pmTrend2D *apTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats); 321 322 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate: 323 // XXX use this or not? probably not, since this is the point of the systematic error analysis 324 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32); 325 for (int i = 0; i < dMag->n; i++) { 326 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.005); 327 } 328 329 // XXX test for errors here 330 if (!pmTrend2DFit (apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) { 331 psWarning("Failed to fit trend for %d x %d map", Nx, Ny); 332 psFree (apTrend); 333 return NULL; 334 } 335 if (apTrend->mode == PM_TREND_MAP) { 336 // p_psImagePrint (2, apTrend->map->map, "ApTrend Before"); // XXX TEST: 337 psImageMapRepair (apTrend->map->map); 338 // p_psImagePrint (2, apTrend->map->map, "ApTrend After"); // XXX TEST: 339 } 245 340 246 341 // construct the fitted values and the residuals 247 psVector *apResidFit = pmTrend2DEvalVector ( psf->ApTrend, mask, 0xff, xPos, yPos);342 psVector *apResidFit = pmTrend2DEvalVector (apTrend, mask, 0xff, xPos, yPos); 248 343 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"); 344 345 // measure systematic error 346 *apResidSysErr = psVectorSystematicError (apResidRes, dMag, 0.10); 347 if (!isfinite(*apResidSysErr)) { 348 psWarning("Failed to find systematic error for %d x %d map", Nx, Ny); 349 psFree (apTrend); 350 return NULL; 351 } 352 353 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid\n", Nx, Ny); 354 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *apResidSysErr); 355 356 if (psTraceGetLevel("psphot") >= 4) { 357 char filename[64]; 358 snprintf (filename, 64, "apresid.%dx%d.dat", Nx, Ny); 359 FILE *dumpFile = fopen (filename, "w"); 253 360 for (int i = 0; i < xPos->n; i++) { 254 fprintf (dumpFile, "%f %f %f %f %f%f %f %x\n",361 fprintf (dumpFile, "%f %f %f %f %f %f %x\n", 255 362 xPos->data.F32[i], yPos->data.F32[i], 256 mag->data.F32[i], dMag->data.F32[i], dMagSys->data.F32[i],363 dMag->data.F32[i], hypot(dMag->data.F32[i], *apResidSysErr), 257 364 apResid->data.F32[i], apResidRes->data.F32[i], 258 365 mask->data.PS_TYPE_VECTOR_MASK_DATA[i]); … … 261 368 } 262 369 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 370 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 371 psFree (stats); 464 372 psFree (dMagSoft); … … 466 374 psFree (apResidRes); 467 375 468 return true;376 return apTrend; 469 377 } 470 378 … … 480 388 pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[2],S32); 481 389 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA); 390 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); 482 391 483 392 for (int i = 0; i < sources->n; i++) { … … 490 399 if (source->mode & PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR"); 491 400 492 if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) { 493 Nskip ++; 494 psTrace ("psphot", 3, "skip : bad source mag"); 495 continue; 401 // replace object in image 402 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 403 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 496 404 } 497 405 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; 406 // clear the mask bit and set the circular mask pixels 407 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 408 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal); 409 410 bool status = pmSourceMagnitudes (source, psf, photMode, maskVal); 411 412 // clear the mask bit 413 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 414 415 // re-subtract the object, leave local sky 416 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 417 418 if (!status) { 419 Nskip ++; 420 psTrace ("psphot", 3, "skip : bad source mag"); 421 continue; 422 } 423 424 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 425 Nfail ++; 426 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 427 continue; 428 } 429 source->mode |= PM_SOURCE_MODE_AP_MAGS; 504 430 } 505 431 506 432 // change the value of a scalar on the array (wrap this and put it in psArray.h) 507 scalar = job->args->data[ 4];433 scalar = job->args->data[5]; 508 434 scalar->data.S32 = Nskip; 509 435 510 scalar = job->args->data[ 5];436 scalar = job->args->data[6]; 511 437 scalar->data.S32 = Nfail; 512 438 513 439 return true; 514 440 } 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.
