Changeset 25616
- Timestamp:
- Sep 27, 2009, 11:15:32 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/20090715/psphot/src/psphotApResid.c
r25536 r25616 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 FILE *f = fopen ("apresid.dat", "w"); 148 psAssert (f, "failed open"); 149 160 150 for (int i = 0; i < sources->n; i++) { 161 151 source = sources->data[i]; … … 170 160 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) SKIPSTAR ("EXTENDED"); 171 161 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) SKIPSTAR ("COSMIC RAY"); 162 if (source->mode & PM_SOURCE_MODE_DEFECT) SKIPSTAR ("DEFECT"); 172 163 173 164 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 174 165 continue; 175 166 } 167 168 // XXX make this user-configurable? 169 if (source->errMag > 0.01) continue; 176 170 177 171 // aperture residual for this source … … 185 179 } 186 180 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 // XXX don't I have errMag at this point?? 195 dMag->data.F32[Npsf] = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0]; 196 197 psVectorExtend (mag, 100, 1); 198 psVectorExtend (mask, 100, 1); 199 psVectorExtend (xPos, 100, 1); 200 psVectorExtend (yPos, 100, 1); 201 psVectorExtend (dMag, 100, 1); 202 psVectorExtend (apResid, 100, 1); 181 fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n", 182 source->peak->xf, source->peak->yf, 183 source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS], 184 source->psfMag, source->apMag, source->errMag, 185 source->modelPSF->params->data.F32[PM_PAR_I0], 186 source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY], source->modelPSF->params->data.F32[PM_PAR_SYY], 187 source->modelPSF->params->data.F32[PM_PAR_7]); 188 189 psVectorAppend (mag, source->psfMag); 190 psVectorAppend (dMag,source->errMag); 191 psVectorAppend (apResid, dap); 192 psVectorAppend (xPos, model->params->data.F32[PM_PAR_XPOS]); 193 psVectorAppend (yPos, model->params->data.F32[PM_PAR_YPOS]); 203 194 Npsf ++; 204 195 } … … 206 197 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "measure aperture residuals for %d objects (%d skipped, %d failed, %ld invalid)\n", 207 198 Npsf, Nskip, Nfail, sources->n - Npsf - Nskip - Nfail); 199 200 fclose (f); 208 201 209 202 // XXX choose a better value here? … … 213 206 } 214 207 215 // XXX deprecating the old code which allowed the ApResid to be fitted as a function of flux and r^2/flux216 // XXX is this asymmetric clipping still needed? this analysis should come after neighbors are subtracted...217 // 3hi/1lo sigma clipping on the rflux vs metric fit218 // systematic error information219 float errorScale = 0.0; 220 float errorFloor = 0.0;221 208 // XXX set the min number of needed source more carefully 209 if ((Npsf < 15) && (APTREND_ORDER_MAX >= 4)) APTREND_ORDER_MAX = 3; 210 if ((Npsf < 11) && (APTREND_ORDER_MAX >= 3)) APTREND_ORDER_MAX = 2; 211 if ((Npsf < 8) && (APTREND_ORDER_MAX >= 2)) APTREND_ORDER_MAX = 1; 212 213 psFree (psf->ApTrend); 214 psf->ApTrend = NULL; 222 215 float errorFloorMin = FLT_MAX; 223 int entryMin = -1; 224 225 // Fit out the dap vs mag trend, iterate over spatial scale until error Floor increases. 226 // Stop if Npsf / (Nx * Ny) < 3 216 217 // as we loop over orders, we need to refer to the initial selection, but we modify the 218 // option values to match the current guess: save the max values here: 219 int NX = readout->image->numCols; 220 int NY = readout->image->numRows; 227 221 for (int i = 1; i <= APTREND_ORDER_MAX; i++) { 228 229 if (!psphotApResidTrend (readout, psf, Npsf, i, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag)) { 230 break; 231 } 232 233 // store the resulting errorFloor values and the scales, redo the best 222 223 int Nx, Ny; 224 if (NX > NY) { 225 Nx = i; 226 Ny = PS_MAX (1, (int)(i * (NY / (float)(NX)) + 0.5)); 227 } else { 228 Ny = i; 229 Nx = PS_MAX (1, (int)(i * (NX / (float)(NY)) + 0.5)); 230 } 231 232 float errorFloor; 233 pmTrend2D *apTrend = psphotApResidTrend (&errorFloor, readout, Nx, Ny, xPos, yPos, apResid, dMag); 234 if (!apTrend) { 235 continue; 236 } 237 238 // store the minimum errorFloor and best ApTrend to keep 234 239 if (errorFloor < errorFloorMin) { 235 240 errorFloorMin = errorFloor; 236 entryMin = i; 241 psFree (psf->ApTrend); 242 psf->ApTrend = psMemIncrRefCounter(apTrend); 237 243 } 238 } 239 if (entryMin == -1) { 244 psFree (apTrend); 245 } 246 if (psf->ApTrend == NULL) { 240 247 psWarning("Failed to find a valid aperture residual value"); 241 248 goto escape; 242 249 } 243 250 244 // XXX catch error condition 245 psphotApResidTrend (readout, psf, Npsf, entryMin, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag); 251 // apply ApTrend results 252 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 253 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 254 255 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 256 psf->dApResid = errorFloorMin; 257 psf->nApResid = Npsf; 258 259 // save results for later output 260 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", psf->ApResid); 261 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid); 262 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid); 263 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss); 264 265 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid); 266 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid")); 267 268 psFree (xPos); 269 psFree (yPos); 270 psFree (apResid); 271 psFree (mag); 272 psFree (dMag); 273 274 psphotVisualPlotApResid (sources, psf->ApResid, psf->dApResid); 275 276 return true; 277 278 escape: 279 // save nan values since these were not calculated 280 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 281 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 282 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 283 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN); 284 285 psFree (xPos); 286 psFree (yPos); 287 psFree (apResid); 288 psFree (mag); 289 psFree (dMag); 290 return false; 291 } 292 293 pmTrend2D *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) { 294 295 // the mask marks the values not used to calculate the ApTrend 296 psVector *mask = psVectorAlloc(xPos->n, PS_TYPE_VECTOR_MASK); 297 psVectorInit (mask, 0); 298 299 // XXX allow user to set this optionally? 300 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 301 302 // measure Trend2D for the current spatial scale 303 pmTrend2D *apTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats); 304 305 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate: 306 // XXX use this or not? probably not, since this is the point of the systematic error analysis 307 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32); 308 for (int i = 0; i < dMag->n; i++) { 309 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.005); 310 } 311 312 // XXX test for errors here 313 if (!pmTrend2DFit (apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) { 314 psWarning("Failed to fit trend for %d x %d map", Nx, Ny); 315 psFree (apTrend); 316 return NULL; 317 } 246 318 247 319 // construct the fitted values and the residuals 248 psVector *apResidFit = pmTrend2DEvalVector ( psf->ApTrend, mask, 0xff, xPos, yPos);320 psVector *apResidFit = pmTrend2DEvalVector (apTrend, mask, 0xff, xPos, yPos); 249 321 psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit); 250 psVector *dMagSys = (psVector *) psBinaryOp (NULL, (void *) dMag, "*", (void *) psScalarAlloc(errorScale, PS_TYPE_F32)); 251 252 if (psTraceGetLevel("psphot") >= 2) { 253 FILE *dumpFile = fopen ("apresid.dat", "w"); 322 323 // measure systematic error 324 *apResidSysErr = psVectorSystematicError (apResidRes, dMag, 0.10); 325 if (!isfinite(*apResidSysErr)) { 326 psWarning("Failed to find systematic error for %d x %d map", Nx, Ny); 327 psFree (apTrend); 328 return NULL; 329 } 330 331 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid\n", Nx, Ny); 332 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *apResidSysErr); 333 334 if (psTraceGetLevel("psphot") >= 4) { 335 char filename[64]; 336 snprintf (filename, 64, "apresid.%dx%d.dat", Nx, Ny); 337 FILE *dumpFile = fopen (filename, "w"); 254 338 for (int i = 0; i < xPos->n; i++) { 255 fprintf (dumpFile, "%f %f %f %f %f%f %f %x\n",339 fprintf (dumpFile, "%f %f %f %f %f %f %x\n", 256 340 xPos->data.F32[i], yPos->data.F32[i], 257 mag->data.F32[i], dMag->data.F32[i], dMagSys->data.F32[i],341 dMag->data.F32[i], hypot(dMag->data.F32[i], *apResidSysErr), 258 342 apResid->data.F32[i], apResidRes->data.F32[i], 259 343 mask->data.PS_TYPE_VECTOR_MASK_DATA[i]); … … 262 346 } 263 347 264 // apply ApTrend results265 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5;266 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5;267 268 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center269 psf->dApResid = errorFloor;270 psf->nApResid = Npsf;271 272 // save results for later output273 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", 0.0);274 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", 0.0);275 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", psf->ApResid);276 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid);277 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss);278 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid);279 280 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid);281 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid"));282 283 psFree (mag);284 348 psFree (mask); 285 psFree (xPos);286 psFree (yPos);287 288 psFree (apResid);289 psFree (apResidFit);290 psFree (apResidRes);291 292 psFree (dMagSys);293 psFree (dMag);294 295 psphotVisualPlotApResid (sources);296 297 return true;298 299 escape:300 // save nan values since these were not calculated301 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", NAN);302 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", NAN);303 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN);304 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);305 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);306 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);307 308 psFree (mag);309 psFree (mask);310 psFree (xPos);311 psFree (yPos);312 psFree (apResid);313 psFree (dMag);314 return false;315 }316 317 /*318 (aprMag' - fitMag) = rflux*skyBias + ApTrend(x,y)319 (aprMag - rflux*skyBias) - fitMag = ApTrend(x,y)320 (aprMag - rflux*skyBias) = fitMag + ApTrend(x,y)321 */322 323 // XXX this still sucks... need a better way to estimate the error floor...324 bool psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup) {325 326 psStats *statsS = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);327 psStats *statsM = psStatsAlloc (PS_STAT_SAMPLE_MEAN);328 329 // measure the trend in bins with 10 values each; if < 10 total, use them all330 int nBin = PS_MAX (dMag->n / nGroup, 1);331 332 // output vectors for ApResid trend333 psVector *dSo = psVectorAlloc (nBin, PS_TYPE_F32);334 psVector *dMo = psVectorAlloc (nBin, PS_TYPE_F32);335 psVector *dRo = psVectorAlloc (nBin, PS_TYPE_F32);336 337 // use dMag to group the dMag and dap vectors338 psVector *index = psVectorSortIndex (NULL, dMag);339 340 // subset vectors for dMag and dap values within the given range341 psVector *dMSubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);342 psVector *dASubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);343 psVector *mkSubset = psVectorAllocEmpty (nGroup, PS_TYPE_VECTOR_MASK);344 345 int n = 0;346 for (int i = 0; i < dMo->n; i++) {347 int j;348 for (j = 0; (j < nGroup) && (n < dMag->n); j++, n++) {349 int N = index->data.U32[n];350 dMSubset->data.F32[j] = dMag->data.F32[N];351 dASubset->data.F32[j] = dap->data.F32[N];352 mkSubset->data.PS_TYPE_VECTOR_MASK_DATA[j] = mask->data.PS_TYPE_VECTOR_MASK_DATA[N];353 }354 dMSubset->n = j;355 dASubset->n = j;356 mkSubset->n = j;357 358 psStatsInit (statsS);359 psStatsInit (statsM);360 361 if (j > 2) {362 if (!psVectorStats (statsS, dASubset, NULL, mkSubset, 0xff)) {363 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");364 return false;365 }366 if (!psVectorStats (statsM, dMSubset, NULL, mkSubset, 0xff)) {367 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");368 return false;369 }370 dSo->data.F32[i] = statsS->robustStdev;371 dMo->data.F32[i] = statsM->sampleMean;372 dRo->data.F32[i] = statsS->robustStdev / statsM->sampleMean;373 } else {374 dSo->data.F32[i] = NAN;375 dMo->data.F32[i] = NAN;376 dRo->data.F32[i] = NAN;377 }378 }379 psFree (dMSubset);380 psFree (dASubset);381 psFree (mkSubset);382 383 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);384 if (!psVectorStats (stats, dRo, NULL, NULL, 0)) {385 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");386 return false;387 }388 389 *errorScale = stats->sampleMedian;390 for (int i = 0; i < dSo->n; i++) {391 *errorFloor = dSo->data.F32[i];392 if (fabs(*errorFloor) <= FLT_EPSILON) continue;393 if (isfinite(*errorFloor)) break;394 }395 396 psFree (stats);397 psFree (index);398 399 psFree (dRo);400 psFree (dMo);401 psFree (dSo);402 403 psFree (statsS);404 psFree (statsM);405 406 return true;407 }408 409 bool psphotApResidTrend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) {410 411 int Nx, Ny;412 413 // XXX use the psf trend scale?414 if (readout->image->numCols > readout->image->numRows) {415 Nx = scale;416 float AR = readout->image->numRows / (float) readout->image->numCols;417 Ny = (int) (Nx * AR + 0.5);418 Ny = PS_MAX (1, Ny);419 } else {420 Ny = scale;421 float AR = readout->image->numRows / (float) readout->image->numCols;422 Nx = (int) (Ny * AR + 0.5);423 Nx = PS_MAX (1, Nx);424 }425 426 // the mask marks the values not used to calculate the ApTrend427 psVectorInit (mask, 0);428 429 // XXX stats structure for use by ApTrend : make parameters user setable430 // XXX another stat?431 psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);432 stats->min = 2.0;433 stats->max = 3.0;434 435 // measure Trend2D for the current spatial scale436 psFree (psf->ApTrend);437 psf->ApTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats);438 439 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate:440 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32);441 for (int i = 0; i < dMag->n; i++) {442 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.01);443 }444 445 // XXX test for errors here446 pmTrend2DFit (psf->ApTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft);447 448 // construct the fitted values and the residuals449 psVector *apResidFit = pmTrend2DEvalVector (psf->ApTrend, mask, 0xff, xPos, yPos);450 psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit);451 452 // measure systematic errorFloor & systematic / photon scale factor453 // XXX this is a bit arbitrary, but it forces ~3 stars from the bright bin per spatial bin454 int nGroup = PS_MAX (3*Nx*Ny, 10);455 psphotMagErrorScale (errorScale, errorFloor, dMag, apResidRes, mask, nGroup);456 457 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid (%d stars per bin)\n", Nx, Ny, nGroup);458 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic error / photon error: %f\n", *errorScale);459 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *errorFloor);460 461 349 psFree (stats); 462 350 psFree (dMagSoft); … … 464 352 psFree (apResidRes); 465 353 466 return true;354 return apTrend; 467 355 } 468 356 … … 478 366 pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[2],S32); 479 367 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA); 368 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); 480 369 481 370 for (int i = 0; i < sources->n; i++) { … … 488 377 if (source->mode & PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR"); 489 378 490 if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) { 491 Nskip ++; 492 psTrace ("psphot", 3, "skip : bad source mag"); 493 continue; 379 // replace object in image 380 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 381 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 494 382 } 495 383 496 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 497 Nfail ++; 498 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 499 continue; 500 } 501 source->mode |= PM_SOURCE_MODE_AP_MAGS; 384 // clear the mask bit and set the circular mask pixels 385 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 386 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal); 387 388 bool status = pmSourceMagnitudes (source, psf, photMode, maskVal); 389 390 // clear the mask bit 391 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 392 393 // re-subtract the object, leave local sky 394 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 395 396 if (!status) { 397 Nskip ++; 398 psTrace ("psphot", 3, "skip : bad source mag"); 399 continue; 400 } 401 402 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 403 Nfail ++; 404 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 405 continue; 406 } 407 source->mode |= PM_SOURCE_MODE_AP_MAGS; 502 408 } 503 409 504 410 // change the value of a scalar on the array (wrap this and put it in psArray.h) 505 scalar = job->args->data[ 4];411 scalar = job->args->data[5]; 506 412 scalar->data.S32 = Nskip; 507 413 508 scalar = job->args->data[ 5];414 scalar = job->args->data[6]; 509 415 scalar->data.S32 = Nfail; 510 416 511 417 return true; 512 418 } 513 514 bool psphotApResidTrend_old (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) {515 516 int Nx, Ny;517 518 if (readout->image->numCols > readout->image->numRows) {519 Nx = scale;520 float AR = readout->image->numRows / (float) readout->image->numCols;521 Ny = (int) (Nx * AR + 0.5);522 Ny = PS_MAX (1, Ny);523 } else {524 Ny = scale;525 float AR = readout->image->numRows / (float) readout->image->numCols;526 Nx = (int) (Ny * AR + 0.5);527 Nx = PS_MAX (1, Nx);528 }529 530 // require at least 10 stars per spatial bin531 if (Npsf < 10*Nx*Ny) {532 return false;533 }534 535 // the mask marks the values not used to calculate the ApTrend536 psVectorInit (mask, 0);537 538 // XXX stats structure for use by ApTrend : make parameters user setable539 psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);540 stats->min = 2.0;541 stats->max = 3.0;542 543 // measure Trend2D for the current spatial scale544 psFree (psf->ApTrend);545 psf->ApTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats);546 547 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate:548 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32);549 for (int i = 0; i < dMag->n; i++) {550 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.01);551 }552 553 // XXX test for errors here554 pmTrend2DFit (psf->ApTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft);555 556 // construct the fitted values and the residuals557 psVector *apResidFit = pmTrend2DEvalVector (psf->ApTrend, mask, 0xff, xPos, yPos);558 psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit);559 560 // measure systematic errorFloor & systematic / photon scale factor561 // XXX this is a bit arbitrary, but it forces ~3 stars from the bright bin per spatial bin562 int nGroup = PS_MAX (3*Nx*Ny, 10);563 psphotMagErrorScale (errorScale, errorFloor, dMag, apResidRes, mask, nGroup);564 565 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid (%d stars per bin)\n", Nx, Ny, nGroup);566 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic error / photon error: %f\n", *errorScale);567 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *errorFloor);568 569 psFree (stats);570 psFree (dMagSoft);571 psFree (apResidFit);572 psFree (apResidRes);573 574 return true;575 }576
Note:
See TracChangeset
for help on using the changeset viewer.
