- Timestamp:
- Mar 5, 2012, 5:19:48 PM (14 years ago)
- Location:
- branches/meh_branches/ppstack_test
- Files:
-
- 4 edited
-
. (modified) (1 prop)
-
psphot (modified) (1 prop)
-
psphot/src (modified) (2 props)
-
psphot/src/psphotRadialApertures.c (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/meh_branches/ppstack_test
- Property svn:mergeinfo changed
-
branches/meh_branches/ppstack_test/psphot
- Property svn:mergeinfo changed
-
branches/meh_branches/ppstack_test/psphot/src
- Property svn:ignore
-
old new 22 22 psphotMakePSF 23 23 psphotStack 24 psphotModelTest
-
- Property svn:mergeinfo set to
- Property svn:ignore
-
branches/meh_branches/ppstack_test/psphot/src/psphotRadialApertures.c
r31452 r33415 3 3 bool psphotRadialAperturesSortFlux (psVector *radius, psVector *pixFlux, psVector *pixVar); 4 4 5 // this function measures the radial aperture fluxes for the set of readouts. this function 6 // may be called multiple times, presumably for different versions of PSF-matched or unmatched images. 7 5 8 // for now, let's store the detections on the readout->analysis for each readout 6 bool psphotRadialApertures (pmConfig *config, const pmFPAview *view, const char *filerule )9 bool psphotRadialApertures (pmConfig *config, const pmFPAview *view, const char *filerule, int entry) 7 10 { 8 11 bool status = true; 12 13 fprintf (stdout, "\n"); 14 psLogMsg ("psphot", PS_LOG_INFO, "--- psphot Radial Apertures ---"); 9 15 10 16 // select the appropriate recipe information … … 20 26 int num = psphotFileruleCount(config, filerule); 21 27 28 // skip the chisq image (optionally?) 29 int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM"); 30 if (!status) chisqNum = -1; 31 22 32 // loop over the available readouts 23 33 for (int i = 0; i < num; i++) { 24 if (!psphotRadialAperturesReadout (config, view, filerule, i, recipe)) { 34 if (i == chisqNum) continue; // skip chisq image 35 36 if (!psphotRadialAperturesReadout (config, view, filerule, i, recipe, entry)) { 25 37 psError (PSPHOT_ERR_CONFIG, false, "failed on measure extended source aperture-like parameters for %s entry %d", filerule, i); 26 38 return false; … … 30 42 } 31 43 44 // these values are used by all threads repeatedly (and are not modified) 45 static psVector *aperRadii = NULL; 46 static psVector *aperRadii2 = NULL; 47 static float outerRadius = NAN; 48 static float SN_LIM = NAN; 49 static psImageMaskType maskVal = 0; 50 32 51 // aperture-like measurements for extended sources 33 52 // flux in simple, circular apertures 34 bool psphotRadialAperturesReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) { 53 // 'entry' tells us which of the matched-PSF images we are working on (0 == unmatched image, also non-stack psphot) 54 bool psphotRadialAperturesReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, int entry) { 35 55 36 56 bool status; … … 63 83 } 64 84 65 // radMax stores the upper bounds of the annuli 85 // determine the number of allowed threads 86 int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads 87 if (!status) { 88 nThreads = 0; 89 } 90 91 // aperRadii stores the upper bounds of the annuli 66 92 // XXX keep the same name here as for the petrosian / elliptical apertures? 67 psVector *radMax = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER"); 68 psAssert (radMax, "annular bins (RADIAL.ANNULAR.BINS.UPPER) are not defined in the recipe"); 69 psAssert (radMax->n, "no valid annular bins (RADIAL.ANNULAR.BINS.UPPER) are define"); 70 float outerRadius = radMax->data.F32[radMax->n - 1]; 93 aperRadii = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER"); 94 psAssert (aperRadii, "annular bins (RADIAL.ANNULAR.BINS.UPPER) are not defined in the recipe"); 95 psAssert (aperRadii->n, "no valid annular bins (RADIAL.ANNULAR.BINS.UPPER) are define"); 96 97 outerRadius = aperRadii->data.F32[aperRadii->n - 1]; 98 99 // save the R^2 values as well for quicker comparison 100 aperRadii2 = psVectorAlloc(aperRadii->n, PS_TYPE_F32); 101 for (int i = 0; i < aperRadii->n; i++) { 102 aperRadii2->data.F32[i] = PS_SQR(aperRadii->data.F32[i]); 103 } 71 104 72 105 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 73 psImageMaskTypemaskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels106 maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 74 107 assert (maskVal); 75 108 76 109 // S/N limit to perform full non-linear fits 77 floatSN_LIM = psMetadataLookupF32 (&status, recipe, "RADIAL_APERTURES_SN_LIM");110 SN_LIM = psMetadataLookupF32 (&status, recipe, "RADIAL_APERTURES_SN_LIM"); 78 111 79 112 // source analysis is done in S/N order (brightest first) … … 81 114 sources = psArraySort (sources, pmSourceSortByFlux); 82 115 116 // XXX make this consistent with entry 0 == unmatched 117 int nEntry = 1; 118 psVector *fwhmValues = psMetadataLookupVector(&status, readout->analysis, "STACK.PSF.FWHM.VALUES"); 119 if (fwhmValues) { 120 psAssert (entry < fwhmValues->n, "inconsistent matched-PSF entry"); 121 nEntry = fwhmValues->n; 122 } 123 if (entry > 0) { 124 psLogMsg ("psphot", PS_LOG_DETAIL, "Radial Apertures for matched image %s : PSF FWHM = %f pixels\n", file->name, fwhmValues->data.F32[entry]); 125 } else { 126 psLogMsg ("psphot", PS_LOG_DETAIL, "Radial Apertures for unmatched image %s\n", file->name); 127 } 128 83 129 // option to limit analysis to a specific region 84 130 char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION"); 85 psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region)); 86 if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined"); 131 psRegion *AnalysisRegion = psRegionAlloc(0,0,0,0); 132 *AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region)); 133 if (psRegionIsNaN (*AnalysisRegion)) psAbort("analysis region mis-defined"); 134 135 // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts) 136 int Cx = 1, Cy = 1; 137 psphotChooseCellSizes (&Cx, &Cy, readout, nThreads); 138 139 psArray *cellGroups = psphotAssignSources (Cx, Cy, sources); 140 141 for (int i = 0; i < cellGroups->n; i++) { 142 143 psArray *cells = cellGroups->data[i]; 144 145 for (int j = 0; j < cells->n; j++) { 146 147 // allocate a job -- if threads are not defined, this just runs the job 148 psThreadJob *job = psThreadJobAlloc ("PSPHOT_RADIAL_APERTURES"); 149 150 psArrayAdd(job->args, 1, readout); 151 psArrayAdd(job->args, 1, cells->data[j]); // sources 152 psArrayAdd(job->args, 1, AnalysisRegion); 153 PS_ARRAY_ADD_SCALAR(job->args, entry, PS_TYPE_S32); 154 PS_ARRAY_ADD_SCALAR(job->args, nEntry, PS_TYPE_S32); 155 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nradial 156 157 // set this to 0 to run without threading 158 # if (1) 159 if (!psThreadJobAddPending(job)) { 160 psError(PS_ERR_UNKNOWN, false, "Unable to guess model."); 161 psFree(AnalysisRegion); 162 return false; 163 } 164 # else 165 if (!psphotRadialApertures_Threaded(job)) { 166 psError(PS_ERR_UNKNOWN, false, "Unable to guess model."); 167 psFree(AnalysisRegion); 168 return false; 169 } 170 psScalar *scalar = NULL; 171 scalar = job->args->data[5]; 172 Nradial += scalar->data.S32; 173 psFree(job); 174 # endif 175 } 176 177 // wait for the threads to finish and manage results 178 if (!psThreadPoolWait (false, true)) { 179 psError(PS_ERR_UNKNOWN, false, "Unable to guess model."); 180 psFree(AnalysisRegion); 181 return false; 182 } 183 184 // we have only supplied one type of job, so we can assume the types here 185 psThreadJob *job = NULL; 186 while ((job = psThreadJobGetDone()) != NULL) { 187 if (job->args->n < 1) { 188 fprintf (stderr, "error with job\n"); 189 } else { 190 psScalar *scalar = NULL; 191 scalar = job->args->data[5]; 192 Nradial += scalar->data.S32; 193 } 194 psFree(job); 195 } 196 } 197 psFree (cellGroups); 198 psFree(AnalysisRegion); 199 psFree (aperRadii2); 200 201 psLogMsg ("psphot", PS_LOG_WARN, "radial source apertures: %f sec for %d objects\n", psTimerMark ("psphot.radial"), Nradial); 202 return true; 203 } 204 205 bool psphotRadialApertures_Threaded (psThreadJob *job) { 206 207 int Nradial = 0; 208 209 // arguments: readout, sources, models, region, psfSize, maskVal, markVal 210 pmReadout *readout = job->args->data[0]; 211 psArray *sources = job->args->data[1]; 212 psRegion *region = job->args->data[2]; 213 int entry = PS_SCALAR_VALUE(job->args->data[3],S32); // which psf-matched image are we working on? (0 == unmatched) 214 int nEntry = PS_SCALAR_VALUE(job->args->data[4],S32); // total number of psf-matched images + 1 unmatched 215 216 // storage for the derived pixel values (these are passed into psphotRadialApertureSource) 217 psVector *pixRadius2 = psVectorAllocEmpty(100, PS_TYPE_F32); 218 psVector *pixFlux = psVectorAllocEmpty(100, PS_TYPE_F32); 219 psVector *pixVar = psVectorAllocEmpty(100, PS_TYPE_F32); 87 220 88 221 // choose the sources of interest … … 90 223 91 224 pmSource *source = sources->data[i]; 225 226 // if we have checked the source validity on the basis of the object set, then 227 // we either skip these tests below or we skip the source completely 228 if (source->tmpFlags & PM_SOURCE_TMPF_RADIAL_SKIP) continue; 229 if (source->tmpFlags & PM_SOURCE_TMPF_RADIAL_KEEP) goto keepSource; 92 230 93 231 // skip PSF-like and non-astronomical objects … … 104 242 105 243 // limit selection by analysis region 106 if (source->peak->x < AnalysisRegion.x0) continue; 107 if (source->peak->y < AnalysisRegion.y0) continue; 108 if (source->peak->x > AnalysisRegion.x1) continue; 109 if (source->peak->y > AnalysisRegion.y1) continue; 244 if (source->peak->x < region->x0) continue; 245 if (source->peak->y < region->y0) continue; 246 if (source->peak->x > region->x1) continue; 247 if (source->peak->y > region->y1) continue; 248 249 keepSource: 110 250 111 251 // allocate pmSourceExtendedParameters, if not already defined 112 if (!source->radialAper) { 113 source->radialAper = psArrayAlloc(1); 252 // XXX check that nPSFsizes is consistent with targets 253 if (source->parent) { 254 if (!source->parent->radialAper) { 255 source->parent->radialAper = psArrayAlloc(nEntry); 256 } 257 } else { 258 if (!source->radialAper) { 259 source->radialAper = psArrayAlloc(nEntry); 260 } 114 261 } 115 262 … … 119 266 } 120 267 121 // we need to change the view for the radial aperture analysis, but we want to recover exactly122 // the original view; the following elements get destroyed by pmSourceRedefinePixels so save them:123 psImage *oldMaskObj = psMemIncrRefCounter(source->maskObj);124 psImage *oldModelFlux = psMemIncrRefCounter(source->modelFlux);125 psImage *oldPSFimage = psMemIncrRefCounter(source->psfImage);126 psRegion oldRegion = source->region;127 128 268 Nradial ++; 129 269 130 // force source image to be a bit larger... 131 pmSourceRedefinePixels (source, readout, source->peak->xf, source->peak->yf, outerRadius + 2); 132 133 if (!psphotRadialApertureSource (source, recipe, maskVal, radMax, 0)) { 270 if (!psphotRadialApertureSource (source, readout, entry, pixRadius2, pixFlux, pixVar)) { 134 271 psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 135 272 } else { … … 137 274 } 138 275 139 pmSourceRedefinePixelsByRegion (source, readout, oldRegion);140 psFree(source->maskObj); source->maskObj = oldMaskObj;141 psFree(source->modelFlux); source->modelFlux = oldModelFlux;142 psFree(source->psfImage); source->psfImage = oldPSFimage;143 144 276 // re-subtract the object, leave local sky 145 277 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 146 278 } 147 148 psLogMsg ("psphot", PS_LOG_INFO, "radial source apertures: %f sec for %d objects\n", psTimerMark ("psphot.radial"), Nradial); 279 psScalar *scalar = job->args->data[5]; 280 scalar->data.S32 = Nradial; 281 282 psFree (pixRadius2); 283 psFree (pixFlux); 284 psFree (pixVar); 285 149 286 return true; 150 287 } 151 288 152 bool psphotRadialApertureSource (pmSource *source, p sMetadata *recipe, psImageMaskType maskVal, const psVector *aperRadii, int entry) {153 289 bool psphotRadialApertureSource (pmSource *source, pmReadout *readout, int entry, psVector *pixRadius2, psVector *pixFlux, psVector *pixVar) { 290 154 291 // if we are a child source, save the results to the parent source radial aperture array 155 292 psArray *radialAperSet = source->radialAper; … … 163 300 radialAperSet->data[entry] = radialAper; 164 301 165 // storage for the derived pixel values 166 psVector *pixRadius2 = psVectorAllocEmpty(100, PS_TYPE_F32); 167 psVector *pixFlux = psVectorAllocEmpty(100, PS_TYPE_F32); 168 psVector *pixVar = psVectorAllocEmpty(100, PS_TYPE_F32); 302 // find the largest aperture of interest (use only apertures with inner radii <= 303 // source->skyRadius) 304 int lastAp = aperRadii->n; 305 for (int i = 0; i < aperRadii->n; i++) { 306 if (aperRadii->data.F32[i] < source->skyRadius) continue; 307 lastAp = i + 1; 308 break; 309 } 169 310 170 311 // outer-most radius for initial truncation 171 float Rmax = aperRadii->data.F32[ aperRadii->n- 1];312 float Rmax = aperRadii->data.F32[lastAp - 1]; 172 313 float Rmax2 = PS_SQR(Rmax); 173 314 174 // store the R^2 values for the apertures 175 psVector *aperRadii2 = psVectorAlloc(aperRadii->n, PS_TYPE_F32); 176 for (int i = 0; i < aperRadii->n; i++) { 177 aperRadii2->data.F32[i] = PS_SQR(aperRadii->data.F32[i]); 178 } 315 // in this function, the operatins are relative to the full image (readout->image, etc) 179 316 180 317 float xCM = NAN, yCM = NAN; 181 318 if (pmSourcePositionUseMoments(source)) { 182 xCM = source->moments->Mx - 0.5 - source->pixels->col0; // coord of peak in subimage183 yCM = source->moments->My - 0.5 - source->pixels->row0; // coord of peak in subimage319 xCM = source->moments->Mx; // index coord of peak in readout 320 yCM = source->moments->My; // index coord of peak in readout 184 321 } else { 185 xCM = source->peak->xf - 0.5 - source->pixels->col0; // coord of peak in subimage 186 yCM = source->peak->yf - 0.5 - source->pixels->row0; // coord of peak in subimage 187 } 322 xCM = source->peak->xf; // index coord of peak in readout 323 yCM = source->peak->yf; // index coord of peak in readout 324 } 325 326 int Nx = readout->image->numCols; 327 int Ny = readout->image->numRows; 328 329 pixRadius2->n = 0; 330 pixFlux->n = 0; 331 pixVar->n = 0; 188 332 189 333 // one pass through the pixels to select the valid pixels and calculate R^2 190 for (int iy = 0; iy < source->pixels->numRows; iy++) { 191 192 float yDiff = iy - yCM; 193 if (fabs(yDiff) > Rmax) continue; 194 195 float *vPix = source->pixels->data.F32[iy]; 196 float *vWgt = source->variance->data.F32[iy]; 197 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy]; 198 199 for (int ix = 0; ix < source->pixels->numCols; ix++, vPix++, vWgt++) { 200 201 if (vMsk) { 202 if (*vMsk & maskVal) { 203 vMsk++; 204 continue; 205 } 206 vMsk++; 207 } 208 if (isnan(*vPix)) continue; 209 210 float xDiff = ix - xCM; 211 if (fabs(xDiff) > Rmax) continue; 334 for (int iy = -Rmax; iy < Rmax + 1; iy++) { 335 336 float yDiff = iy + 0.5 + yCM; // y-coordinate at this offse 337 int yPix = (int) yDiff; 338 339 if (yPix < 0) continue; 340 if (yPix > Ny - 1) continue; 341 if (fabs(iy) > Rmax) continue; 342 343 float *vPix = readout->image->data.F32[yPix]; 344 float *vWgt = readout->variance->data.F32[yPix]; 345 psImageMaskType *vMsk = readout->mask->data.PS_TYPE_IMAGE_MASK_DATA[yPix]; 346 347 for (int ix = -Rmax; ix < Rmax + 1; ix++) { 348 349 float xDiff = ix + 0.5 + xCM; // x-coordinate at this offse 350 int xPix = (int) xDiff; 351 352 if (xPix < 0) continue; 353 if (xPix > Nx - 1) continue; 354 if (fabs(ix) > Rmax) continue; 355 356 if (vMsk[xPix] & maskVal) continue; 357 if (isnan(vPix[xPix])) continue; 212 358 213 359 // radius is just a function of (xDiff, yDiff) 214 float r2 = PS_SQR( xDiff) + PS_SQR(yDiff);360 float r2 = PS_SQR(ix) + PS_SQR(iy); 215 361 if (r2 > Rmax2) continue; 216 362 217 363 psVectorAppend(pixRadius2, r2); 218 psVectorAppend(pixFlux, *vPix);219 psVectorAppend(pixVar, *vWgt);364 psVectorAppend(pixFlux, vPix[xPix]); 365 psVectorAppend(pixVar, vWgt[xPix]); 220 366 } 221 367 } … … 226 372 psVector *fill = psVectorAlloc(aperRadii->n, PS_TYPE_F32); // surface brightness of radial bin 227 373 374 // init the apertures of interest to 0.0, the rest go to NAN 228 375 psVectorInit (flux, 0.0); 229 376 psVectorInit (fluxStd, 0.0); 230 377 psVectorInit (fluxErr, 0.0); 231 378 psVectorInit (fill, 0.0); 379 for (int i = lastAp; i < flux->n; i++) { 380 flux->data.F32[i] = NAN; 381 fluxStd->data.F32[i] = NAN; 382 fluxErr->data.F32[i] = NAN; 383 fill->data.F32[i] = NAN; 384 } 232 385 233 386 float *rPix2 = pixRadius2->data.F32; … … 236 389 int j = 0; 237 390 float *aRad2 = aperRadii2->data.F32; 238 for (; (*aRad2 < *rPix2) && (j < aperRadii2->n); j++, aRad2++); 239 for (; j < aperRadii2->n; j++, aRad2++) { 391 for (; (*aRad2 < *rPix2) && (j < lastAp); j++, aRad2++); 392 393 // XXX I can speed this up by only saving this single aperture 394 for (; j < lastAp; j++, aRad2++) { 240 395 flux->data.F32[j] += pixFlux->data.F32[i]; 241 396 fluxStd->data.F32[j] += PS_SQR(pixFlux->data.F32[i]); … … 249 404 2) the fractional fill factor (count of valid pixels / effective area of the aperture 250 405 3) the error on the flux within that aperture 251 */252 253 for (int i = 0; i < flux->n; i++) {406 */ 407 408 for (int i = 0; i < lastAp; i++) { 254 409 // calculate the total flux for bin 'nOut' 255 410 float Area = M_PI*aperRadii2->data.F32[i]; … … 261 416 // XXX report the total flux or the mask-corrected flux? 262 417 // flux->data.F32[i] = SBmean * Area; 263 // fluxErr->data.F32[i] = sqrt(fluxErr->data.F32[i]) * Area / nPix;418 // fluxErr->data.F32[i] = sqrt(fluxErr->data.F32[i]) * Area / Pinx; 264 419 265 420 fluxErr->data.F32[i] = sqrt(fluxErr->data.F32[i]); … … 271 426 } 272 427 428 # if (1) 273 429 radialAper->flux = flux; 274 430 radialAper->fluxStdev = fluxStd; 275 431 radialAper->fluxErr = fluxErr; 276 432 radialAper->fill = fill; 277 278 psFree (aperRadii2); 279 psFree (pixRadius2); 280 psFree (pixFlux); 281 psFree (pixVar); 433 # else 434 // XXX TEST 435 psFree(flux); 436 psFree(fluxStd); 437 psFree(fluxErr); 438 psFree(fill); 439 # endif 282 440 283 441 return true; 284 442 } 443 444 /*** below is a test to use a sort to speed this up, not very successfully ***/ 285 445 286 446 static int nCalls = 0; … … 373 533 // *** pmSourceRadialProfileSortPair is a utility function for sorting a pair of vectors 374 534 # define COMPARE_VECT(A,B) (radius->data.F32[A] < radius->data.F32[B]) 375 # define SWAP_VECT(TYPE,A,B) { \376 float tmp;\377 if (A != B) {\378 tmp = radius->data.F32[A];\379 radius->data.F32[A] = radius->data.F32[B];\380 radius->data.F32[B] = tmp;\381 tmp = pixFlux->data.F32[A];\382 pixFlux->data.F32[A] = pixFlux->data.F32[B];\383 pixFlux->data.F32[B] = tmp;\384 tmp = pixVar->data.F32[A];\385 pixVar->data.F32[A] = pixVar->data.F32[B];\386 pixVar->data.F32[B] = tmp;\387 }\388 }535 # define SWAP_VECT(TYPE,A,B) { \ 536 float tmp; \ 537 if (A != B) { \ 538 tmp = radius->data.F32[A]; \ 539 radius->data.F32[A] = radius->data.F32[B]; \ 540 radius->data.F32[B] = tmp; \ 541 tmp = pixFlux->data.F32[A]; \ 542 pixFlux->data.F32[A] = pixFlux->data.F32[B]; \ 543 pixFlux->data.F32[B] = tmp; \ 544 tmp = pixVar->data.F32[A]; \ 545 pixVar->data.F32[A] = pixVar->data.F32[B]; \ 546 pixVar->data.F32[B] = tmp; \ 547 } \ 548 } 389 549 390 550 bool psphotRadialAperturesSortFlux (psVector *radius, psVector *pixFlux, psVector *pixVar) {
Note:
See TracChangeset
for help on using the changeset viewer.
