Changeset 27838 for branches/tap_branches/psphot/src/psphotSourceStats.c
- Timestamp:
- May 3, 2010, 8:41:49 AM (16 years ago)
- Location:
- branches/tap_branches
- Files:
-
- 4 edited
-
. (modified) (1 prop)
-
psphot (modified) (1 prop)
-
psphot/src (modified) (1 prop)
-
psphot/src/psphotSourceStats.c (modified) (18 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/tap_branches
- Property svn:mergeinfo changed
-
branches/tap_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/tap_branches/psphot/src
- Property svn:ignore
-
old new 19 19 psphotMomentsStudy 20 20 psphotPetrosianStudy 21 psphotForced 22 psphotMakePSF 23 psphotStack
-
- Property svn:ignore
-
branches/tap_branches/psphot/src/psphotSourceStats.c
r25852 r27838 1 1 # include "psphotInternal.h" 2 2 3 bool psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources); 4 5 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections, bool setWindow) { 3 // convert detections to sources and measure their basic properties (moments, local sky, sky 4 // variance) Note: this function only generates sources for the new peaks (peak->assigned). 5 // The new sources are added to any existing sources on detections->newSources. The sources 6 // on detections->allSources are ignored. 7 bool psphotSourceStats (pmConfig *config, const pmFPAview *view, bool setWindow) 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 // loop over the available readouts 19 for (int i = 0; i < num; i++) { 20 if (!psphotSourceStatsReadout (config, view, "PSPHOT.INPUT", i, recipe, setWindow)) { 21 psError (PSPHOT_ERR_CONFIG, false, "failed to find initial detections for PSPHOT.INPUT entry %d", i); 22 return false; 23 } 24 } 25 return true; 26 } 27 28 bool psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool setWindow) { 6 29 7 30 bool status = false; … … 10 33 psTimerStart ("psphot.stats"); 11 34 12 // select the appropriate recipe information 13 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 14 assert (recipe); 35 // find the currently selected readout 36 pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest 37 psAssert (file, "missing file?"); 38 39 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); 40 psAssert (readout, "missing readout?"); 41 42 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 43 psAssert (detections, "missing detections?"); 44 45 // XXX TEST: 46 if (detections->allSources) { 47 psphotMaskCosmicRayFootprintCheck(detections->allSources); 48 } 49 if (detections->newSources) { 50 psphotMaskCosmicRayFootprintCheck(detections->newSources); 51 } 15 52 16 53 // determine the number of allowed threads … … 21 58 22 59 // determine properties (sky, moments) of initial sources 23 float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS"); 24 if (!status) return NULL; 25 60 float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS"); 61 psAssert (status, "missing SKY_OUTER_RADIUS in recipe?"); 62 63 // XXX this seems like an arbitrary number... 26 64 OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius 27 65 28 66 char *breakPt = psMetadataLookupStr (&status, recipe, "BREAK_POINT"); 29 if (!status) return NULL; 67 psAssert (status, "missing BREAK_POINT?"); 68 69 float INNER = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS"); psAssert (status, "missing SKY_INNER_RADIUS"); 70 float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); psAssert (status, "missing MOMENTS_SN_MIN"); 71 72 // bit-masks to test for good/bad pixels 73 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); 74 psAssert (maskVal, "missing MASK.PSPHOT"); 75 76 // bit-mask to mark pixels not used in analysis 77 psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); 78 psAssert (markVal, "missing MARK.PSPHOT"); 30 79 31 80 psArray *peaks = detections->peaks; 32 81 if (!peaks) { 33 82 psError(PS_ERR_UNEXPECTED_NULL, false, "No peaks found!"); 34 return NULL;83 return false; 35 84 } 36 85 37 86 // generate the array of sources, define the associated pixel 38 sources = psArrayAllocEmpty (peaks->n); 87 if (!detections->newSources) { 88 detections->newSources = psArrayAllocEmpty (peaks->n); 89 } 90 sources = detections->newSources; 91 92 // if there are no peaks, we save the empty source array and return 93 if (!peaks->n) { 94 return true; 95 } 39 96 40 97 for (int i = 0; i < peaks->n; i++) { … … 45 102 // create a new source 46 103 pmSource *source = pmSourceAlloc(); 104 source->imageID = index; 47 105 48 106 // add the peak … … 58 116 psArrayAdd (sources, 100, source); 59 117 psFree (source); 118 } 119 120 if (!strcasecmp (breakPt, "PEAKS")) { 121 psLogMsg ("psphot", PS_LOG_INFO, "%ld sources : %f sec\n", sources->n, psTimerMark ("psphot.stats")); 122 psLogMsg ("psphot", PS_LOG_INFO, "break point PEAKS, skipping MOMENTS\n"); 123 psphotVisualShowMoments (sources); 124 return true; 125 } 126 127 if (setWindow) { 128 if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) { 129 psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!"); 130 psFree(detections->newSources); 131 return false; 132 } 133 } 134 135 // if we have measured the window, we will be saving the modified version of these recipe values on readout->analysis 136 float SIGMA = psMetadataLookupF32 (&status, readout->analysis, "MOMENTS_GAUSS_SIGMA"); 137 if (!status) { 138 SIGMA = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA"); 139 } 140 float RADIUS = psMetadataLookupF32 (&status, readout->analysis, "PSF_MOMENTS_RADIUS"); 141 if (!status) { 142 RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS"); 143 } 144 145 // threaded measurement of the source magnitudes 146 int Nfail = 0; 147 int Nmoments = 0; 148 int Nfaint = 0; 149 150 // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts) 151 int Cx = 1, Cy = 1; 152 psphotChooseCellSizes (&Cx, &Cy, readout, nThreads); 153 154 psArray *cellGroups = psphotAssignSources (Cx, Cy, sources); 155 156 for (int i = 0; i < cellGroups->n; i++) { 157 158 psArray *cells = cellGroups->data[i]; 159 160 for (int j = 0; j < cells->n; j++) { 161 162 // allocate a job -- if threads are not defined, this just runs the job 163 psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS"); 164 165 psArrayAdd(job->args, 1, cells->data[j]); // sources 166 167 PS_ARRAY_ADD_SCALAR(job->args, INNER, PS_TYPE_F32); 168 PS_ARRAY_ADD_SCALAR(job->args, MIN_SN, PS_TYPE_F32); 169 PS_ARRAY_ADD_SCALAR(job->args, RADIUS, PS_TYPE_F32); 170 PS_ARRAY_ADD_SCALAR(job->args, SIGMA, PS_TYPE_F32); 171 172 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 173 PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK); 174 175 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nmoments 176 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail 177 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfaint 178 179 if (!psThreadJobAddPending(job)) { 180 psError(PS_ERR_UNKNOWN, false, "Unable to launch thread job PSPHOT_SOURCE_STATS"); 181 psFree (job); 182 psFree(detections->newSources); 183 return false; 184 } 185 psFree(job); 186 } 187 188 // wait for the threads to finish and manage results 189 if (!psThreadPoolWait (false)) { 190 psError(PS_ERR_UNKNOWN, false, "Failure in thread job PSPHOT_SOURCE_STATS"); 191 psFree(detections->newSources); 192 return false; 193 } 194 195 // we have only supplied one type of job, so we can assume the types here 196 psThreadJob *job = NULL; 197 while ((job = psThreadJobGetDone()) != NULL) { 198 if (job->args->n < 1) { 199 fprintf (stderr, "error with job\n"); 200 } else { 201 psScalar *scalar = NULL; 202 scalar = job->args->data[7]; 203 Nmoments += scalar->data.S32; 204 scalar = job->args->data[8]; 205 Nfail += scalar->data.S32; 206 scalar = job->args->data[9]; 207 Nfaint += scalar->data.S32; 208 } 209 psFree(job); 210 } 211 } 212 213 psFree (cellGroups); 214 215 psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d faint, %d failed: %f sec\n", sources->n, Nmoments, Nfaint, Nfail, psTimerMark ("psphot.stats")); 216 217 psphotVisualShowMoments (sources); 218 219 if (detections->allSources) { 220 psphotMaskCosmicRayFootprintCheck(detections->allSources); 221 } 222 if (detections->newSources) { 223 psphotMaskCosmicRayFootprintCheck(detections->newSources); 224 } 225 226 return true; 227 } 228 229 // this function is currently only called by psphotCheckExtSources 230 bool psphotSourceStatsUpdate (psArray *sources, pmConfig *config, pmReadout *readout) { 231 232 bool status = false; 233 234 psTimerStart ("psphot.stats"); 235 236 // select the appropriate recipe information 237 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 238 assert (recipe); 239 240 // determine the number of allowed threads 241 int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads 242 if (!status) { 243 nThreads = 0; 244 } 245 246 // determine properties (sky, moments) of initial sources 247 float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS"); 248 if (!status) return false; 249 250 OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius 251 252 char *breakPt = psMetadataLookupStr (&status, recipe, "BREAK_POINT"); 253 if (!status) return false; 254 255 for (int i = 0; i < sources->n; i++) { 256 257 pmSource *source = sources->data[i]; 258 if (!source->peak) continue; // XXX how can we have a peak-less source? 259 260 // allocate space for moments 261 if (!source->moments) { 262 source->moments = pmMomentsAlloc(); 263 } 264 265 // allocate image, weight, mask arrays for each peak (square of radius OUTER) 266 pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER); 267 source->peak->assigned = true; 60 268 } 61 269 … … 67 275 } 68 276 69 if (setWindow) { 70 if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) { 71 psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!"); 72 return NULL; 73 } 277 // XXX how else could we get the window size in? 278 if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) { 279 psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!"); 280 return NULL; 74 281 } 75 282 … … 94 301 psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS"); 95 302 303 // XXX: this must match the above 96 304 psArrayAdd(job->args, 1, cells->data[j]); // sources 97 305 psArrayAdd(job->args, 1, recipe); … … 148 356 149 357 psArray *sources = job->args->data[0]; 150 psMetadata *recipe = job->args->data[1]; 151 152 float INNER = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS"); 153 if (!status) return false; 154 float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); 155 if (!status) return false; 156 float RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS"); 157 if (!status) return false; 158 float SIGMA = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA"); 159 if (!status) return false; 160 161 // bit-masks to test for good/bad pixels 162 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); 163 assert (maskVal); 164 165 // bit-mask to mark pixels not used in analysis 166 psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); 167 assert (markVal); 358 359 float INNER = PS_SCALAR_VALUE(job->args->data[1],F32); 360 float MIN_SN = PS_SCALAR_VALUE(job->args->data[2],F32); 361 float RADIUS = PS_SCALAR_VALUE(job->args->data[3],F32); 362 float SIGMA = PS_SCALAR_VALUE(job->args->data[4],F32); 363 364 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[5],PS_TYPE_IMAGE_MASK_DATA); 365 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[6],PS_TYPE_IMAGE_MASK_DATA); 168 366 169 367 // maskVal is used to test for rejected pixels, and must include markVal … … 176 374 for (int i = 0; i < sources->n; i++) { 177 375 pmSource *source = sources->data[i]; 376 377 if (source->tmpFlags & PM_SOURCE_TMPF_MOMENTS_MEASURED) continue; 378 source->tmpFlags |= PM_SOURCE_TMPF_MOMENTS_MEASURED; 178 379 179 380 // skip faint sources for moments measurement … … 205 406 206 407 // measure basic source moments (no S/N clipping on input pixels) 207 status = pmSourceMoments (source, RADIUS, SIGMA, 0.0 );408 status = pmSourceMoments (source, RADIUS, SIGMA, 0.0, maskVal); 208 409 if (status) { 209 410 Nmoments ++; … … 215 416 BIG_RADIUS = PS_MIN (INNER, 3*RADIUS); 216 417 psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y); 217 status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, 0.0 );418 status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, 0.0, maskVal); 218 419 if (status) { 219 420 source->mode |= PM_SOURCE_MODE_BIG_RADIUS; … … 229 430 230 431 // change the value of a scalar on the array (wrap this and put it in psArray.h) 231 scalar = job->args->data[ 2];432 scalar = job->args->data[7]; 232 433 scalar->data.S32 = Nmoments; 233 434 234 scalar = job->args->data[ 3];435 scalar = job->args->data[8]; 235 436 scalar->data.S32 = Nfail; 236 437 237 scalar = job->args->data[ 4];438 scalar = job->args->data[9]; 238 439 scalar->data.S32 = Nfaint; 239 440 … … 242 443 243 444 // this function attempts to iteratively determine the best value for sigma of the moments weighting Gaussian 445 // this function modifies the recipe values MOMENTS_SX_MAX, MOMENTS_SY_MAX, and PSF_CLUMP_GRID_SCALE, used by pmSourcePSFClump 244 446 bool psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources) { 245 447 246 448 bool status; 247 449 248 float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); 249 if (!status) return false; 450 float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); psAssert (status, "missing MOMENTS_SN_MIN"); 451 float PSF_SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM"); psAssert (status, "missing PSF_SN_LIM"); 452 psF32 MOMENTS_AR_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_AR_MAX"); psAssert (status, "missing MOMENTS_AR_MAX"); 250 453 251 454 // XXX move this to a config file? 252 float sigma[4] = {1.0, 2.0, 3.0, 4.5}; 253 float Sout[4]; 455 # define NSIGMA 8 456 float sigma[NSIGMA] = {1.0, 2.0, 3.0, 4.5, 6.0, 9.0, 12.0, 18.0}; 457 float Sout[NSIGMA]; 254 458 255 459 // this sorts by peak->SN … … 257 461 258 462 // loop over radii: 259 for (int i = 0; i < 4; i++) {463 for (int i = 0; i < NSIGMA; i++) { 260 464 261 465 // XXX move max source number to config … … 272 476 273 477 // measure basic source moments (no S/N clipping on input pixels) 274 status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0 );478 status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0, 0xffff); 275 479 } 276 480 277 481 // choose a grid scale that is a fixed fraction of the psf sigma^2 278 psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(sigma[i]));279 psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(sigma[i]));280 psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(sigma[i]));482 float PSF_CLUMP_GRID_SCALE = 0.1*PS_SQR(sigma[i]); 483 float MOMENTS_SX_MAX = 2.0*PS_SQR(sigma[i]); 484 float MOMENTS_SY_MAX = 2.0*PS_SQR(sigma[i]); 281 485 282 486 // determine the PSF parameters from the source moment values 283 pmPSFClump psfClump = pmSourcePSFClump (NULL, sources, recipe);487 pmPSFClump psfClump = pmSourcePSFClump (NULL, NULL, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_AR_MAX); 284 488 psLogMsg ("psphot", 3, "radius %.1f, nStars: %d, nSigma: %5.2f, X, Y: %f, %f (%f, %f)\n", sigma[i], psfClump.nStars, psfClump.nSigma, psfClump.X, psfClump.Y, sqrt(psfClump.X) / sigma[i], sqrt(psfClump.Y) / sigma[i]); 285 489 … … 296 500 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY); 297 501 298 // psphotVisualPlotMoments (recipe, sources);502 psphotVisualPlotMoments (recipe, analysis, sources); 299 503 300 504 Sout[i] = sqrt(0.5*(psfClump.X + psfClump.Y)) / sigma[i]; … … 302 506 303 507 // we are looking for sigma for which Sout = 0.65 (or some other value) 304 305 508 float Sigma = NAN; 306 509 float minS = Sout[0]; 307 510 float maxS = Sout[0]; 308 for (int i = 0; i < 4; i++) {511 for (int i = 0; i < NSIGMA; i++) { 309 512 minS = PS_MIN(Sout[i], minS); 310 513 maxS = PS_MAX(Sout[i], maxS); 311 514 } 312 if (minS > 0.65) Sigma = sigma[ 3];515 if (minS > 0.65) Sigma = sigma[NSIGMA-1]; 313 516 if (maxS < 0.65) Sigma = sigma[0]; 314 517 315 for (int i = 0; i < 3; i++) { 518 for (int i = 0; i < NSIGMA - 1 && isnan(Sigma); i++) { 519 if (!isfinite(Sout[i]) || !isfinite(Sout[i+1])) continue; 316 520 if ((Sout[i] > 0.65) && (Sout[i+1] > 0.65)) continue; 317 521 if ((Sout[i] < 0.65) && (Sout[i+1] < 0.65)) continue; … … 321 525 322 526 // choose a grid scale that is a fixed fraction of the psf sigma^2 323 psMetadataAddF32( recipe, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(Sigma));324 psMetadataAddF32( recipe, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));325 psMetadataAddF32( recipe, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));326 psMetadataAddF32( recipe, PS_LIST_TAIL, "MOMENTS_GAUSS_SIGMA", PS_META_REPLACE, "moments limit", Sigma);327 psMetadataAddF32( recipe, PS_LIST_TAIL, "PSF_MOMENTS_RADIUS", PS_META_REPLACE, "moments limit", 4.0*Sigma);527 psMetadataAddF32(analysis, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(Sigma)); 528 psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma)); 529 psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma)); 530 psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_GAUSS_SIGMA", PS_META_REPLACE, "moments limit", Sigma); 531 psMetadataAddF32(analysis, PS_LIST_TAIL, "PSF_MOMENTS_RADIUS", PS_META_REPLACE, "moments limit", 4.0*Sigma); 328 532 329 533 psLogMsg ("psphot", 3, "using window function with sigma = %f\n", Sigma); 330 534 return true; 331 535 } 536 537 // if we use the footprints, the output peaks list contains both old and new peaks, 538 // otherwise it only contains the new peaks. 539
Note:
See TracChangeset
for help on using the changeset viewer.
